Skip to content

'Flag' URL Query params don't decode into structs #3163

Closed
@challfry

Description

@challfry

Describe the issue

req.query.decode(Struct.self) fails to decode '?flag1' query into 'let flag1: Bool?' property

Vapor version

4.92.5

Operating system and version

mac OS 14.3.1

Swift version

Apple Swift version 5.9.2

Steps to reproduce

  1. Add the following to "routes.swift" in a template Vapor project created with vapor new hello -n.
struct QueryStruct: Content {
    var flag1: Bool?
}
app.get("singlevaluedecode") { req async throws -> String in
    var queryStruct = QueryStruct()
    queryStruct.flag1 = req.query[Bool.self, at: "flag1"]
    return "\(queryStruct)"
}
app.get("structdecode") { req async throws -> String in
    let queryStruct = try req.query.decode(QueryStruct.self)
    return "\(queryStruct)"
}
  1. Run curl on the two routes, with a ?flag1 query:
% curl "http://127.0.0.1:8080/singlevaluedecode?flag1" 
QueryStruct(flag1: Optional(true))

% curl "http://127.0.0.1:8080/structdecode?flag1"
QueryStruct(flag1: nil)

Outcome

It's not feasible for a generalized decoder to capture all the possible semantic meanings of a query; a query that relied on order of query params couldn't use either single-value decoding nor struct decoding. There's no standard here; the query coders are a utility to help with commonly-used cases.

But single-value and struct decoding should work the same, as much as they can. 4.92.2 fixed flag query params for the single-value decode method; struct decoding (into optional Bools) ought to have parity in this case.

Additional notes

Cause of this issue appears to be that URLEncodedFormParser parses flags into URLEncodedFormData.values and key-value params into URLEncodedFormData.children while URLEncodedFormDecoder's _Decoder.KeyedContainer.contains() only checks .children. This makes decodeIfPresent() always return nil for flags.

_Decoder.KeyedContainer.decode() contains a case for decoding flag values into Bools, so decoding into a non-optional Bool works.

PR incoming.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions