Vapor middleware + services

Hi :slight_smile:

I'm trying to make a middleware that checks if a request contains a valid apple jwt token + check if a user already exists with User.appleId == token.subject.value and create a new user if no user was found + make the token.subject.value available in my routes.

struct AppleSubjectKey: StorageKey {
    typealias Value = String
}

extension Request {
    var appleSubject: String? {
        get {
            self.storage[AppleSubjectKey.self]
        }
        set {
            self.storage[AppleSubjectKey.self] = newValue
        }
    }
}

struct SignInWithAppleMiddleware: AsyncMiddleware {
    func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response {
        guard let token = try? await request.jwt.apple.verify() else {
            throw Abort(.unauthorized)
        }

        // check if user with appleId == token.subject.value
        // create new user if no user was found

        request.appleSubject = token.subject.value
        return try await next.respond(to: request)
    }
}

but while working on this middleware I read somewhere that using this approach the app would risk crashing if the server receive a lot of requests - is this true or would I be fine with this solution?

@henrikac Storage is not thread safe (due to outdated assumptions about server implementations pre-concurrency. That's about to change but the number of requests shouldn't make a difference (where did you read that) since each request is isolated.

The thing you need to be careful of is writing the storage in multiple threads in a Swift concurrency world. However for your use case of write once in middleware, only read later you'll be fine

1 Like

Maybe I misunderstood the post that I read - it might have mentioned something about threads.

But to be sure: I should be fine setting e.g. request.appleSubject = token.subject.value in the middleware (+ searching for and potentially creating a user) and then read request.appleSubject in my routes?

Correct yes, write in middleware read from anywhere after is fine

2 Likes

Cool.

Thank you for taking the time to answer my question :slight_smile:

Is there a "best answer" button?