Access-Control-Allow-Origin and Angular.js $http

109,790

Solution 1

I'm new to AngularJS and I came across this CORS problem, almost lost my mind! Luckily i found a way to fix this. So here it goes....

My problem was, when I use AngularJS $resource in sending API requests I'm getting this error message XMLHttpRequest cannot load http://website.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. Yup, I already added callback="JSON_CALLBACK" and it didn't work.

What I did to fix it the problem, instead of using GET method or resorting to $http.get, I've used JSONP. Just replace GET method with JSONP and change the api response format to JSONP as well.

    myApp.factory('myFactory', ['$resource', function($resource) {

           return $resource( 'http://website.com/api/:apiMethod',
                        { callback: "JSON_CALLBACK", format:'jsonp' }, 
                        { 
                            method1: { 
                                method: 'JSONP', 
                                params: { 
                                            apiMethod: 'hello world'
                                        } 
                            },
                            method2: { 
                                method: 'JSONP', 
                                params: { 
                                            apiMethod: 'hey ho!'
                                        } 
                            }
            } );

    }]);

I hope someone find this helpful. :)

Solution 2

I've had success with express and editing the res.header. Mine matches yours pretty closely but I have a different Allow-Headers as noted below:

res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

I'm also using Angular and Node/Express, but I don't have the headers called out in the Angular code only the node/express

Solution 3

Adding below to server.js resolved mine

    server.post('/your-rest-endpt/*', function(req,res){
    console.log('');
    console.log('req.url: '+req.url);
    console.log('req.headers: ');   
    console.dir(req.headers);
    console.log('req.body: ');
    console.dir(req.body);  

    var options = {
        host: 'restAPI-IP' + ':' + '8080'

        , protocol: 'http'
        , pathname: 'your-rest-endpt/'
    };
    console.log('options: ');
    console.dir(options);   

    var reqUrl = url.format(options);
    console.log("Forward URL: "+reqUrl);

    var parsedUrl = url.parse(req.url, true);
    console.log('parsedUrl: ');
    console.dir(parsedUrl);

    var queryParams = parsedUrl.query;

    var path = parsedUrl.path;
    var substr = path.substring(path.lastIndexOf("rest/"));
    console.log('substr: ');
    console.dir(substr);

    reqUrl += substr;
    console.log("Final Forward URL: "+reqUrl);

    var newHeaders = {
    };

    //Deep-copy it, clone it, but not point to me in shallow way...
    for (var headerKey in req.headers) {
        newHeaders[headerKey] = req.headers[headerKey];
    };

    var newBody = (req.body == null || req.body == undefined ? {} : req.body);

    if (newHeaders['Content-type'] == null
            || newHeaders['Content-type'] == undefined) {
        newHeaders['Content-type'] = 'application/json';
        newBody = JSON.stringify(newBody);
    }

    var requestOptions = {
        headers: {
            'Content-type': 'application/json'
        }
        ,body: newBody
        ,method: 'POST'
    };

    console.log("server.js : routes to URL : "+ reqUrl);

    request(reqUrl, requestOptions, function(error, response, body){
        if(error) {
            console.log('The error from Tomcat is --> ' + error.toString());
            console.dir(error);
            //return false;
        }

        if (response.statusCode != null 
                && response.statusCode != undefined
                && response.headers != null
                && response.headers != undefined) {
            res.writeHead(response.statusCode, response.headers);
        } else {
            //404 Not Found
            res.writeHead(404);         
        }
        if (body != null
                && body != undefined) {

            res.write(body);            
        }
        res.end();
    });
});

Solution 4

Writing this middleware might help !

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,     Content-Type, Accept");
next();
});

for details visit http://enable-cors.org/server_expressjs.html

Solution 5

@Swapnil Niwane

I was able to solve this issue by calling an ajax request and formatting the data to 'jsonp'.

$.ajax({
          method: 'GET',
          url: url,
          defaultHeaders: {
              'Content-Type': 'application/json',
              "Access-Control-Allow-Origin": "*",
              'Accept': 'application/json'
           },

          dataType: 'jsonp',

          success: function (response) {
            console.log("success ");
            console.log(response);
          },
          error: function (xhr) {
            console.log("error ");
            console.log(xhr);
          }
});
Share:
109,790
PCoelho
Author by

PCoelho

