【问题标题】:Access-Control-Allow-Origin and Angular.js $httpAccess-Control-Allow-Origin 和 Angular.js $http
【发布时间】:2014-01-12 07:38:22
【问题描述】:

每当我制作 web 应用程序并遇到 CORS 问题时,我都会开始制作咖啡。在搞砸了一段时间后,我设法让它工作了,但这次不行,我需要帮助。

这是客户端代码:

$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" ); });

服务器端是带有 express 应用的常规 node.js。我有一个名为 cors 的扩展,它以这种方式与 express 一起使用:

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

如果我这样做了

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

返回:

* 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

如果我运行客户端代码,它会引发此错误:

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 

检查 Chrome 标头:

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

检查请求标头我看到我的测试字符串 X-Random-Shit 存在于“Access-Control-Request-Headers”中,但它的值不存在。此外,在我的脑海中,我希望看到我设置的每个标题都对应一行,而不是一个 blob。

更新 ---

我把我的前端改成了 jQuery 而不是 Angular,我的后端是这样的:

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

现在它适用于 GET,但不适用于其他任何东西(PUT、POST..)。

我会看看你们中是否有人提出了解决方案。与此同时,我们将 RESTful 概念抛到脑后,并使用 GET 完成一切。

【问题讨论】:

  • 咖啡解决了很多问题... =~)

标签: javascript angularjs cors


【解决方案1】:

我是 AngularJS 的新手,遇到了这个 CORS 问题,差点失去理智!幸运的是,我找到了解决此问题的方法。就这样吧……

我的问题是,当我使用 AngularJS $resource 发送 API 请求时,我收到了这个错误消息 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. 是的,我已经添加了 callback="JSON_CALLBACK" 但它不起作用。

我做了什么来解决这个问题,而不是使用 GET 方法或诉诸 $http.get,我使用了 JSONP。只需将 GET 方法替换为 JSONP,并将 api 响应格式也更改为 JSONP。

    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!'
                                        } 
                            }
            } );

    }]);

我希望有人觉得这很有帮助。 :)

【讨论】:

    【解决方案2】:

    我在表达和编辑res.header 方面取得了成功。我的和你的很接近,但我有一个不同的Allow-Headers,如下所述:

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

    我也在使用 Angular 和 Node/Express,但我没有在 Angular 代码中仅调用节点/express 中的标头

    【讨论】:

      【解决方案3】:

      编写这个中间件可能会有所帮助!

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

      详情请访问http://enable-cors.org/server_expressjs.html

      【讨论】:

        【解决方案4】:

        将下面添加到 server.js 解决了我的问题

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

        【讨论】:

          【解决方案5】:

          @Swapnil Niwane

          我能够通过调用 ajax 请求并将数据格式化为“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);
                    }
          });
          

          【讨论】:

            【解决方案6】:

            我找到了一种在$http 中直接使用JSONP 方法并在配置对象中支持params 的方法:

            params = {
              'a': b,
              'callback': 'JSON_CALLBACK'
            };
            
            $http({
              url: url,
              method: 'JSONP',
              params: params
            })
            

            【讨论】:

              【解决方案7】:

              试试这个:

                        $.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);
                            }
                        });
              

              【讨论】:

              • 一点上下文?添加您的解决方案的一些描述
              猜你喜欢
              • 2013-10-28
              • 2016-09-30
              • 2014-03-24
              • 1970-01-01
              • 2017-06-15
              • 2015-06-17
              • 2013-01-20
              • 1970-01-01
              • 2013-11-14
              相关资源
              最近更新 更多