smithy icon indicating copy to clipboard operation
smithy copied to clipboard

What is the server behavior for routing based on query strings when multiple values appear for the same query key parameter?

Open david-perez opened this issue 2 years ago • 1 comments

The docs don't specify a behavior. Relevant section in the docs: https://awslabs.github.io/smithy/1.0/spec/core/http-traits.html#query-string-literals

There are also no protocol tests.

An example. Consider two routes with URI request patterns:

  1. /path?fooKey=bar
  2. /path?fooKey=baz

And we receive an HTTP request with URI http://yourhost/path?fooKey=bar&fooKey=baz. Where should we route it to?

Note that currently this scenario is accepted by Smithy i.e. this minimal model builds fine:

$version: "1.0"

namespace com.amazonaws.simple

use aws.protocols#restJson1

@restJson1
@title("SimpleService")
service SimpleService {
    version: "2022-01-01",
    operations: [
        Healthcheck1,
        Healthcheck2,
    ],
}

@http(uri: "/healthcheck?fooKey=bar", method: "GET")
operation Healthcheck1 {
    input: HealthcheckInputRequest,
    output: HealthcheckOutputResponse
}

@http(uri: "/healthcheck?fooKey=baz", method: "GET")
operation Healthcheck2 {
    input: HealthcheckInputRequest,
    output: HealthcheckOutputResponse
}

structure HealthcheckInputRequest {
}

structure HealthcheckOutputResponse {
}

david-perez avatar Jan 31 '22 18:01 david-perez

If the operation can't be determined, you throw a serialization exception. It's pretty clear that this would be indeterminable, though I suppose your question could also be phrased as "How should duplicate query keys be treated?". The answer to that can be found here:

List and set members are serialized by adding multiple query string parameters to the query string using the same name. For example, given a member bound to foo that targets a list of strings with a value of ["a", "b"], the value is serialized in the query string as foo=a&foo=b.

So since we treat duplicate entries as lists, the query params in your example could be represented in JSON as:

{
    "fooKey": ["bar", "baz"]
}

But you're expecting fooKey to have a value of bar or baz. Since it has neither of those values, the intended request cannot be determined and you must then return an error.

JordonPhillips avatar Feb 28 '22 16:02 JordonPhillips