I am an Interaction Designer / Prototyper for VMware, in Palo Alto, California.

Updated on January 06, 2020

Comments

  • PCoelho
    PCoelho over 4 years

    Whenever I make a webapp and I get a CORS problem, I start making coffee. After screwing with it for a while I manage to get it working but this time it's not and I need help.

    Here is the client side code:

    $http({method: 'GET', url: 'http://localhost:3000/api/symbol/junk', 
                headers:{
                    'Access-Control-Allow-Origin': '*',
                    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
                    'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With',
                    'X-Random-Shit':'123123123'
                }})
            .success(function(d){ console.log( "yay" ); })
            .error(function(d){ console.log( "nope" ); });
    

    The server side is a regular node.js with an express app. I have an extention called cors and it's being used with express this way:

    var app = express();
    app.configure(function(){
      app.use(express.bodyParser());
      app.use(app.router);
      app.use(cors({origin:"*"}));
    });
    app.listen(3000);
    
    app.get('/', function(req, res){
        res.end("ok");
    });
    

    If I do

    curl -v -H "Origin: https://github.com" http://localhost:3000/
    

    It gets back with:

    * Adding handle: conn: 0x7ff991800000
    * Adding handle: send: 0
    * Adding handle: recv: 0
    * Curl_addHandleToPipeline: length: 1
    * - Conn 0 (0x7ff991800000) send_pipe: 1, recv_pipe: 0
    * About to connect() to localhost port 3000 (#0)
    *   Trying ::1...
    *   Trying 127.0.0.1...
    * Connected to localhost (127.0.0.1) port 3000 (#0)
    > GET / HTTP/1.1
    > User-Agent: curl/7.30.0
    > Host: localhost:3000
    > Accept: */*
    > Origin: https://github.com
    >
    < HTTP/1.1 200 OK
    < X-Powered-By: Express
    < Date: Tue, 24 Dec 2013 03:23:40 GMT
    < Connection: keep-alive
    < Transfer-Encoding: chunked
    <
    * Connection #0 to host localhost left intact
    ok
    

    If I run the client side code, it brigs up this error:

    OPTIONS http://localhost:3000/api/symbol/junk No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. angular.js:7889
    XMLHttpRequest cannot load http://localhost:3000/api/symbol/junk. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. localhost/:1
    nope 
    

    Checking Chromes headers:

    Request URL:http://localhost:3000/api/symbol/junk
    Request Method:OPTIONS
    Status Code:200 OK
    Request Headersview source
    Accept:*/*
    Accept-Encoding:gzip,deflate,sdch
    Accept-Language:en-US,en;q=0.8,es;q=0.6,pt;q=0.4
    Access-Control-Request-Headers:access-control-allow-origin, accept, access-control-allow-methods, access-control-allow-headers, x-random-shit
    Access-Control-Request-Method:GET
    Cache-Control:max-age=0
    Connection:keep-alive
    Host:localhost:3000
    Origin:http://localhost:8000
    Referer:http://localhost:8000/
    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
    Allow:GET
    Connection:keep-alive
    Content-Length:3
    Content-Type:text/html; charset=utf-8
    Date:Tue, 24 Dec 2013 03:27:45 GMT
    X-Powered-By:Express
    

    Checking the request headers I see that my test string X-Random-Shit is present in the "Access-Control-Request-Headers" but it's value is not there. Also, in my head I was expecting to see one line for each one of the headers I am setting, not a blob.

    UPDATES ---

    I changed my frontend to jQuery instead of Angular and made my backend like this:

    var app = express();
    app.configure(function(){
      app.use(express.bodyParser());
      app.use(app.router);
    });
    app.all('*', function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header('Access-Control-Allow-Methods', 'OPTIONS,GET,POST,PUT,DELETE');
        res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
        if ('OPTIONS' == req.method){
            return res.send(200);
        }
        next();
    });
    
    app.get('/', function(req, res){
        res.end("ok");
    });
    

    Now it works with GET but does not with anything else (PUT, POST..).

    I'll see if any of you comes up with a solution. In the mean time in throwing the RESTful concept out the window and making everything with GETs.

    • HaveSpacesuit
      HaveSpacesuit over 7 years
      Coffee solves lots of problems... =~)
  • PyNoob
    PyNoob almost 8 years
    a little context? Add some description of your solution