Skip to content

Commit 5688648

Browse files
authored
Merge pull request #408 from ClickHouse/1.11.1
Release 1.11.1
2 parents b0502be + c3a22c3 commit 5688648

File tree

7 files changed

+64
-13
lines changed

7 files changed

+64
-13
lines changed

Diff for: CHANGELOG.md

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# 1.11.1 (Common, Node.js, Web)
2+
3+
## Bug fixes
4+
5+
- Fixed an issue with URLEncoded special characters in the URL configuration for username or password. ([#407](https://github.com/ClickHouse/clickhouse-js/issues/407))
6+
7+
## Improvements
8+
9+
- Added support for streaming on 32-bit platforms. ([#403](https://github.com/ClickHouse/clickhouse-js/pull/403), [shevchenkonik](https://github.com/shevchenkonik))
10+
111
# 1.11.0 (Common, Node.js, Web)
212

313
## New features

Diff for: packages/client-common/src/config.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -320,12 +320,12 @@ export function loadConfigOptionsFromURL(
320320
handleExtraURLParams: HandleImplSpecificURLParams | null,
321321
): [URL, BaseClickHouseClientConfigOptions] {
322322
let config: BaseClickHouseClientConfigOptions = {}
323-
if (url.username.trim() !== '') {
324-
config.username = url.username
323+
// trim is not needed, cause space is not allowed in the URL basic auth and should be encoded as %20
324+
if (url.username !== '') {
325+
config.username = decodeURIComponent(url.username)
325326
}
326-
// no trim for password
327327
if (url.password !== '') {
328-
config.password = url.password
328+
config.password = decodeURIComponent(url.password)
329329
}
330330
if (url.pathname.trim().length > 1) {
331331
config.database = url.pathname.slice(1)

Diff for: packages/client-common/src/version.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export default '1.11.0'
1+
export default '1.11.1'

Diff for: packages/client-node/__tests__/unit/node_client.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,39 @@ describe('[Node.js] createClient', () => {
108108
} satisfies CreateConnectionParams)
109109
expect(createConnectionStub).toHaveBeenCalledTimes(1)
110110
})
111+
112+
it('should parse username and password with special characters', async () => {
113+
const username = '! $'
114+
const password = '(#%%@) '
115+
const auth = `${encodeURIComponent(username)}:${encodeURIComponent(password)}`
116+
createClient({
117+
url:
118+
`https://${auth}@my.host:8443/analytics?` +
119+
[
120+
// base config parameters
121+
'application=my_app',
122+
'pathname=my_proxy',
123+
'request_timeout=42000',
124+
'http_header_X-ClickHouse-Auth=secret_token',
125+
// Node.js specific
126+
'keep_alive_idle_socket_ttl=1500',
127+
].join('&'),
128+
})
129+
expect(createConnectionStub).toHaveBeenCalledWith({
130+
connection_params: {
131+
...params,
132+
url: new URL('https://my.host:8443/my_proxy'),
133+
auth: { username, password, type: 'Credentials' },
134+
},
135+
tls: undefined,
136+
keep_alive: {
137+
enabled: true,
138+
idle_socket_ttl: 1500,
139+
},
140+
set_basic_auth_header: true,
141+
http_agent: undefined,
142+
} satisfies CreateConnectionParams)
143+
expect(createConnectionStub).toHaveBeenCalledTimes(1)
144+
})
111145
})
112146
})

Diff for: packages/client-node/src/utils/stream.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import Stream from 'stream'
2+
import { constants } from 'buffer'
23

3-
// See https://github.com/v8/v8/commit/ea56bf5513d0cbd2a35a9035c5c2996272b8b728
4-
const MaxStringLength = Math.pow(2, 29) - 24
4+
const { MAX_STRING_LENGTH } = constants
55

6-
export function isStream(obj: any): obj is Stream.Readable {
7-
return obj !== null && typeof obj.pipe === 'function'
6+
export function isStream(obj: unknown): obj is Stream.Readable {
7+
return (
8+
typeof obj === 'object' &&
9+
obj !== null &&
10+
'pipe' in obj &&
11+
typeof obj.pipe === 'function' &&
12+
'on' in obj &&
13+
typeof obj.on === 'function'
14+
)
815
}
916

1017
export async function getAsText(stream: Stream.Readable): Promise<string> {
@@ -13,10 +20,10 @@ export async function getAsText(stream: Stream.Readable): Promise<string> {
1320
const textDecoder = new TextDecoder()
1421
for await (const chunk of stream) {
1522
const decoded = textDecoder.decode(chunk, { stream: true })
16-
if (decoded.length + text.length > MaxStringLength) {
23+
if (decoded.length + text.length > MAX_STRING_LENGTH) {
1724
throw new Error(
1825
'The response length exceeds the maximum allowed size of V8 String: ' +
19-
`${MaxStringLength}; consider limiting the amount of requested rows.`,
26+
`${MAX_STRING_LENGTH}; consider limiting the amount of requested rows.`,
2027
)
2128
}
2229
text += decoded

Diff for: packages/client-node/src/version.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export default '1.11.0'
1+
export default '1.11.1'

Diff for: packages/client-web/src/version.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export default '1.11.0'
1+
export default '1.11.1'

0 commit comments

Comments
 (0)