Skip to content

Commit

Permalink
Remove HeadResponder (#3147)
Browse files Browse the repository at this point in the history
The HEAD method is identical to GET except that the server must not send content in the response (RFC 9110, section 9.3.2).

The previous default behaviour of returning 200 OK to every HEAD request to a constant route is not standard-compliant.

The new behaviour is to always forward the request to the GET route, unless the developer explicitly configured a custom HEAD route.
  • Loading branch information
baarde committed Apr 23, 2024
1 parent 526a000 commit 0311f9a
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 44 deletions.
26 changes: 0 additions & 26 deletions Sources/Vapor/Responder/DefaultResponder.swift
Expand Up @@ -39,26 +39,6 @@ internal struct DefaultResponder: Responder {
}
}

// If the route isn't explicitly a HEAD route,
// and it's made up solely of .constant components,
// register a HEAD route with the same path
if route.method == .GET &&
route.path.allSatisfy({ component in
if case .constant(_) = component { return true }
return false
}) {
let headRoute = Route(
method: .HEAD,
path: route.path,
responder: middleware.makeResponder(chainingTo: HeadResponder()),
requestType: route.requestType,
responseType: route.responseType)

let headCachedRoute = CachedRoute(route: headRoute, responder: middleware.makeResponder(chainingTo: HeadResponder()))

router.register(headCachedRoute, at: [.constant(HTTPMethod.HEAD.string)] + path)
}

router.register(cached, at: [.constant(route.method.string)] + path)
}
self.router = router
Expand Down Expand Up @@ -155,12 +135,6 @@ internal struct DefaultResponder: Responder {
}
}

private struct HeadResponder: Responder {
func respond(to request: Request) -> EventLoopFuture<Response> {
request.eventLoop.makeSucceededFuture(.init(status: .ok))
}
}

private struct NotFoundResponder: Responder {
func respond(to request: Request) -> EventLoopFuture<Response> {
request.eventLoop.makeFailedFuture(RouteNotFound())
Expand Down
21 changes: 3 additions & 18 deletions Tests/VaporTests/RouteTests.swift
Expand Up @@ -229,38 +229,23 @@ final class RouteTests: XCTestCase {
}
}

func testHeadRequestWithConstantPathReturnsOK() throws {
func testHeadRequestForwardedToGet() throws {
let app = Application(.testing)
defer { app.shutdown() }

app.get("hello") { req -> String in
return "hi"
}

try app.testable(method: .running(port: 0)).test(.HEAD, "/hello") { res in
XCTAssertEqual(res.status, .ok)
XCTAssertEqual(res.headers.first(name: .contentLength), "0")
XCTAssertEqual(res.body.readableBytes, 0)
}
}

func testHeadRequestWithParameterForwardedToGet() throws {
let app = Application(.testing)
defer { app.shutdown() }

app.get("hello", ":name") { req -> String in
XCTAssertEqual(req.method, .HEAD)
return "hi"
}

try app.testable(method: .running(port: 0)).test(.HEAD, "/hello/joe") { res in
try app.testable(method: .running(port: 0)).test(.HEAD, "/hello") { res in
XCTAssertEqual(res.status, .ok)
XCTAssertEqual(res.headers.first(name: .contentLength), "2")
XCTAssertEqual(res.body.readableBytes, 0)
}
}

func testExplicitHeadRouteHandlerOverridesGeneratedHandler() throws {
func testExplicitHeadRouteOverridesForwardingToGet() throws {
let app = Application(.testing)
defer { app.shutdown() }

Expand Down

0 comments on commit 0311f9a

Please sign in to comment.