From 30487432425b864967aa47ba06370e387682aa7d Mon Sep 17 00:00:00 2001 From: t Date: Tue, 30 May 2023 05:25:08 -0700 Subject: [PATCH] handle base64-encoded request bodies (#10) --- Sources/Vercel/InvokeEvent.swift | 1 + Sources/Vercel/Request.swift | 18 ++++++++++++++-- Tests/VercelTests/RequestTests.swift | 31 ++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Sources/Vercel/InvokeEvent.swift b/Sources/Vercel/InvokeEvent.swift index 9b468b1..609beb5 100644 --- a/Sources/Vercel/InvokeEvent.swift +++ b/Sources/Vercel/InvokeEvent.swift @@ -13,6 +13,7 @@ public struct InvokeEvent: Codable, Sendable { public let headers: HTTPHeaders public let path: String public let body: String? + public let encoding: String? } public let body: String diff --git a/Sources/Vercel/Request.swift b/Sources/Vercel/Request.swift index 6890a45..63abd3e 100644 --- a/Sources/Vercel/Request.swift +++ b/Sources/Vercel/Request.swift @@ -10,16 +10,30 @@ public struct Request: Sendable { public let headers: HTTPHeaders public let path: String public let searchParams: [String: String] - public let body: String? + public let rawBody: Data? /// Private instance var to prevent decodable from failing public internal(set) var pathParams: Parameters = .init() + public var body: String? { + if let rawBody = rawBody { + return String(bytes: rawBody, encoding: .utf8) + } + + return nil + } + internal init(_ payload: InvokeEvent.Payload) { self.method = payload.method self.headers = payload.headers self.path = payload.path - self.body = payload.body + + if let encoding = payload.encoding, let body = payload.body, encoding == "base64" { + rawBody = Data(base64Encoded: body) + } else { + rawBody = payload.body?.data(using: .utf8) + } + self.searchParams = URLComponents(string: payload.path)? .queryItems? .reduce(into: [:]) { $0[$1.name] = $1.value } ?? [:] diff --git a/Tests/VercelTests/RequestTests.swift b/Tests/VercelTests/RequestTests.swift index 5b67052..c983b95 100644 --- a/Tests/VercelTests/RequestTests.swift +++ b/Tests/VercelTests/RequestTests.swift @@ -46,4 +46,35 @@ final class RequestTests: XCTestCase { XCTAssertEqual(req.method, .GET) XCTAssertEqual(req.searchParams["token"], "12345") } + + func testPlainBody() throws { + let json = """ + { + "method": "PUT", + "path": "/", + "headers": {}, + "body": "hello" + } + """ + let payload = try JSONDecoder().decode(InvokeEvent.Payload.self, from: json.data(using: .utf8)!) + let req = Request(payload) + XCTAssertEqual(req.body, "hello") + } + + func testBase64Body() throws { + let json = """ + { + "method": "PUT", + "path": "/", + "headers": {}, + "body": "/////w==", + "encoding": "base64" + } + """ + let payload = try JSONDecoder().decode(InvokeEvent.Payload.self, from: json.data(using: .utf8)!) + let req = Request(payload) + let expectData: [UInt8] = [0xff, 0xff, 0xff, 0xff] + XCTAssertEqual(req.rawBody, Data(expectData)) + XCTAssertNil(req.body) + } }