0

angularjs中的JSONP请求失败

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

我的本地网络服务器返回的内容存储在 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 或猴子)网络服务器发出请求时,它会失败并显示以下控制台日志记录;

 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 地址而不是 localhost
  • 使用主机名而不是 IP 地址
  • 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
4

1 回答 1

1

Angular 将JSON_CALLBACK在您的 url 中替换为特定的回调名称,例如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。我的猜测是这可能是错误的原因。

于 2014-11-15T17:55:08.480 回答