-
Notifications
You must be signed in to change notification settings - Fork 8
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].type
When 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:123
And 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
%20
or 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,3
Note that if your text-values contain commas, those need to be encoded as %2C
, to avoid being mistaken for
value separators.