angularjs $ http JSONP方法返回http状态代码0

时间:2014-11-15 15:55:52

标签: javascript angularjs jsonp http-status

angularjs中的JSONP请求失败

运行以下angularjs代码以检索JSONP数据时,在向https://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Herohttp://code.jsontest.com?callback=JSON_CALLBACK发出请求时,它可以正常工作。但是当向我的本地(bash或monkey)网络服务器发出请求时,它失败了。

我本地网络服务器的返回内容存储在wcontent

export wcontent='JSON_CALLBACK([ 
    {"msg":"Message one"}, 
    {"msg":"Message two"} 
    ]);'

bash脚本网络服务器代码是

while true; do cat <<EOF | nc -l 8024 ; done
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/javascript; charset=ISO-8859-1
Vary: Accept-Encoding
Date: `date`
Server: Google Frontend
Cache-Control: private
Content-Length: ${#wcontent}

${wcontent}
EOF

通过firefox请求url时,会返回带有正常响应头的HTTP 200。响应也是正常的并且被识别为js(javascript),这对于JSONP数据是正确的。

使用以下angularjs代码。

function messagesController ($scope,$http,$templateCache) {

    $scope.fetch = function() {

        console.log("messagesController FETCH Method:" + $scope.method + "  Url:"  + $scope.url ) ;

        $scope.code = null;
        $scope.response = null;

        $http({method: $scope.method, url: $scope.url, cache: $templateCache, timeout: 5000}).
            success(function(data, status) {
                $scope.status = status;
                $scope.data = data;
                $scope.msgs = $scope.data;
                console.log("Fetch SUCCESS ") ;
                console.log("method "+ $scope.method ) ;
                console.log("status " + status) ;
                console.log("data") ;
                console.dir(data) ;
            }).
            error(function(data, status, headers, config) {
                $scope.data = data || "Request failed";
                $scope.status = status;
                console.log("Fetch ERROR") ;                  
                console.log("method " + $scope.method) ;
                console.log("data") ;
                console.dir(data) ;
                console.log("Status:" + status ) ;
                console.log("Headers" + headers) ;
                console.dir(headers) ;
                console.log("config") ;
                console.dir(config);

            });
        };

    $scope.updateModel = function(method, url) {
    $scope.method = method;
    $scope.url = url;
};

当向任何前面提到的外部JSONP对象发出请求时,将检索JSONP对象。当向(bash或monkey)web服务器发出请求时,它会失败并显示以下控制台记录;

 messagesController FETCH method:JSONP Url://http://127.0.0.1:8024/?callback=JSON_CALLBACK
 Fetch ERROR
 method JSONP
 data
     undefined
 Status: 0
 Headersfunction(name) {
 "use strict";

     if (!headersObj) headersObj = parseHeaders(headers) ;

     if (name) {
        return headersObj[lowercase(name)] || null ;
     }

     return headersObj;
 }
 [object Function] 
 "config"
 [object Object]

因此它返回HTTP状态代码0.并且基于输出标头,似乎有一些HTTP标头。

我尝试了什么;

  • 我尝试过不同的HTTP标头组合。
  • 2个不同版本的网络服务器
  • 使用外部ip-address而不是localhost
  • 使用主机名而不是ip-address
  • AngularJS 1.2.1,1.2.26和1.3.2

任何可以帮助我解决这个问题的人?

20141115在使用angularjs

发出请求时,添加了使用tcpdump创建的HTTP标头

请求

GET /?callback=angular.callbacks._1 HTTP/1.1
Host: reddipped.localdomain:8024
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:7002/console/console.portal?_nfpb=true&_pageLabel=HomePage1
Connection: keep-alive

回复

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/javascript; charset=ISO-8859-1
Vary: Accept-Encoding
Date: Sat Nov 15 23:14:52 CET 2014
Server: Google Frontend
Cache-Control: private
Content-Length: 91

JSON_CALLBACK([ 
        {"msg":"Message one"}, 
        {"msg":"Message two"} 
        ]);

为了其他人的利益,这里有一个重写的bash http服务器,可以测试使用angularjs发出的JSONP请求。请参阅Roman L的答案以获得解释。

#!/bin/bash
#
#

# reads JSON Data
function loadJSON(){

        echo '[
                {"msg":"Message 1"},
                {"msg":"Anonco 2"},
                {"msg":"Avis 3"}
        ]'

}

# proces HTTP JSONP request
function procesRequest() {

   # Read first line of HTTP request,this line has the format
   # "Method SP Request-URI SP HTTP-Version CRLF"
   read request
   # Get callback url variable value which is requested JSONP callback 
   # function name 
   callback=$(echo $request | sed -r 's/.*callback=(.*) .*/\1/g ; /GET/{q100}')
   if [ "$?" -eq "100" ] || [ -z "$callback" ]; then
     callback="JSONP_CALLBACK"
   fi
   # Create response body
   wcontent=${callback}"("$(loadJSON)");"

   # Compose response
cat <<EOF
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/javascript;
Date: `date`
Server: Reddipped Bash
Cache-Control: no-cache
Content-Length: ${#wcontent}

${wcontent}
EOF

  ## Clearing buffer
  while read -t 1; do
    true
  done

}

# Listen Port
PORT=8024

# Setup named pipe to pass HTTP response back to netcat
TMP=`mktemp -d`
LOOP=$TMP/pipe.loop
REQ=$TMP/pipe.req
RPY=$TMP/pipe.rpy
trap 'rm -rf "$TMP"' EXIT
mkfifo -m 0600 "$LOOP" "$REQ" "$RPY"
sed 's/^/-REQUEST->/' <"$REQ" &
sed 's/^/<--REPLY--/' <"$RPY" &


echo Waiting for HTTP request
nc -r -l $PORT <"$LOOP" | tee "$REQ" | procesRequest | tee "$RPY" >"$LOOP"
echo Send HTTP response
nohup $0

1 个答案:

答案 0 :(得分:1)

Angular会使用特定的回调名称替换您网址中的JSON_CALLBACK,例如cb_0,因此实际请求看起来像server?callback=cb_0。您的服务器必须返回包含在此回调中的JSON

cb_0([ 
  {"msg":"Message one"}, 
  {"msg":"Message two"} 
])

尝试更改链接中的回拨名称,并在浏览器中查看回复:https://angularjs.org/greet.php?name=Super%20Hero&callback=cb_0

更新

如果我正确理解了您的bash代码,当您导航到http://127.0.0.1:8024/?callback=cb_0时,您会看到此输出:

JSON_CALLBACK([ 
  {"msg":"Message one"}, 
  {"msg":"Message two"} 
]);

你应该看到cb_0。我的猜测是这可能是错误的原因。