diff --git a/src/util/url-template.ts b/src/util/url-template.ts index aeb41c7e..42b4cb34 100644 --- a/src/util/url-template.ts +++ b/src/util/url-template.ts @@ -156,7 +156,7 @@ export function parseUrl(template: string) { function expand(template: string, context: object): string { var operators = ["+", "#", ".", "/", ";", "?", "&"]; - return template.replace( + template = template.replace( /\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { if (expression) { @@ -190,4 +190,10 @@ function expand(template: string, context: object): string { } }, ); + + if (template === "/") { + return template; + } else { + return template.replace(/\/$/, ""); + } } diff --git a/test/endpoint.test.ts b/test/endpoint.test.ts index 391a15a2..58e7ca49 100644 --- a/test/endpoint.test.ts +++ b/test/endpoint.test.ts @@ -336,7 +336,7 @@ describe("endpoint()", () => { expect(endpoint("/").url).toEqual("https://api.github.com/"); expect(endpoint("/").method).toEqual("GET"); expect(endpoint("https://github.acme-inc/api/v3/").url).toEqual( - "https://github.acme-inc/api/v3/", + "https://github.acme-inc/api/v3", ); }); @@ -500,6 +500,72 @@ describe("endpoint()", () => { }); }); + it("Undefined placeholder value with no trailing slash in URL", () => { + const options1 = endpoint("GET /repos/{owner}/{repo}/branches/{branch}", { + owner: "owner", + repo: "repo", + }); + + expect(options1).toEqual({ + method: "GET", + url: "https://api.github.com/repos/owner/repo/branches", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent, + }, + }); + + const options2 = endpoint("GET /repos/{owner}/{repo}/branches{/branch}", { + owner: "owner", + repo: "repo", + }); + + expect(options2).toEqual({ + method: "GET", + url: "https://api.github.com/repos/owner/repo/branches", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent, + }, + }); + }); + + it("Trailing slash in URL in expression is encoded", () => { + const options1 = endpoint( + "GET /repos/{owner}/{repo}/git/matching-refs/{ref}", + { + owner: "owner", + repo: "repo", + ref: "heads/", + }, + ); + + expect(options1).toEqual({ + method: "GET", + url: "https://api.github.com/repos/owner/repo/git/matching-refs/heads%2F", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent, + }, + }); + + const options2 = endpoint("GET /repos/{owner}/{repo}/contents/{path}", { + owner: "owner", + repo: "repo", + path: "my-folder/", + ref: "feature/branch", + }); + + expect(options2).toEqual({ + method: "GET", + url: "https://api.github.com/repos/owner/repo/contents/my-folder%2F?ref=feature%2Fbranch", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent, + }, + }); + }); + it("Undefined header value", () => { const options = endpoint({ method: "GET",