Skip to content

Instantly share code, notes, and snippets.

@MahdiBM
Last active February 27, 2024 20:14
Show Gist options
  • Save MahdiBM/7108ba4a5e42368e23b6b291b908abf1 to your computer and use it in GitHub Desktop.
Save MahdiBM/7108ba4a5e42368e23b6b291b908abf1 to your computer and use it in GitHub Desktop.
swift-openapi-vapor + `TaskLocal`s to pass the `Request` to the OpenAPI handler
/// PREREQUISITES:
/// Add https://github.com/pointfreeco/swift-dependencies as a dependency of your target, currently it looks like so:
/// `.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0"),`
// MARK: '+DependencyValues.swift'
import Vapor
import Dependencies
extension DependencyValues {
/// The request available in the context. This will cause a crash if you don't access it in a `Request` context.
/// It will not ever crash if you use it like in this example in the routes, but you can also make it
/// an optional property if you want to.
var request: Request {
get { self[RequiredGenericKey.self] }
set { self[RequiredGenericKey.self] = newValue }
}
/// A generic `DependencyKey` that requires a value to be present, or crashes.
private enum RequiredGenericKey<Value>: DependencyKey {
static var liveValue: Value {
fatalError("Value of type \(Value.self) is not registered in this context")
}
}
}
// MARK: 'OpenAPIMiddleware.swift'
import Vapor
import Dependencies
/// A middleware to inject the request to the context.
/// You might need to use this middleware as the last registered middleware on the app.
struct OpenAPIMiddleware: AsyncMiddleware {
func respond(
to request: Request,
chainingTo responder: AsyncResponder
) async throws -> Response {
/// Inject the request to the context.
try await withDependencies {
$0.request = request
} operation: {
try await responder.respond(to: request)
}
}
}
// MARK: 'MyAPIProtocol.swift'
import OpenAPIVapor
import Dependencies
struct MyAPI: APIProtocol {
@Dependency(\.request) var request
func myOpenAPIEndpointFunction() async throws -> Operations.myOperation.Output {
/// Use `request` as if this is a normal Vapor endpoint function
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment