【发布时间】:2021-11-08 20:12:13
【问题描述】:
对于我的小型 Javascript 应用程序,我使用 CGI 编写了服务器端 API 函数。
我把它做得很简单,完整的示例脚本如下所示:
#!/usr/bin/env perl
use strict; use warnings; use 5.014;
use CGI;
use JSON;
use Data::Dumper;
my $q = new CGI;
my %p = $q->Vars;
_api_response();
sub _api_response {
my ( $error ) = @_;
my $res;
my $status = 200;
my $type = 'application/json';
my $charset = 'utf-8';
if ( $error ) {
$status = 500;
$res->{data} = {
status => 500,
};
$res->{error} = {
error => 'failure',
message => $error,
detail => Dumper \%p,
};
} else {
$res->{data} = {
status => 200,
};
}
print $q->header(
-status => $status,
-type => $type,
-charset => $charset,
);
my $body = encode_json( $res );
print $body;
}
当我使用 fetch 从 JS 脚本调用它时,它没有得到响应体。如果我从开发者工具/网络检查,它也没有响应正文。如果我在浏览器中输入相同的 URL,它会显示 JSON 正文。如果我使用curl 作为
curl -v 'https://example.com/my_api?api=1;test=2;id=32'
响应似乎也有正确的正文:
< HTTP/2 200
< date: Mon, 13 Sep 2021 14:04:42 GMT
< server: Apache/2.4.25 (Debian)
< set-cookie: example=80b7b276.5cbe0f250c6c7; path=/; expires=Thu, 08-Sep-22 14:04:42 GMT
< cache-control: max-age=0, no-store
< content-type: application/json; charset=utf-8
<
* Connection #0 to host example.com left intact
{"data":{"status":200}}
为什么fetch 不将其视为一个身体?
为了完整起见,我还包括了 JS 部分:
async function saveData(url = '', data = {}) {
const response = await fetch(url, {
method: 'GET',
mode: 'no-cors',
cache: 'no-cache',
credentials: 'omit',
headers: {
'Content-Type': 'application/json'
},
redirect: 'follow',
referrerPolicy: 'no-referrer',
});
console.log(response); // body is null
return response.json();
}
使用函数为:
saveData('https://example.com/my_api?api=1;test=2;id=32', { answer: 42 })
.then(data => {
console.log(data);
})
.catch( error => {
console.error( error );
});
在控制台我看到错误:
SyntaxError: Unexpected end of input
此错误的一个可能原因是空 JSON 字符串。
【问题讨论】:
-
为什么
fetch中有content-type标头?该标头指定请求正文的内容类型,但没有请求正文,因为它是 GET 请求。为了向服务器发出信号,您应该使用Accept标头接受什么样的内容。另请注意,您没有在curl命令中发送此标头,因此此标头实际上可能是问题所在。 -
@SteffenUllrich
content-type显然是不必要的,但忽略它并没有改变。 -
你在 Perl 端做过调试吗?您在服务器日志中看到了什么?
-
你打电话给
_api_response()没有任何参数。_api_response(@args)需要一些参数,如果没有提供参数,那么你最终会得到print $q->header(...)和print $body其中 body 是json { status => 200 }(正是来自 Web 浏览器的请求接收)。看起来您的问题出在 JavaScript 中,出于调试目的添加 Perl 代码验证块,它将接收到的数据转储到文件中以研究可能导致问题的原因。 -
我可以用您显示的代码重现您的问题。
标签: javascript api perl cgi fetch-api