Last active
February 27, 2024 20:14
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// 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