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