Skip to content

Instantly share code, notes, and snippets.

@hishma
Last active September 15, 2019 00:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hishma/fad76e95a0c8ebc2ec67003ffcc391c4 to your computer and use it in GitHub Desktop.
Save hishma/fad76e95a0c8ebc2ec67003ffcc391c4 to your computer and use it in GitHub Desktop.
Vapor 3 middleware to respond with errors based on the requested media type
import Vapor
import LeafErrorMiddleware
import APIErrorMiddleware
/// Respond with errors based on the requested media type
public final class VariantHandlingErrorMiddleware: Middleware, ServiceType {
public static func makeService(for container: Container) throws -> Self {
return self.init(environment: container.environment)
}
private let htmlErrorMiddleware: LeafErrorMiddleware
private let jsonErrorMiddleware: APIErrorMiddleware
init(environment: Environment) {
self.htmlErrorMiddleware = LeafErrorMiddleware(environment: environment)
self.jsonErrorMiddleware = APIErrorMiddleware(environment: environment)
}
public func respond(to request: Request, chainingTo next: Responder) throws -> Future<Response> {
if request.accepts(type: MediaType.json, exactly: true) {
// Return errors as JSON
return try jsonErrorMiddleware.respond(to: request, chainingTo: next)
} else {
// Return erros as HTML
return try htmlErrorMiddleware.respond(to: request, chainingTo: next)
}
}
}
extension Request {
/// Check if a `Request` accepts a specified `MediaType`.
///
/// - Parameters:
/// - type: The `MediaType` to check for.
/// - exactly: If false, `*/*` or `_type_/*` will be considered a match. If true the 'type' and 'subType' must match exactly. Default is false.
/// - Returns: True if the 'Accept' header of the `Request` contains the provided MediaType.
func accepts(type expectedType: MediaType, exactly: Bool = false) -> Bool {
guard exactly else {
return self.http.accept.mediaTypes.contains(expectedType)
}
return self.http.accept.mediaTypes.contains(where: { (aType) -> Bool in
aType.type == expectedType.type && aType.subType == expectedType.subType
})
}
}
@hishma
Copy link
Author

hishma commented Sep 15, 2019

Added to configure.swift:

services.register { return LeafErrorMiddleware(environment: $0.environment) }

services.register { return VariantHandlingErrorMiddleware(environment: $0.environment) }

services.register { worker in
    return APIErrorMiddleware(environment: worker.environment, specializations: [ModelNotFound()])
}

middlewares.use(VariantHandlingErrorMiddleware.self)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment