Skip to content

Commit

Permalink
fix: path params must not contain any unescaped generic syntax charac…
Browse files Browse the repository at this point in the history
…ters (#132)
  • Loading branch information
Himenon authored Mar 1, 2024
1 parent 62e852a commit 9fa1ce9
Show file tree
Hide file tree
Showing 15 changed files with 5,145 additions and 5,121 deletions.
18 changes: 14 additions & 4 deletions src/code-templates/_shared/MethodBody/PathParameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,21 @@ export const generateUrlTemplateExpression = (
pathParameters: CodeGenerator.PickedParameter[],
): Utils.Params$TemplateExpression => {
const patternMap = pathParameters.reduce<{ [key: string]: string }>((previous, item) => {
return { ...previous, [`{${item.name}}`]: item.name };
previous[`{${item.name}}`] = item.name;
return previous;
}, {});
const urlTemplate: Utils.Params$TemplateExpression = [];
let temporaryStringList: string[] = [];
// TODO generateVariableIdentifierに噛み合わ下げいいように変換する
const replaceText = (text: string): string | undefined => {
let replacedText = text;
Object.keys(patternMap).forEach(pathParameterName => {
for (const pathParameterName of Object.keys(patternMap)) {
if (new RegExp(pathParameterName).test(replacedText)) {
const { text, escaped } = escapeText(patternMap[pathParameterName]);
const variableDeclareText = escaped ? `params.parameter[${text}]` : `params.parameter.${text}`;
replacedText = replacedText.replace(new RegExp(pathParameterName, "g"), variableDeclareText);
}
});
}
return replacedText === text ? undefined : replacedText;
};

Expand All @@ -94,9 +95,18 @@ export const generateUrlTemplateExpression = (
});
temporaryStringList = [];
}

/**
* @see https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#path-templating
*/
urlTemplate.push({
type: "property",
value: Utils.generateVariableIdentifier(factory, replacedText),
value: factory.CallExpression.create({
expression: factory.Identifier.create({
name: "encodeURIComponent",
}),
argumentsArray: [Utils.generateVariableIdentifier(factory, replacedText)],
}),
});
} else {
temporaryStringList.push(requestUriTick);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,76 +45,90 @@ describe("PathParameter Test", () => {
return getText(expression);
};
test("generateUrlTemplateExpression", () => {
expect(generate("/{a}", [{ in: "path", name: "a", required: true }])).toEqual(`\`/\${params.parameter.a}\`;${EOL}`);
expect(generate("/{a}/", [{ in: "path", name: "a", required: true }])).toEqual(`\`/\${params.parameter.a}/\`;${EOL}`);
expect(generate("/a/{b}", [{ in: "path", name: "b", required: true }])).toEqual(`\`/a/\${params.parameter.b}\`;${EOL}`);
expect(generate("/a/{b}/", [{ in: "path", name: "b", required: true }])).toEqual(`\`/a/\${params.parameter.b}/\`;${EOL}`);
expect(generate("/a/{b}/c", [{ in: "path", name: "b", required: true }])).toEqual(`\`/a/\${params.parameter.b}/c\`;${EOL}`);
expect(generate("/a/{b}/c/", [{ in: "path", name: "b", required: true }])).toEqual(`\`/a/\${params.parameter.b}/c/\`;${EOL}`);
expect(generate("/a/b/{c}", [{ in: "path", name: "c", required: true }])).toEqual(`\`/a/b/\${params.parameter.c}\`;${EOL}`);
expect(generate("/a/b/{c}", [{ in: "path", name: "c", required: true }])).toEqual(`\`/a/b/\${params.parameter.c}\`;${EOL}`);
expect(generate("/a/b/{c}/", [{ in: "path", name: "c", required: true }])).toEqual(`\`/a/b/\${params.parameter.c}/\`;${EOL}`);
expect(generate("/a/b/{c}.json", [{ in: "path", name: "c", required: true }])).toEqual(`\`/a/b/\${params.parameter.c}.json\`;${EOL}`);
expect(generate("/{a}", [{ in: "path", name: "a", required: true }])).toEqual(`\`/\${encodeURIComponent(params.parameter.a)}\`;${EOL}`);
expect(generate("/{a}/", [{ in: "path", name: "a", required: true }])).toEqual(`\`/\${encodeURIComponent(params.parameter.a)}/\`;${EOL}`);
expect(generate("/a/{b}", [{ in: "path", name: "b", required: true }])).toEqual(`\`/a/\${encodeURIComponent(params.parameter.b)}\`;${EOL}`);
expect(generate("/a/{b}/", [{ in: "path", name: "b", required: true }])).toEqual(
`\`/a/\${encodeURIComponent(params.parameter.b)}/\`;${EOL}`,
);
expect(generate("/a/{b}/c", [{ in: "path", name: "b", required: true }])).toEqual(
`\`/a/\${encodeURIComponent(params.parameter.b)}/c\`;${EOL}`,
);
expect(generate("/a/{b}/c/", [{ in: "path", name: "b", required: true }])).toEqual(
`\`/a/\${encodeURIComponent(params.parameter.b)}/c/\`;${EOL}`,
);
expect(generate("/a/b/{c}", [{ in: "path", name: "c", required: true }])).toEqual(
`\`/a/b/\${encodeURIComponent(params.parameter.c)}\`;${EOL}`,
);
expect(generate("/a/b/{c}", [{ in: "path", name: "c", required: true }])).toEqual(
`\`/a/b/\${encodeURIComponent(params.parameter.c)}\`;${EOL}`,
);
expect(generate("/a/b/{c}/", [{ in: "path", name: "c", required: true }])).toEqual(
`\`/a/b/\${encodeURIComponent(params.parameter.c)}/\`;${EOL}`,
);
expect(generate("/a/b/{c}.json", [{ in: "path", name: "c", required: true }])).toEqual(
`\`/a/b/\${encodeURIComponent(params.parameter.c)}.json\`;${EOL}`,
);
expect(generate("/{a}.json/{a}.json/{a}.json", [{ in: "path", name: "a", required: true }])).toEqual(
`\`/\${params.parameter.a}.json/\${params.parameter.a}.json/\${params.parameter.a}.json\`;${EOL}`,
`\`/\${encodeURIComponent(params.parameter.a)}.json/\${encodeURIComponent(params.parameter.a)}.json/\${encodeURIComponent(params.parameter.a)}.json\`;${EOL}`,
);
expect(generate("/.json.{a}.json/{a}.json.{a}", [{ in: "path", name: "a", required: true }])).toEqual(
`\`/.json.\${params.parameter.a}.json/\${params.parameter.a}.json.\${params.parameter.a}\`;${EOL}`,
`\`/.json.\${encodeURIComponent(params.parameter.a)}.json/\${encodeURIComponent(params.parameter.a)}.json.\${encodeURIComponent(params.parameter.a)}\`;${EOL}`,
);

expect(
generate("/{a}/{b}", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "b", required: true },
]),
).toBe(`\`/\${params.parameter.a}/\${params.parameter.b}\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/\${encodeURIComponent(params.parameter.b)}\`;${EOL}`);
expect(
generate("/{a}/{b}/", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "b", required: true },
]),
).toBe(`\`/\${params.parameter.a}/\${params.parameter.b}/\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/\${encodeURIComponent(params.parameter.b)}/\`;${EOL}`);
expect(
generate("/{a}/{b}/c", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "b", required: true },
]),
).toBe(`\`/\${params.parameter.a}/\${params.parameter.b}/c\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/\${encodeURIComponent(params.parameter.b)}/c\`;${EOL}`);
expect(
generate("/{a}/{b}/c/", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "b", required: true },
]),
).toBe(`\`/\${params.parameter.a}/\${params.parameter.b}/c/\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/\${encodeURIComponent(params.parameter.b)}/c/\`;${EOL}`);
expect(
generate("/{a}/b/{c}", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "c", required: true },
]),
).toBe(`\`/\${params.parameter.a}/b/\${params.parameter.c}\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/b/\${encodeURIComponent(params.parameter.c)}\`;${EOL}`);
expect(
generate("/{a}/b/{c}/", [
{ in: "path", name: "a", required: true },
{ in: "path", name: "c", required: true },
]),
).toBe(`\`/\${params.parameter.a}/b/\${params.parameter.c}/\`;${EOL}`);
).toBe(`\`/\${encodeURIComponent(params.parameter.a)}/b/\${encodeURIComponent(params.parameter.c)}/\`;${EOL}`);
expect(
generate("/a/{b}/{c}", [
{ in: "path", name: "b", required: true },
{ in: "path", name: "c", required: true },
]),
).toBe(`\`/a/\${params.parameter.b}/\${params.parameter.c}\`;${EOL}`);
).toBe(`\`/a/\${encodeURIComponent(params.parameter.b)}/\${encodeURIComponent(params.parameter.c)}\`;${EOL}`);
expect(
generate("/a/{b}/{c}/", [
{ in: "path", name: "b", required: true },
{ in: "path", name: "c", required: true },
]),
).toBe(`\`/a/\${params.parameter.b}/\${params.parameter.c}/\`;${EOL}`);
).toBe(`\`/a/\${encodeURIComponent(params.parameter.b)}/\${encodeURIComponent(params.parameter.c)}/\`;${EOL}`);
expect(
generate("/a/{b}...{c}/", [
{ in: "path", name: "b", required: true },
{ in: "path", name: "c", required: true },
]),
).toBe(`\`/a/\${params.parameter.b}...\${params.parameter.c}/\`;${EOL}`);
).toBe(`\`/a/\${encodeURIComponent(params.parameter.b)}...\${encodeURIComponent(params.parameter.c)}/\`;${EOL}`);
});
});
20 changes: 10 additions & 10 deletions test/__tests__/class/__snapshots__/argo-rollout-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3859,7 +3859,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_ListRolloutInfos(params: Params$RolloutService_ListRolloutInfos, option?: RequestOption): Promise<Response$RolloutService_ListRolloutInfos$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/info\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/info\`;
const headers = {
Accept: "application/json"
};
Expand All @@ -3870,7 +3870,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_WatchRolloutInfos(params: Params$RolloutService_WatchRolloutInfos, option?: RequestOption): Promise<Response$RolloutService_WatchRolloutInfos$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/info/watch\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/info/watch\`;
const headers = {
Accept: "application/json"
};
Expand All @@ -3881,7 +3881,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_AbortRollout(params: Params$RolloutService_AbortRollout, option?: RequestOption): Promise<Response$RolloutService_AbortRollout$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/abort\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/abort\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand All @@ -3894,7 +3894,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_GetRolloutInfo(params: Params$RolloutService_GetRolloutInfo, option?: RequestOption): Promise<Response$RolloutService_GetRolloutInfo$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/info\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/info\`;
const headers = {
Accept: "application/json"
};
Expand All @@ -3905,7 +3905,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_WatchRolloutInfo(params: Params$RolloutService_WatchRolloutInfo, option?: RequestOption): Promise<Response$RolloutService_WatchRolloutInfo$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/info/watch\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/info/watch\`;
const headers = {
Accept: "application/json"
};
Expand All @@ -3916,7 +3916,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_PromoteRollout(params: Params$RolloutService_PromoteRollout, option?: RequestOption): Promise<Response$RolloutService_PromoteRollout$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/promote\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/promote\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand All @@ -3929,7 +3929,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_RestartRollout(params: Params$RolloutService_RestartRollout, option?: RequestOption): Promise<Response$RolloutService_RestartRollout$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/restart\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/restart\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand All @@ -3942,7 +3942,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_RetryRollout(params: Params$RolloutService_RetryRollout, option?: RequestOption): Promise<Response$RolloutService_RetryRollout$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.name}/retry\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.name)}/retry\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand All @@ -3955,7 +3955,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_SetRolloutImage(params: Params$RolloutService_SetRolloutImage, option?: RequestOption): Promise<Response$RolloutService_SetRolloutImage$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.rollout}/set/\${params.parameter.container}/\${params.parameter.image}/\${params.parameter.tag}\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.rollout)}/set/\${encodeURIComponent(params.parameter.container)}/\${encodeURIComponent(params.parameter.image)}/\${encodeURIComponent(params.parameter.tag)}\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand All @@ -3968,7 +3968,7 @@ export class Client<RequestOption> {
}, option);
}
public async RolloutService_UndoRollout(params: Params$RolloutService_UndoRollout, option?: RequestOption): Promise<Response$RolloutService_UndoRollout$Status$200["application/json"]> {
const url = this.baseUrl + \`/api/v1/rollouts/\${params.parameter.namespace}/\${params.parameter.rollout}/undo/\${params.parameter.revision}\`;
const url = this.baseUrl + \`/api/v1/rollouts/\${encodeURIComponent(params.parameter.namespace)}/\${encodeURIComponent(params.parameter.rollout)}/undo/\${encodeURIComponent(params.parameter.revision)}\`;
const headers = {
"Content-Type": "application/json",
Accept: "application/json"
Expand Down
Loading

0 comments on commit 9fa1ce9

Please sign in to comment.