Skip to content

explode defaults to true for query parameters #7148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function defaultEncoding(
value: Uint8Array,
options?: DefaultEncodingOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
value: encodeUint8Array(value, "base64url")!,
});
const httpRequestOptions = {
Expand Down
10 changes: 5 additions & 5 deletions packages/http-client-js/test/scenarios/encoding/query_date.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function defaultEncoding(
value: Date,
options?: DefaultEncodingOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
value: dateRfc3339Serializer(value),
});
const httpRequestOptions = {
Expand Down Expand Up @@ -65,7 +65,7 @@ export async function defaultEncoding(
client: TestClientContext,
options?: DefaultEncodingOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
...(options?.value && { value: dateRfc3339Serializer(options.value) }),
});
const httpRequestOptions = {
Expand Down Expand Up @@ -109,7 +109,7 @@ export async function get(
value: Date,
options?: GetOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
value: dateRfc3339Serializer(value),
});
const httpRequestOptions = {
Expand Down Expand Up @@ -153,7 +153,7 @@ export async function get(
value: Date,
options?: GetOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
value: dateRfc7231Serializer(value),
});
const httpRequestOptions = {
Expand Down Expand Up @@ -197,7 +197,7 @@ export async function get(
value: Date,
options?: GetOptions,
): Promise<void> {
const path = parse("/default{?value}").expand({
const path = parse("/default{?value*}").expand({
value: dateUnixTimestampSerializer(value),
});
const httpRequestOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export async function read(
name: string,
options?: ReadOptions,
): Promise<void> {
const path = parse("/widgets/{id}{?foo}").expand({
const path = parse("/widgets/{id}{?foo*}").expand({
id: id,
foo: foo,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function link(

```ts src/api/testClientOperations.ts function linkSend
async function linkSend(client: TestClientContext, filter: string, options?: Record<string, any>) {
const path = parse("/link{?filter,nextToken}").expand({
const path = parse("/link{?filter*,nextToken*}").expand({
filter: filter,
...(options?.nextToken && { nextToken: options.nextToken }),
});
Expand Down Expand Up @@ -173,7 +173,7 @@ export function link(

```ts src/api/testClientOperations.ts function linkSend
async function linkSend(client: TestClientContext, filter: string, options?: Record<string, any>) {
const path = parse("/link{?filter,maxPageSize}").expand({
const path = parse("/link{?filter*,maxPageSize*}").expand({
filter: filter,
...(options?.maxPageSize && { maxPageSize: options.maxPageSize }),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export async function read(
name: string,
options?: ReadOptions,
): Promise<void> {
const path = parse("/widgets/{id}{?foo}").expand({
const path = parse("/widgets/{id}{?foo*}").expand({
id: id,
foo: foo,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export async function getWithParams(
age: number,
options?: GetWithParamsOptions,
): Promise<number> {
const path = parse("/{?name,age}").expand({
const path = parse("/{?name*,age*}").expand({
name: name,
age: age,
});
Expand Down
3 changes: 2 additions & 1 deletion packages/http/src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ export function resolveQueryOptionsWithDefaults(
options: QueryOptions & { name: string },
): Required<QueryOptions> {
return {
explode: options.explode ?? false,
// For query parameters(style: form) the default is explode: true https://spec.openapis.org/oas/v3.0.2#fixed-fields-9
explode: options.explode ?? true,
name: options.name,
};
}
Expand Down
15 changes: 13 additions & 2 deletions packages/http/test/http-decorators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,16 +277,27 @@ describe("http: decorators", () => {
strictEqual(getQueryParamName(runner.program, select), "$select");
});

it("specify explode: true", async () => {
it("don't specify explode", async () => {
const { selects } = await runner.compile(`
op test(@test @query(#{ explode: true }) selects: string[]): string;
op test(@test @query selects: string[]): string;
`);
expect(getQueryParamOptions(runner.program, selects)).toEqual({
type: "query",
name: "selects",
explode: true,
});
});

it("specify explode: false", async () => {
const { selects } = await runner.compile(`
op test(@test @query(#{ explode: false }) selects: string[]): string;
`);
expect(getQueryParamOptions(runner.program, selects)).toEqual({
type: "query",
name: "selects",
explode: false,
});
});
});

describe("@route", () => {
Expand Down
7 changes: 4 additions & 3 deletions packages/http/test/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,16 +572,17 @@ describe("uri template", () => {
[`@path(#{style: "fragment"}) one: string`, "/foo/{#one}"],
[`@path(#{style: "path"}) one: string`, "/foo/{/one}"],
["@path(#{allowReserved: true, explode: true}) one: string", "/foo/{+one*}"],
["@query one: string", "/foo{?one}"],
["@query one: string", "/foo{?one*}"],
["@query(#{explode: true}) one: string", "/foo{?one*}"],
["@query(#{explode: false}) one: string", "/foo{?one}"],
[
"@query(#{explode: true}) one: string, @query(#{explode: true}) two: string",
"/foo{?one*,two*}",
],

// cspell:ignore Atwo Dtwo
[`@query("one:two") one: string`, "/foo{?one%3Atwo}"],
[`@query("one-two") one: string`, "/foo{?one%2Dtwo}"],
[`@query("one:two") one: string`, "/foo{?one%3Atwo*}"],
[`@query("one-two") one: string`, "/foo{?one%2Dtwo*}"],
])("%s -> %s", async (param, expectedUri) => {
const op = await getOp(`@route("/foo") op foo(${param}): void;`);
expect(op.uriTemplate).toEqual(expectedUri);
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi3/src/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,7 @@ function createOAPIEmitter(
function getQueryParameterAttributes(httpProperty: HttpProperty & { kind: "query" }) {
const attributes: { style?: string; explode?: boolean } = {};

if (httpProperty.options.explode !== true) {
if (httpProperty.options.explode === false) {
// For query parameters(style: form) the default is explode: true https://spec.openapis.org/oas/v3.0.2#fixed-fields-9
attributes.explode = false;
}
Expand Down
2 changes: 0 additions & 2 deletions packages/openapi3/test/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,6 @@ worksFor(["3.0.0", "3.1.0"], ({ openApiFor }) => {
"Parameters.q": {
name: "q",
in: "query",
explode: false,
required: true,
schema: { type: "string" },
},
Expand Down Expand Up @@ -731,7 +730,6 @@ worksFor(["3.0.0", "3.1.0"], ({ openApiFor }) => {
name: "q",
in: "query",
required: true,
explode: false,
schema: { type: "string" },
},
{
Expand Down
2 changes: 0 additions & 2 deletions packages/openapi3/test/parameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
`op test(@query @encode(${encoding}) myParam: string[]): void;`,
);
expect(param).toMatchObject({
explode: false,
style: style,
});
expect(param.schema).toStrictEqual({
Expand Down Expand Up @@ -94,7 +93,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
deepStrictEqual(res.paths["/"].get.parameters[0], {
in: "query",
name: "id",
explode: false,
required: true,
schema: {
type: "string",
Expand Down
5 changes: 0 additions & 5 deletions packages/openapi3/test/shared-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
{
in: "query",
name: "resourceGroup",
explode: false,
required: false,
schema: {
type: "string",
Expand All @@ -79,7 +78,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
{
in: "query",
name: "foo",
explode: false,
required: true,
schema: {
type: "string",
Expand All @@ -88,7 +86,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
{
in: "query",
name: "subscription",
explode: false,
required: false,
schema: {
type: "string",
Expand Down Expand Up @@ -133,7 +130,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
{
in: "query",
name: "filter",
explode: false,
required: true,
schema: {
type: "string",
Expand Down Expand Up @@ -180,7 +176,6 @@ worksFor(["3.0.0", "3.1.0"], ({ diagnoseOpenApiFor, openApiFor }) => {
name: "filter",
in: "query",
required: false,
explode: false,
schema: {
type: "string",
enum: ["resourceGroup"],
Expand Down
6 changes: 4 additions & 2 deletions packages/rest/test/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -583,9 +583,11 @@ describe("uri template", () => {
[`@path(#{style: "fragment"}) one: string`, "/foo/{#one}"],
[`@path(#{style: "path"}) one: string`, "/foo/{/one}"],
["@path(#{allowReserved: true, explode: true}) one: string", "/foo/{+one*}"],
["@query one: string", "/foo{?one}"],
["@query one: string", "/foo{?one*}"],
["@query(#{explode: true}) one: string", "/foo{?one*}"],
["@query(#{explode: false}) one: string", "/foo{?one}"],
// cspell:ignore Atwo
[`@query("one:two") one: string`, "/foo{?one%3Atwo}"],
[`@query("one:two") one: string`, "/foo{?one%3Atwo*}"],
])("%s -> %s", async (param, expectedUri) => {
const op = await getOp(`@route("/foo") interface Test {@autoRoute op foo(${param}): void;}`);
expect(op.uriTemplate).toEqual(expectedUri);
Expand Down
2 changes: 1 addition & 1 deletion packages/samples/specs/visibility/visibility.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ namespace Hello {
@get op read(
@path id: string,

@query(#{ explode: true })
@query(#{ explode: false })
fieldMask: string[],
): ReadablePerson;
@post op create(@body person: WritablePerson): ReadablePerson;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@ components:
schema:
type: integer
format: int32
explode: false
ListRequestBase.page_token:
name: page_token
in: query
Expand All @@ -282,7 +281,6 @@ components:
returned from the previous call to `ListShelves` method.
schema:
type: string
explode: false
MergeShelvesRequest.name:
name: name
in: path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ paths:
schema:
type: string
nullable: true
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ paths:
schema:
type: string
default: defaultQueryString
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ paths:
format: int32
minimum: 0
maximum: 10
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ paths:
required: false
schema:
type: string
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down Expand Up @@ -104,7 +103,6 @@ paths:
required: true
schema:
type: string
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,6 @@ paths:
required: true
schema:
type: string
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ components:
type: integer
format: int32
default: 50
explode: false
TodoItems.PaginationControls.offset:
name: offset
in: query
Expand All @@ -311,7 +310,6 @@ components:
type: integer
format: int32
default: 0
explode: false
schemas:
ApiError:
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ paths:
type: array
items:
type: string
explode: false
responses:
'200':
description: The request has succeeded.
Expand Down
Loading