Search code examples
swiftvaporpreflight

Preflight requests (OPTIONS) failing for local vapor project


I've created a basic backend written in Swift using the Vapor framework. I am running it locally on my machine, so it can be reached at http://localhost:8080.
For the project I'm working on, I'm also building the frontend, which is built using ReactJS and can be reached at http://localhost:3000.

When calling my backend in Postman, with the following info, the request works fine and the user is created in the database:

Method
POST /user

Headers
Content-Type: application/json Accept: application/json

Body

{
    email: "email@example.com
    password: "12345"
}

Now, when calling that same method with the same body & headers from within the local frontend, my request immediately fails, without any response:

failed response

When I inspect the response, I see that all body & headers were sent properly, but there was no response.
I googled a little and realized that Postman (& similar) behave differently than browsers and that I should check whether the method works with OPTIONS, instead of POST. I called the method again: OPTIONS /user and it failed in Postman as well:

failed options call

The only difference is, in Postman, I receive a response, being "Result not found" as you can see in the screenshot.

I thought, it may have something to do with localhost in the API call's url, since the frontend is also running on localhost. So I used ngrok to forward my port 8080 (backend) and then called the *.ngrok.io url, instead of localhost:8080. No luck.
I also tried using my machine's network IP address, instead of localhost. Still no luck.

What can I do about this?


Solution

  • If you configure your backend's CORS settings as follows, it should work:

    Vapor 4

    let corsConfiguration = CORSMiddleware.Configuration(
        allowedOrigin: .all,
        allowedMethods: [.GET, .POST, .PUT, .OPTIONS, .DELETE, .PATCH],
        allowedHeaders: [.accept, .authorization, .contentType, .origin, .xRequestedWith, .userAgent, .accessControlAllowOrigin]
    )
    app.middleware.use(CORSMiddleware(configuration: corsConfiguration))
    


    Vapor 3

    let corsConfiguration = CORSMiddleware.Configuration(
        allowedOrigin: .all,
        allowedMethods: [.GET, .POST, .PUT, .OPTIONS, .DELETE, .PATCH],
        allowedHeaders: [.accept, .authorization, .contentType, .origin, .xRequestedWith, .userAgent, .accessControlAllowOrigin]
    )
    middlewares.use(CORSMiddleware(configuration: corsConfiguration))
    services.register(middlewares)