为什么我的 micro-API 没有反应 body?
Why my micro-API does not have response body?
对于我的 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 脚本调用它时,它没有得到任何响应 body。如果我从开发人员 Tools/Network 那里检查过,它也没有响应 body。如果我在浏览器中输入相同的 URL,它会显示 JSON body。如果我使用 curl
作为
curl -v 'https://example.com/my_api?api=1;test=2;id=32'
回复好像也正确body:
< 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
不认为它是 body?
为了完整起见,我也包括了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 字符串为空。
你也必须 await
response.json()
。
试试 return await response.json();
,而不是 return response.json();
我能够重现您的问题,然后我能够修复它。
这是一个 CORS 问题。前后端都需要开启CORS
在前端,您需要在页面的 <head>
:
中使用元标记设置内容安全策略
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost">
(不要忘记将 localhost
更改为您的真实域名。)
后面需要添加CORs头:
print $q->header(
-status => $status,
-type => $type,
-charset => $charset,
-access_control_allow_origin => '*', # <-- add this line
);
附带说明一下,您传递给 fetch
的设置中有 none 是必需的。而且由于您正在等待响应,然后无论如何都会返回另一个承诺,因此实际上没有理由将其作为异步函数。
在您准备好使用未使用的 data
参数之前,以下代码就足够了:
function saveData(url = '', data = {}) {
return fetch(url).then(response=>response.json());
}
对于我的 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 脚本调用它时,它没有得到任何响应 body。如果我从开发人员 Tools/Network 那里检查过,它也没有响应 body。如果我在浏览器中输入相同的 URL,它会显示 JSON body。如果我使用 curl
作为
curl -v 'https://example.com/my_api?api=1;test=2;id=32'
回复好像也正确body:
< 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
不认为它是 body?
为了完整起见,我也包括了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 字符串为空。
你也必须 await
response.json()
。
试试 return await response.json();
,而不是 return response.json();
我能够重现您的问题,然后我能够修复它。
这是一个 CORS 问题。前后端都需要开启CORS
在前端,您需要在页面的 <head>
:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost">
(不要忘记将 localhost
更改为您的真实域名。)
后面需要添加CORs头:
print $q->header(
-status => $status,
-type => $type,
-charset => $charset,
-access_control_allow_origin => '*', # <-- add this line
);
附带说明一下,您传递给 fetch
的设置中有 none 是必需的。而且由于您正在等待响应,然后无论如何都会返回另一个承诺,因此实际上没有理由将其作为异步函数。
在您准备好使用未使用的 data
参数之前,以下代码就足够了:
function saveData(url = '', data = {}) {
return fetch(url).then(response=>response.json());
}