scottoffen / grapevine-legacy

Embedding A REST Server In Your Application Should Be Simple
http://scottoffen.github.io/grapevine-legacy/
Apache License 2.0
209 stars 50 forks source link

Preflight for CORS #230

Closed seikosantana closed 3 years ago

seikosantana commented 3 years ago

I have been struggling for enabling cors in the grapevine REST API. I have read the pinned issue and applied a clean way suggested to enable cors, with the BeforeRouting, just like

public static void CorsPolicy(IHttpContext context)
{
    context.Response.AddHeader("Access-Control-Allow-Origin", "*");
    context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
}

It was that simple, until i get preflight request failures.

I always stick to Fetch API to perform ajax requests. GET requests with cors was good afterall, but not with POST. The BeforeRouting delegate is never invoked when I do the POST request with my browser, but things went smoothly with Postman.

I discovered on my console that No route found for OPTIONS /endpoint was dumped by Grapevine before the request fails related to preflight. When route is not found, the BeforeRouting delegate is not invoked.

After digging around, i found out that when attempting to perform POST request on different origin, our browser would do Preflight Request to ensure the origin really accepts CORS. And just according to that, i made a route for the same endpoint, with OPTIONS method.

[RestRoute(HttpMethod = HttpMethod.POST, PathInfo = "/login")]
public IHttpContext Login(IHttpContext context) //original POST request to handle login

but before that one is invoked, a preflight request will be invoked first, so put

[RestRoute(HttpMethod = HttpMethod.OPTIONS, PathInfo = "/login")]
public IHttpContext PreflightLogin(IHttpContext context)
{
    context.Response.SendResponse(HttpStatusCode.NoContent);
    return context;
}

That way, preflight will receive cors headers before doing the POST request. I came from ExpressJs and it seems there is no issue like OPTIONS route not found.

Is there a way to handle all OPTIONS request just for the preflight? I understand that Grapevine-legacy is in maintenance mode, but maybe this will also help those who wasn't able to to POST request from the browser, and wonder it also occurs as well in Grapevine 5. Looking forward to try it out.

scottoffen commented 3 years ago

This route will respond to all OPTIONS requests regardless of path:

[RestRoute(HttpMethod = HttpMethod.OPTIONS)]
public IHttpContext PreflightLogin(IHttpContext context)
{
    context.Response.SendResponse(HttpStatusCode.NoContent);
    return context;
}

Yes, you would need to do the same thing in Grapevine 5.

Closing this issue. For further discussion, please use the discussions section.