Skip to content

Commit

Permalink
Ensure errors have server and date header
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed May 22, 2024
1 parent 0288162 commit b3efc76
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 8 deletions.
17 changes: 16 additions & 1 deletion Sources/Hummingbird/Application.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,22 @@ extension ApplicationProtocol {
logger: self.logger.with(metadataKey: "hb_id", value: .stringConvertible(RequestID()))
)
// respond to request
var response = try await responder.respond(to: request, context: context)
var response: Response
do {
response = try await responder.respond(to: request, context: context)
} catch {
switch error {
case let httpError as HTTPResponseError:
// this is a processed error so don't log as Error
response = httpError.response(allocator: channel.allocator)
default:
// this error has not been recognised
response = Response(
status: .internalServerError,
body: .init()
)
}
}
response.headers[.date] = dateCache.date
// server name header
if let serverName = self.configuration.serverName {
Expand Down
23 changes: 23 additions & 0 deletions Sources/HummingbirdCore/Error/NIOCore+HTTPResponseError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Hummingbird server framework project
//
// Copyright (c) 2024 the Hummingbird authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import HTTPTypes
import NIOCore

// If we catch a too many bytes error report that as payload too large
extension NIOTooManyBytesError: HTTPResponseError {
public var status: HTTPResponse.Status { .contentTooLarge }
public var headers: HTTPFields { [:] }
public func body(allocator: ByteBufferAllocator) -> ByteBuffer? { nil }
}
7 changes: 0 additions & 7 deletions Sources/HummingbirdCore/Server/HTTP/HTTPChannelHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,6 @@ struct HTTPServerBodyWriter: Sendable, ResponseBodyWriter {
}
}

// If we catch a too many bytes error report that as payload too large
extension NIOTooManyBytesError: HTTPResponseError {
public var status: HTTPResponse.Status { .contentTooLarge }
public var headers: HTTPFields { [:] }
public func body(allocator: ByteBufferAllocator) -> ByteBuffer? { nil }
}

extension NIOLockedValueBox {
/// Exchange stored value for new value and return the old stored value
func exchange(_ newValue: Value) -> Value {
Expand Down
14 changes: 14 additions & 0 deletions Tests/HummingbirdTests/ApplicationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,20 @@ final class ApplicationTests: XCTestCase {
}
}

func testErrorHeaders() async throws {
let router = Router()
router.get("error") { _, _ -> HTTPResponse.Status in
throw HTTPError(.badRequest, message: "BAD!")
}
let app = Application(router: router, configuration: .init(serverName: "HB"))
try await app.test(.live) { client in
try await client.execute(uri: "/error", method: .get) { response in
XCTAssertEqual(response.headers[.server], "HB")
XCTAssertNotNil(response.headers[.date])
}
}
}

func testResponseBody() async throws {
let router = Router()
router
Expand Down

0 comments on commit b3efc76

Please sign in to comment.