Angular + Rails Access-Control Headers - javascript

I'm getting an Access-Control-Allow-Origin error when doing an $http.post to the opencalais API from my Angular controller in my Rails app:
XMLHttpRequest cannot load https://api.thomsonreuters.com/permid/calais?access-token=APIKEY. The 'Access-Control-Allow-Origin' header has a value 'http://developer.permid.org' that is not equal to the supplied origin. Origin 'http://localhost:3000' is therefore not allowed access.
Here's the API call inside my Angular controller:
function fetchTags() {
var token = API-KEY,
query = $scope.brief.description;
$http.post('https://api.thomsonreuters.com/permid/calais?access-token=' + token, query, {
headers: {
'Content-Type': 'text/raw',
'OutputFormat': 'application/json',
'X-AG-Access-Token': API-KEY,
'Access-Control-Allow-Origin': '*'
}
}).success(function(data) {
console.log(data);
});
}
I've read and tried several different ways of setting the Access-Control headers, either through the Angular request or even through something like a before_filter in the Rails application_controller.rb, but they all seem to result in the same response.
Furthermore, I've replicated the request in Postman, just by setting the URL and Headers to the same as above, and it works perfectly.
Any ideas or links would be greatly appreciated, thanks
EDIT: Here's the request/response headers from Chrome:
Request:
OPTIONS /permid/calais?access-token=API-KEY HTTP/1.1
Host: api.thomsonreuters.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36
Access-Control-Request-Headers: accept, access-control-allow-origin, content-type, outputformat, x-ag-access-token, x-csrf-token
Accept: /
DNT: 1
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Response:
HTTP/1.1 200 OK
Content-Type: application/json
Access-Control-Allow-Origin: http://developer.permid.org
Access-Control-Allow-Headers: accept, x-ag-access-token, authorization, outputformat, content-type, x-openmatch-numberofmatchesperrecord, x-openmatch-datatype, x-calais-language
Access-Control-Max-Age: 3628800
Access-Control-Allow-Methods: GET, POST, OPTIONS
Origin: http://localhost:3000
Content-Length: 0
Connection: keep-alive

Related

CORS 405 Method Not Allowed even though I have the right headers (I think)

I need some more eyes on this. My preflight request is failing with 405 Method Not Allowed.
As far as I can tell it should be working. Here's my request:
OPTIONS http://diffDomain/spf/v1/user/user#example.com/password/change
HTTP/1.1
Host: diffDomain.com
Connection: keep-alive
Access-Control-Request-Method: PUT
Origin: http://www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36
Accept: */*
Referer: http://www.example.com/appName/index.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,es-US;q=0.8,es;q=0.6,en;q=0.4
Response:
HTTP/1.1 405 Method Not Allowed
Date: Thu, 14 Sep 2017 02:06:30 GMT
Server: Apache/2.4.7 (Ubuntu)
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, DELETE
X-Powered-By: PHP/5.5.9-1ubuntu4.20
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type, api_key, Authorization, Accept
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json
I'm waiting for access to the server so that I can add Access-Control-Request-Method to the Access-Control-Allow-Headers line. Would that help?
I just need some eyes, because I've been debugging this for a few hours today and I don't have access to the server yet.
When I do as #sideshowbarker suggested below i get:
> curl -i -X OPTIONS http://diffDomain.com/spf/v1/user/user#example.com/password/change
HTTP/1.1 500 Internal Server Error
Date: Thu, 14 Sep 2017 21:25:39 GMT
Server: Apache/2.4.7 (Ubuntu)
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, DELETE
X-Powered-By: PHP/5.5.9-1ubuntu4.20
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Content-Type, api_key, Authorization, Accept, Content-Type, api_key, Authorization, Accept, Access-Control-Request-Method, Origin
Content-Length: 0
Connection: close
Content-Type: application/json
I don't know how your backend looks like, but what I would suggest you is to add a middleware that intercepts every OPTIONS and return a 200 response and moving to the next request.
To clarify here is a post about this issue with Laravel based APIs.
I hope it helps.

How to solve CORS redirection with express js router?

I'm trying to implement OAuth2 authentication. When I try to send Authorization code I get this error:
XMLHttpRequest cannot load link1.
Redirect from link1 to link2
has been blocked by CORS policy: Request requires preflight, which is
disallowed to follow cross-origin redirect.
My req/rsp looks like this:
General:
Request URL:link1
Request Method:OPTIONS Status Code:204 No
Content Remote Address:
Response Headers: HTTP/1.1 204 No Content X-Powered-By: Express
Access-Control-Allow-Origin: * Access-Control-Allow-Methods:
GET,HEAD,PUT,PATCH,POST,DELETE Access-Control-Allow-Headers:
content-type, sessionid Date:
Request Headers: OPTIONS /authorize HTTP/1.1 Host: host Connection:
keep-alive Access-Control-Request-Method: POST Origin: origin_link
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/56.0.2924.76 Safari/537.36
Access-Control-Request-Headers: content-type, sessionid Accept: /
Referer: origin_link/dialog Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8
Maybe you have not configured express to accept CORS request.
In a small project, I had to configure CORS request in an Express application. My code was:
// Enable CORS
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested With, Content-Type, Accept');
next();
});
app is a variable corresponding to an Express instance.
Moreover, I did find an npm package to set CORS request to an express app, but I have never used it:
https://github.com/expressjs/cors

hapi.js Cors Pre-flight not returning Access-Control-Allow-Origin header

I have an ajax file upload using (Dropzone js). which sends a file to my hapi server. I realised the browser sends a PREFLIGHT OPTIONS METHOD. but my hapi server seems not to send the right response headers so i am getting errors on chrome.
here is the error i get on chrome
XMLHttpRequest cannot load http://localhost:3000/uploadbookimg. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.
this is the hapi js route handler
server.route({
path: '/uploadbookimg',
method: 'POST',
config: {
cors : true,
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
handler: require('./books/webbookimgupload'),
}
});
In my understanding hapi js should send all cors headers from the Pre-fight (OPTIONS) request.
Cant understand why its is not
Network request /response from chrome
**General**
Request Method:OPTIONS
Status Code:200 OK
Remote Address:127.0.0.1:3000
**Response Headers**
view parsed
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
cache-control: no-cache
vary: accept-encoding
Date: Wed, 27 Apr 2016 07:25:33 GMT
Connection: keep-alive
Transfer-Encoding: chunked
**Request Headers**
view parsed
OPTIONS /uploadbookimg HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36
Access-Control-Request-Headers: accept, cache-control, content-type
Accept: */*
Referer: http://localhost:4200/books/upload
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Thanks in advance
The hapi cors: true is a wildcard rule that allows CORS requests from all domains except for a few cases including when there are additional request headers outside of hapi's default whitelist:
["accept", "authorization", "content-type", "if-none-match", "origin"]
See the cors option section in the API docs under route options:
headers - a strings array of allowed headers ('Access-Control-Allow-Headers'). Defaults to ['Accept', 'Authorization', 'Content-Type', 'If-None-Match'].
additionalHeaders - a strings array of additional headers to headers. Use this to keep the default headers in place.
Your problem is that Dropzone sends a couple of headers along with the file upload that aren't in this list:
x-requested-with (not in your headers above but was sent for me)
cache-control
You have two options to get things working, you need to change something on either the server or the client:
Option 1 - Whitelist the extra headers:
server.route({
config: {
cors: {
origin: ['*'],
additionalHeaders: ['cache-control', 'x-requested-with']
}
},
method: 'POST',
path: '/upload',
handler: function (request, reply) {
...
}
});
Option 2 - Tell dropzone to not send those extra headers
Not possible yet through their config but there's a pending PR to allow it: https://github.com/enyo/dropzone/pull/685
I want to add my 2 cents on this one as the above did not fully resolve the issue in my case.
I started my Hapi-Server at localhost:3300. Then I made a request from localhost:80 to http://localhost:3300/ to test CORS. This lead to chrome still blocking the ressource because it said that
No 'Access-Control-Allow-Origin' header is present on the requested
resource
(which was not true at all).
Then I changed the XHR-Request to fetch the url to a url for which I actually created a route inside HapiJS which - in my case - was http://localhost:3300/api/test. This worked.
To overgo this issue I created a "catch-all" route in HapiJS (to overgo the built-in 404 catch).
const Boom = require('Boom'); //You can require Boom when you have hapi
Route({
method: '*',
path: '/{any*}',
handler: function(request, reply) {
reply(Boom.notFound());
}
})

Angular $resource calls not accepted by Access Control Allow with Safari vs. accepted with Chrome

I've been a bit stuck on this for a while now, and since I'm new to angular and web development I don't know where to look.
I've built a simple service that makes calls to a RESTapi which is set to accept Cross Origin calls, using the $resource service in Angular:
angular.module('vinifyApp')
.factory('WinesVinibar',function($resource){
return $resource('http://devinify1.herokuapp.com/wines/');
})
.controller('GetWinesVinibarCtrl', function($scope, WinesVinibar){
$scope.WINES = WinesVinibar.query();
}
I have tested this service locally and on heroku, it works fine with Chrome and Firefox. Here are the request and response for Chrome:
Request
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:devinify1.herokuapp.com
Origin:http://mobilevinify.herokuapp.com
Referer:http://mobilevinify.herokuapp.com/
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
Response Headersview source
Access-Control-Allow-Origin:*
Allow:GET, POST, HEAD, OPTIONS
Connection:keep-alive
Content-Type:application/json
Date:Mon, 09 Dec 2013 16:16:36 GMT
Server:gunicorn/18.0
transfer-encoding:chunked
Vary:Accept, Cookie
However, the request fails with Safari with the following error:
[Error] Failed to load resource: Request header field Accept-Encoding is not allowed by Access-Control-Allow-Headers. (wines, line 0)
Here are the request and response headers:
Request
Access-Control-Request-Method GET
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71
Access-Control-Request-Headers accept-language, origin, accept-encoding
Response
Access-Control-Max-Age 86400
Access-Control-Allow-Methods GET, POST, PUT, PATCH, DELETE, OPTIONS
Content-Type text/html; charset=utf-8
Access-Control-Allow-Origin *
Connection keep-alive
Access-Control-Allow-Headers x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Content-Length 0
There seems to be an issue with the encoding, but I don't know wher to go and fix that.
Thanks for your time !
It seems like you have missed out some parameters in the CORS_ALLOW_HEADERS settings:
Request:
Access-Control-Request-Headers accept-language, origin, accept-encoding
Response:
Access-Control-Allow-Headers x-requested-with, content-type, accept, origin, authorization, x-csrftoken
Try to add accept-language and accept-encoding to your headers in your settings.py
CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken',
'accept-encoding',
'accept-language'
)

CORS Ajax post with Jetty/Firefox

I'm trying to do a cross-domain POST with jQuery using CORS, but after the OPTIONS request is sent (and responded to), the POST doesn't happen. My request/response filters are shown below. My jQuery post code is also shown. It looks like the response has the proper CORS response headers, so I'm not sure why this isn't working.
var params = {};
params.data = myPostData;
params.headers = {
'x-pingother' : 'pingpong'
};
$.ajax(params);
Request Header
OPTIONS /my/service/url HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://localhost:9876
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type,x-pingother
Pragma: no-cache
Cache-Control: no-cache
Response Header:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:9876
Access-Control-Allow-Methods: POST,GET,OPTIONS
Access-Control-Allow-Headers: x-pingother
Content-Length: 703
Content-Type: application/vnd.sun.wadl+xml
Allow: OPTIONS,POST
Last-Modified: Sat, 19 Jan 2013 13:46:51 EST
Server: Jetty(6.1.25)
I'm running automated tests from a local server (JSTestDriver) that connects to a web server running on a different port. The web server runs on 8080 and the page making the request runs on 9876.
This was solved by adding the response headers as specified in
jQuery CORS request not working when sending Range request
Did you try to explicitly tell jQuery to enable cors?
$.support.cors = true;

Categories

Resources