Skip to content

Commit

Permalink
Add support for multivalue headers in APIGatewayV2
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Mar 5, 2024
1 parent 59b99fe commit 593a3cc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 21 deletions.
14 changes: 14 additions & 0 deletions Sources/HummingbirdLambda/APIGatewayLambda.swift
Expand Up @@ -75,6 +75,20 @@ extension APIGatewayRequest: APIRequest {
}

Check warning on line 75 in Sources/HummingbirdLambda/APIGatewayLambda.swift

View check run for this annotation

Codecov / codecov/patch

Sources/HummingbirdLambda/APIGatewayLambda.swift#L74-L75

Added lines #L74 - L75 were not covered by tests
return queryParams.joined(separator: "&")
}

var httpHeaders: [(name: String, value: String)] {
var headerValues = [(name: String, value: String)].init()
var originalHeaders = self.headers
headerValues.reserveCapacity(headers.count)
for header in self.multiValueHeaders {
originalHeaders[header.key] = nil
for value in header.value {
headerValues.append((name: header.key, value: value))
}
}
headerValues.append(contentsOf: originalHeaders.map { (name: $0.key, value: $0.value) })
return headerValues
}
}

// conform `APIGatewayResponse` to `APIResponse` so we can use HBResponse.apiReponse()
Expand Down
10 changes: 8 additions & 2 deletions Sources/HummingbirdLambda/APIGatewayV2Lambda.swift
Expand Up @@ -63,9 +63,15 @@ extension APIGatewayV2Request: APIRequest {
}

var httpMethod: AWSLambdaEvents.HTTPMethod { context.http.method }
var multiValueQueryStringParameters: [String: [String]]? { nil }
var multiValueHeaders: HTTPMultiValueHeaders { [:] }
var queryString: String { self.rawQueryString }
var httpHeaders: [(name: String, value: String)] {
self.headers.flatMap { header in
let headers = header.value
.split(separator: ",")
.map { (name: header.key, value: String($0.drop(while: \.isWhitespace))) }
return headers
}
}
}

// conform `APIGatewayV2Response` to `APIResponse` so we can use HBResponse.apiReponse()
Expand Down
22 changes: 3 additions & 19 deletions Sources/HummingbirdLambda/Request+APIGateway.swift
Expand Up @@ -24,8 +24,7 @@ protocol APIRequest {
var path: String { get }
var httpMethod: AWSLambdaEvents.HTTPMethod { get }
var queryString: String { get }
var headers: AWSLambdaEvents.HTTPHeaders { get }
var multiValueHeaders: HTTPMultiValueHeaders { get }
var httpHeaders: [(name: String, value: String)] { get }
var body: String? { get }
var isBase64Encoded: Bool { get }
}
Expand All @@ -48,7 +47,7 @@ extension HBRequest {
}
// construct headers
var authority: String?
let headers = HTTPFields(headers: from.headers, multiValueHeaders: from.multiValueHeaders, authority: &authority)
let headers = HTTPFields(headers: from.httpHeaders, authority: &authority)

// get body
let body: ByteBuffer?
Expand Down Expand Up @@ -82,32 +81,17 @@ extension HTTPFields {
/// - headers: headers
/// - multiValueHeaders: multi-value headers
/// - authority: reference to authority string
init(headers: AWSLambdaEvents.HTTPHeaders, multiValueHeaders: HTTPMultiValueHeaders, authority: inout String?) {
init(headers: [(name: String, value: String)], authority: inout String?) {
self.init()
self.reserveCapacity(headers.count)
var firstHost = true
for (name, values) in multiValueHeaders {
if firstHost, name.lowercased() == "host" {
if let value = values.first {
firstHost = false
authority = value
continue
}
}
if let fieldName = HTTPField.Name(name) {
for value in values {
self.append(HTTPField(name: fieldName, value: value))
}
}
}
for (name, value) in headers {
if firstHost, name.lowercased() == "host" {
firstHost = false
authority = value
continue
}
if let fieldName = HTTPField.Name(name) {
if self[fieldName] != nil { continue }
self.append(HTTPField(name: fieldName, value: value))
}
}
Expand Down

0 comments on commit 593a3cc

Please sign in to comment.