-
Notifications
You must be signed in to change notification settings - Fork 9
FAQ
- How to use special symbols for user name or password?
- Is there a simpler way to access the first host name + port?
- How to get the full host name properly?
- How to use a file path in URL directly?
- How can I specify a Unix-socket host?
- How to access user name + password as URL-encoded?
- Can I pass in a complex type as a URL parameter?
- How to pass arrays of values?
User name, password, path or parameters - all need to be URL-encoded. When in doubt, just run this:
console.log(encodeURIComponent('my-password'));Some popular special symbols that need to be encoded:
-
#=%23 -
@=%40 -
%=%25 -
^=%5E -
?=%3F -
+=%2B -
==%3D -
,=%2C -
/=%2F -
<=%3C -
>=%3E -
|=%7C
Other special symbols, such as ~ or $, for example, can be, but do not need to be encoded.
Note that all non-Latin letters need to be encoded.
The library supports host, hostname, port + type for that, as documented within Virtual Properties.
// when supporting multiple hosts:
const host = cs.hosts?.[0].toString();
const hostname = cs.hosts?.[0].name;
const port = cs.hosts?.[0].port;
const type = cs.hosts?.[0].type;
// when supporting only one host, the above code can be simplified to this:
const {host} = cs; // = cs.hosts?.[0].toString()
const {hostname} = cs; // = cs.hosts?.[0].name
const {port} = cs; // = cs.hosts?.[0].port
const {type} = cs; // = cs.hosts?.[0].typeWhen hosts is set, each element in the array is an object that has method toString, to generate the full host name:
const cs = new ConnectionString('test://first,second:123');
const firstHost = cs.hosts?.[0].toString(); // = first = cs.host
const secondHost = cs.hosts?.[1].toString(); // = second:123And for the first host, there is even simpler approach - property host.
Do not use something like ${cs.hostname}:${cs.port}, which would incorrectly produce first:undefined.
See also the encoding options that method toString can accept.
If your protocol allows an alternative syntax of a file path, in place of regular connection details,
the recommended approach is to make the distinction via an optional extension (sub-protocol), like -file,
for example, and then use the path section of the URL for the file path:
const cs = new ConnectionString('protocol-file:///some/file/path/file-name.txt');
// cs.protocol = 'protocol-file'
const [protocol, ext] = cs.protocol?.split('-') ?? []; // split protocol from extension
if(ext === 'file') {
console.log(cs.path?.join('/'));
//=> some/file/path/file-name.txt
}And it will work the same for a relative path:
const cs = new ConnectionString('protocol-file:///../..some/file/path/file-name.txt');
console.log(cs.path?.join('/'));
//=> ../..some/file/path/file-name.txt- Protocol can also contain
+,:and.as alternative separators. - Any space in the file path must be encoded either as
%20or as+.
Any host name that either ends with .sock or contains /, after decoding, is recognized as a Unix socket,
with the host's type property set to socket after parsing.
Note that in a socket name inside URL, every symbol / must be encoded as %2F.
// cs - our ConnectionString
// check if the first host is a Unix socket:
const isSocket = cs.type === HostType.socket; // checking type of the first host
// full syntax:
// const isSocket = cs.hosts?.[0].type === HostType.socket;
// or you can compare it to a string:
const isSocket = cs.type === 'socket';
// full syntax:
// const isSocket = cs.hosts?.[0].type === 'socket';Q: The type of server that I'm using, natively supports URL-encoded user and password, so I don't want those decoded, I want them exactly as they are in the connection string. How can I do this?
A: URL encoding/decoding is a symmetric operation, i.e. you can simply re-encode those parameters when needed, using the global encodeURIComponent function:
const cs = new ConnectionString(/* your connection string here */);
const encodedUser = cs.user ? encodeURIComponent(cs.user) : '';
const encodedPassword = cs.password ? encodeURIComponent(cs.password) : '';Alternatively, you can double-encode those, and then no extra work will be needed.
Yes, you can pass in anything, but after parsing such value will be a string, so you need to apply JSON.parse to it, as shown in the example below.
import {ConnectionString} from 'connection-string';
const s1 = new ConnectionString('test://', {
params: {
// passing in a complex value:
value: [123, true, 'hello', {hi: 'there'}]
}
});
const connection = s1.toString();
//=> test://?value=123,true,hello,%7B%22hi%22%3A%22there%22%7D
// the reverse operation:
const s2 = new ConnectionString(connection);
// parsing all the values to their original type:
s2.params.value[0] = Number(s2.params.value[0]); // for number
s2.params.value[1] = Boolean(s2.params.value[1]); // for boolean
s2.params.value[3] = JSON.parse(s2.params.value[3]); // for JSON-object
console.log(s2.params.value);
//=> [123, true, 'hello', {hi: 'there'}]The library supports standard comma-separated list of values that you can assign to a parameter, which automatically turns the property into an array of the corresponding values:
const cs = new ConnectionString('?val=one,two');
//=> { params: { val: [ 'one', 'two' ] } }And it also supports repeated-parameter syntax, accumulating all values into parameter-array:
const cs = new ConnectionString('?val=one,two&val=three,four');
//=> { params: { val: [ 'one', 'two', 'three', 'four' ] } }The syntax is symmetric, which means that setting params: {val: [1, 2, 3]} in the connection object will serialize it
into a comma-separated list:
const cs = new ConnectionString('', {
params: {
val: [1, 2, 3]
}
});
console.log(cs.toString());
//=> ?val=1,2,3Note that if your text-values contain commas, those need to be encoded as %2C, to avoid being mistaken for
value separators.