31

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.

1
  • Coffee solves lots of problems... =~) Commented Dec 8, 2016 at 18:16

7 Answers 7

8

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. :)

Sign up to request clarification or add additional context in comments.

Comments

4

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

Comments

1

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

Comments

1

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();
    });
});

Comments

1

@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);
          }
});

Comments

0

I have found a way to use JSONP method in $http directly and with support of params in the config object:

params = {
  'a': b,
  'callback': 'JSON_CALLBACK'
};

$http({
  url: url,
  method: 'JSONP',
  params: params
})

Comments

-1

Try with this:

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

              data: obj,
              dataType: 'json',
              success: function (response) {
            //    BindTableData();
                console.log("success ");
                alert(response);
              },
              error: function (xhr) {
                console.log("error ");
                console.log(xhr);
              }
          });

1 Comment

a little context? Add some description of your solution

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.