Skip to content

Commit

Permalink
Fix decoding 'flag' URL query params via `req.query.decode(StructType…
Browse files Browse the repository at this point in the history
….self)`

Fixes vapor#3163.
  • Loading branch information
challfry committed Apr 1, 2024
1 parent 11cdb29 commit 53268fc
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
6 changes: 3 additions & 3 deletions Sources/Vapor/URLEncodedForm/URLEncodedFormDecoder.swift
Expand Up @@ -212,7 +212,7 @@ private struct _Decoder: Decoder {
var configuration: URLEncodedFormDecoder.Configuration

var allKeys: [Key] {
self.data.children.keys.compactMap { Key(stringValue: String($0)) }
(self.data.children.keys + self.data.values.compactMap { try? $0.asUrlDecoded() }).compactMap { Key(stringValue: String($0)) }
}

init(
Expand All @@ -226,11 +226,11 @@ private struct _Decoder: Decoder {
}

func contains(_ key: Key) -> Bool {
self.data.children[key.stringValue] != nil
self.data.children[key.stringValue] != nil || self.data.values.contains(.init(stringLiteral: key.stringValue))
}

func decodeNil(forKey key: Key) throws -> Bool {
self.data.children[key.stringValue] == nil
self.data.children[key.stringValue] == nil && !self.data.values.contains(.init(stringLiteral: key.stringValue))
}

private func decodeDate(forKey key: Key, child: URLEncodedFormData) throws -> Date {
Expand Down
15 changes: 15 additions & 0 deletions Tests/VaporTests/QueryTests.swift
Expand Up @@ -310,17 +310,32 @@ final class QueryTests: XCTestCase {
url: URI(string: "/"),
on: app.eventLoopGroup.next()
)
struct BarStruct : Content {
let bar: Bool
}
struct OptionalBarStruct : Content {
let bar: Bool?
let baz: String?
}

req.url = .init(path: "/foo?bar")
XCTAssertTrue(try req.query.get(Bool.self, at: "bar"))
XCTAssertTrue(try req.query.decode(BarStruct.self).bar)
XCTAssertEqual(try req.query.decode(OptionalBarStruct.self).bar, true)

req.url = .init(path: "/foo?bar&baz=bop")
XCTAssertTrue(try req.query.get(Bool.self, at: "bar"))
XCTAssertTrue(try req.query.decode(BarStruct.self).bar)
XCTAssertEqual(try req.query.decode(OptionalBarStruct.self).bar, true)

req.url = .init(path: "/foo")
XCTAssertFalse(try req.query.get(Bool.self, at: "bar"))
XCTAssertFalse(try req.query.decode(BarStruct.self).bar)
XCTAssertNil(try req.query.decode(OptionalBarStruct.self).bar)

req.url = .init(path: "/foo?baz=bop")
XCTAssertFalse(try req.query.get(Bool.self, at: "bar"))
XCTAssertFalse(try req.query.decode(BarStruct.self).bar)
XCTAssertNil(try req.query.decode(OptionalBarStruct.self).bar)
}
}
16 changes: 16 additions & 0 deletions Tests/VaporTests/URLEncodedFormTests.swift
Expand Up @@ -520,6 +520,22 @@ final class URLEncodedFormTests: XCTestCase {
XCTAssertEqual(foo.flag, true)
}

func testFlagDecodingAsOptionalBool() throws {
struct Foo: Codable {
var flag: Bool?
}
let foo1 = try URLEncodedFormDecoder().decode(Foo.self, from: "flag")
XCTAssertEqual(foo1.flag, true)
let foo2 = try URLEncodedFormDecoder().decode(Foo.self, from: "somethingelse")
XCTAssertEqual(foo2.flag, nil)
let foo3 = try URLEncodedFormDecoder().decode(Foo.self, from: "")
XCTAssertEqual(foo3.flag, nil)
let foo4 = try URLEncodedFormDecoder().decode(Foo.self, from: "flag=true")
XCTAssertEqual(foo4.flag, true)
let foo5 = try URLEncodedFormDecoder().decode(Foo.self, from: "flag=false")
XCTAssertEqual(foo5.flag, false)
}

func testFlagIsOnDecodingAsBool() throws {
struct Foo: Codable {
var flag: Bool
Expand Down

0 comments on commit 53268fc

Please sign in to comment.