Skip to content

Commit 19442b0

Browse files
authored
Fix: properly encode path segments in getUrl (#1893)
* fix: properly encode path segments in getUrl * add changelog entry
1 parent 733e462 commit 19442b0

2 files changed

Lines changed: 18 additions & 17 deletions

File tree

cli/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
This change log covers only the command line interface (CLI) of Open VSX.
44

5+
### [next] (unreleased)
6+
7+
### Fixes
8+
9+
- Properly encode path segments in getUrl method ([#1893](https://github.com/eclipse/openvsx/pull/1893))
10+
511
### [v1.0.0] (28/05/2026)
612

713
#### Dependencies

cli/src/registry.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
import * as http from 'http';
1212
import * as fs from 'fs';
13-
import * as querystring from 'querystring';
1413
import * as followRedirects from 'follow-redirects';
1514
import { RegistryOptions } from './registry-options';
1615
import { rejectError, statusError } from './util';
@@ -34,6 +33,7 @@ export class Registry {
3433
this.url = options.registryUrl;
3534
else
3635
this.url = DEFAULT_URL;
36+
3737
this.maxNamespaceSize = options.maxNamespaceSize ?? DEFAULT_NAMESPACE_SIZE;
3838
this.maxPublishSize = options.maxPublishSize ?? DEFAULT_PUBLISH_SIZE;
3939
this.username = options.username;
@@ -47,8 +47,7 @@ export class Registry {
4747

4848
createNamespace(name: string, pat: string): Promise<Response> {
4949
try {
50-
const query: { [key: string]: string } = { token: pat };
51-
const url = this.getUrl('api/-/namespace/create', query);
50+
const url = this.getUrl(['api', '-', 'namespace', 'create'], { token: pat });
5251
const namespace = { name };
5352
return this.post(JSON.stringify(namespace), url, {
5453
'Content-Type': 'application/json'
@@ -60,17 +59,15 @@ export class Registry {
6059

6160
verifyPat(namespace: string, pat: string): Promise<Response> {
6261
try {
63-
const query: { [key: string]: string } = { token: pat };
64-
return this.getJson(this.getUrl(`api/${namespace}/verify-pat`, query));
62+
return this.getJson(this.getUrl(['api', namespace, 'verify-pat'], { token: pat }));
6563
} catch (err) {
6664
return rejectError(err);
6765
}
6866
}
6967

7068
publish(file: string, pat: string): Promise<Extension> {
7169
try {
72-
const query: { [key: string]: string } = { token: pat };
73-
const url = this.getUrl('api/-/publish', query);
70+
const url = this.getUrl(['api', '-', 'publish'], { token: pat });
7471
return this.postFile(file, url, {
7572
'Content-Type': 'application/octet-stream'
7673
}, this.maxPublishSize);
@@ -81,11 +78,11 @@ export class Registry {
8178

8279
getMetadata(namespace: string, extension: string, target?: string): Promise<Extension> {
8380
try {
84-
let path = `api/${encodeURIComponent(namespace)}/${encodeURIComponent(extension)}`;
81+
const segments = ['api', namespace, extension];
8582
if (target) {
86-
path += `/${encodeURIComponent(target)}`;
83+
segments.push(target);
8784
}
88-
return this.getJson(this.getUrl(path));
85+
return this.getJson(this.getUrl(segments));
8986
} catch (err) {
9087
return rejectError(err);
9188
}
@@ -157,15 +154,13 @@ export class Registry {
157154
});
158155
}
159156

160-
private getUrl(path: string, query?: { [key: string]: string }): URL {
157+
private getUrl(segments: string[], query?: Record<string, string>): URL {
161158
const url = new URL(this.url);
162-
if (url.pathname.endsWith("/")) {
163-
url.pathname += path;
164-
} else {
165-
url.pathname += `/${path}`;
166-
}
159+
const basePath = url.pathname.replace(/\/+$/, '');
160+
const encodedSegments = segments.filter(s => s.length > 0).map(encodeURIComponent);
161+
url.pathname = `${basePath}/${encodedSegments.join('/')}`;
167162
if (query) {
168-
url.search = querystring.stringify(query);
163+
url.search = new URLSearchParams(query).toString();
169164
}
170165
return url;
171166
}

0 commit comments

Comments
 (0)