Handle preflight request with Golang, Revel - go

I made API application with Golang + Revel framework
Now I tried to send http request from front end application, made by vue.js.
But because of cors, PUT method cannot be handled.(POST method worked fine now)
In revel, I thought we can set header in app/init.go file, like this
var HeaderFilter = func(c *revel.Controller, fc []revel.Filter) {
c.Response.Out.Header().Add("X-Frame-Options", "SAMEORIGIN")
c.Response.Out.Header().Add("X-XSS-Protection", "1; mode=block")
c.Response.Out.Header().Add("X-Content-Type-Options", "nosniff")
c.Response.Out.Header().Add("Referrer-Policy", "strict-origin-when-cross-origin")
// Add them by myself
c.Response.Out.Header().Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept")
c.Response.Out.Header().Add("Access-Control-Allow-Origin", "*")
c.Response.Out.Header().Add("Access-Control-Allow-Method", "POST, GET, OPTIONS, PUT, DELETE")
c.Response.Out.Header().Add("Content-Type", "application/json; charset=UTF-8")
fc[0](c, fc[1:]) // Execute the next filter stage.
But still I got 404 error from API and request method is shown as OPTIONS.
How can I set request header to enable to handle every requests ?

Add a filters before revel.PanicFilter
revel.Filters = []revel.Filter{
ValidateOrigin,
revel.PanicFilter, // Recover from panics and display an error page instead.
revel.RouterFilter, // Use the routing table to select the right Action
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
revel.ParamsFilter, // Parse parameters into Controller.Params.
IpLimitFilter,
revel.SessionFilter, // Restore and write the session cookie.
revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
revel.I18nFilter, // Resolve the requested language
HeaderFilter,
revel.InterceptorFilter, // Run interceptors around the action.
revel.CompressFilter, // Compress the result.
revel.BeforeAfterFilter, // Call the before and after filter functions
revel.ActionInvoker, // Invoke the action.
}
var ValidateOrigin = func(c *revel.Controller, fc []revel.Filter) {
if c.Request.Method == "OPTIONS" {
c.Response.Out.Header().Add("Access-Control-Allow-Origin", "*")
c.Response.Out.Header().Add("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization") //自定义 Header
c.Response.Out.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
c.Response.Out.Header().Add("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
c.Response.Out.Header().Add("Access-Control-Allow-Credentials", "true")
c.Response.SetStatus(http.StatusNoContent)
// 截取复杂请求下post变成options请求后台处理方法(针对跨域请求检测)
} else {
c.Response.Out.Header().Add("Access-Control-Allow-Headers", "Origin, Content-Type, Accept")
c.Response.Out.Header().Add("Access-Control-Allow-Origin", "*")
c.Response.Out.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
c.Response.Out.Header().Add("Content-Type", "application/json; charset=UTF-8")
c.Response.Out.Header().Add("X-Frame-Options", "SAMORIGIN")
c.Response.Out.Header().Add("Vary", "Origin, Access-Control-Request-Method, Access-Control-Request-Headers")
fc[0](c, fc[1:]) // Execute the next filter stage.
}
}
...
Because ajax turns a simple request (single post) request into a secondary request, that is, an options request is first sent to determine whether the domain is allowed, and then the real request post is sent to obtain the result.

Related

Http OPTION REQUEST with cors in web api with authentication

I am using Microsoft.AspNet.WebApi.Cors to support cross origin request as per this
https://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
My web apis are configured to use windows authentication and every request coming from angular has withCredentials set to true. Everything is working with HTTP GET but with PUT request sends preflight request which in getting unauthorised. My question is does Microsoft.AspNet.WebApi.Cors support configuration of OPTION request.
Put this in your Global.asax.cs
(I'm sure you either found a solution or gave up, but this is the link that I found on Google while looking for a solution to this.)
protected void Application_BeginRequest()
{
if (Request.HttpMethod == "OPTIONS")
{
Response.StatusCode = (int)HttpStatusCode.OK;
Response.AppendHeader("Access-Control-Allow-Origin", Request.Headers.GetValues("Origin")[0]);
Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
Response.AppendHeader("Access-Control-Allow-Credentials", "true");
Response.End();
}
}

Angular2 : X-XSRF-TOKEN is not allowed by Access-Control-Allow-Headers

I am struggling with this issue today as I am implementing a cross-site API call. The worst thing is it works well from my local environment but once on heroku, it fails with the following error:
XMLHttpRequest cannot load https://restcountries.eu/rest/v1/all. Request header field X-XSRF-TOKEN is not allowed by Access-Control-Allow-Headers in preflight response.
Here is the function triggering the call:
let observable = this._http
.get(GEO_API_URL + query)
.map(response => response.json())
.do(val => {
this.cache = val;
observable = null;
})
.share();
return observable;
Any idea ?
Thanks.
Had the same issue.
In my case the reason was that in my Chrome cookies was saved X-XSRF-TOKEN field. And somehow Chrome added header 'Access-Control-Request-Headers: x-xsrf-token' to OPTION request. In Firefox the same page works fine, in incognito mode Chrome - too.
So I've just delete this cookies field (X-XSRF-TOKEN) and that's all.
In my case I had to add the 'x-xsrf-token' value to 'Access-Control-Allow-Headers' header:
header('Access-Control-Allow-Headers: Content-Type, x-xsrf-token')
see AngularJS: POST Data to External REST API
I cleared cookies, this solved problem.
this helped me in java (expose the headers and then include in the allow headers). This will then show in your HttpResponse object:
response.addHeader("Access-Control-Expose-Headers", "header1");
response.addHeader("Access-Control-Expose-Headers", "header2");
response.addHeader("Access-Control-Expose-Headers", "header3");
response.addHeader("Access-Control-Allow-Headers", "Origin, header1, header2, header3, X-Requested-With, Content-Type, Accept");
The reason is that x-xsrf-token keyword is not in response header Access-Control-Allow-Headers.
I solved this problem in java using following solution:
rsp.setHeader("Access-Control-Allow-Methods", "GET,HEAD,POST,OPTIONS,PUT,DELETE,TRACE,CONNECT");
rsp.setHeader("Access-Control-Allow-Headers", "cache-control,content-type,hash-referer,x-requested-with, x-xsrf-token");
if ("OPTIONS".equals(req.getMethod())) {
rsp.setStatus(HttpServletResponse.SC_OK);
return;
}

OPTIONS request returns "No 'Access-Control-Allow-Origin' header" error during ajax POST to a different domain

I'm struggling with CORS issue. I make a request from js to a different domain, the method allows cross domain request and all works fine with GET but not with POST request. Looks like OPTIONS method is called before the POST and return standard error
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
return Response.ok().entity(c).header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS")
.header("Access-Control-Allow-Headers", "Content-Type, x-xsrf-token, X-Requested-With, Accept, Expires, Last-Modified, Cache-Control").build();
On the client side I use angularjs
$http.post(url, data).success(...)
But also tried with
$.ajax({type:'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}...})
the same result. what else can I do to fix POST request?
Add the below code to your Angular JS application config file
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

Sending ajax request between https

I'm using angular to send ajax request to nodejs file, and I'm having this error,
XMLHttpRequest cannot load https://localhost:3000/SetUser. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost' is therefore not allowed access.
sending it from index.html to https://localhost:3000/SetUser, and direction what could go wrong and how can I allow that access of Access-Control-Allow-Origin?
-- edit:
I googled and I found this lines
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
but I still get the same error, this is the current app.post
app.post('/SetUser', function(req, res) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
console.log("New user added ", req.body);
});
thanks!

HTTP OPTIONS error in Phil Sturgeon's Codeigniter Restserver and Backbone.js

My backbone.js application throwing an HTTP OPTIONS not found error when I try to save a model to my restful web service that's located on another host/URL.
Based on my research, I gathered from this post that :
a request would constantly send an OPTIONS http request header, and not trigger the POST request at all.
Apparently CORS with requests that will "cause side-effects on user data" will make your browser "preflight" the request with the OPTIONS request header to check for approval, before actually sending your intended HTTP request method.
I tried to get around this by:
Settting emulateHTTP in Backbone to true.
Backbone.emulateHTTP = true;
I also allowed allowed all CORS and CSRF options in the header.
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
The application crashed when the Backbone.emulateHTTP line of code was introduced.
Is there a way to respond to OPTIONS request in CodeIgniter RESTServer and are there any other alternatives to allow either disable this request from talking place?
I found this on Github as one solution. I am not sure if I should use it as it seems a bit outdated.
I encountered exactly the same problem. To solve it I have a MY_REST_Controller.php in core and all my REST API controllers use it as a base class. I simply added a constructor like this to handle OPTIONS requests.
function __construct() {
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method");
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
$method = $_SERVER['REQUEST_METHOD'];
if($method == "OPTIONS") {
die();
}
parent::__construct();
}
This just checks if the request type is OPTIONS and if so just dies out which return a code 200 for the request.
You can also modify the $allowed_http_methods property in your subclass to exclude the options method. Previous versions of REST_controller did nothing with OPTIONS and adding this line seems to mimic that behavior:
protected $allowed_http_methods = array('get', 'delete', 'post', 'put');
I solved in this way:
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE");
header("Access-Control-Allow-Headers: X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Request-Method, x_requested_with");
if ( "OPTIONS" === $_SERVER['REQUEST_METHOD'] ) {
die();
}
Pay attention to add x_requested_with in Access-Control-Allow-Headers.

Resources