Ktor: call.parameters containing query parameter instead of path segment

Created on 14 Mar 2019  路  4Comments  路  Source: ktorio/ktor

Ktor Version

1.2.0-alpha-1

Ktor Engine Used(client or server and name)

Tried both Netty and CIO

JVM Version, Operating System and Relevant Context

openjdk version "1.8.0_191"
Ubuntu 18.04

Feedback

The following routing configuration

route("/{bar}") {
    get {
        call.respond(HttpStatusCode.OK, "${call.request.uri}\n" +
            "\tcall.parameters[\"bar\"]: ${call.parameters["bar"]}\n" +
            "\tcall.request.queryParameters[\"bar\"]: ${call.request.queryParameters["bar"]}")
    }
}

provides the following responses:

/foo?bar=baz
    call.parameters["bar"]: baz
    call.request.queryParameters["bar"]: baz
/foo?baz=baz
    call.parameters["bar"]: foo
    call.request.queryParameters["bar"]: null

So when we try to get path component value by it's name from `call.parameters', and the request has query parameter of the same name, we get query parameter instead of expected path component. Neither KDoc comment nor documentation mentions this behavior. Is it expected?

Kudos to @frost13it for this interesting finding.

design

Most helpful comment

I've looked through all samples using call.parameters, and all of them are using it to get specifically path segments, both via get and getAll. Why query parameters are present there at all? I believe that one of these should be true:

  • call.parameters is store explicitly for path segments, and query parameters shouldn't be present there
  • call.parameters is store akin to PHP's $_REQUEST which is a garbage bin for all kinds of things that can be labeled a "parameter", and there should be another store similar to call.request.queryParameters (e.g. call.request.pathSegments), where one can find specifically path segments.

I can't come up with situation when developer would expect that query parameter implicitly hides path segment value with the same name (not that I claim such situations don't exist), so I'd say this is a surprise point for library users.

All 4 comments

Yes, it seems to be expected: to get all values use call.parameters.getAll("bar") white the get operator returns the first occurrence. The question is what priority it should have...

I've looked through all samples using call.parameters, and all of them are using it to get specifically path segments, both via get and getAll. Why query parameters are present there at all? I believe that one of these should be true:

  • call.parameters is store explicitly for path segments, and query parameters shouldn't be present there
  • call.parameters is store akin to PHP's $_REQUEST which is a garbage bin for all kinds of things that can be labeled a "parameter", and there should be another store similar to call.request.queryParameters (e.g. call.request.pathSegments), where one can find specifically path segments.

I can't come up with situation when developer would expect that query parameter implicitly hides path segment value with the same name (not that I claim such situations don't exist), so I'd say this is a surprise point for library users.

I agree, parameters and queryParameters are not the same thing at all.

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.

Was this page helpful?
0 / 5 - 0 ratings