For my little Javascript app I wrote serverside API function with CGI.
I made it very simple, and full example script looks like that:
#!/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;
}
When I call it from JS script with fetch
, it gets no response body. If I checked from Developers Tools/Network, it has also no response body. If I enter the same URL into browser, it shows JSON body. If I use curl
as
curl -v 'https://example.com/my_api?api=1;test=2;id=32'
response seems have also correct 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}}
Why fetch
does not see it as a body?
For sake of completeness, I include JS part also:
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();
}
Using the function as:
saveData('https://example.com/my_api?api=1;test=2;id=32', { answer: 42 })
.then(data => {
console.log(data);
})
.catch( error => {
console.error( error );
});
On console I see error:
SyntaxError: Unexpected end of input
One possible reason for this error is empty JSON string.
2
Answers
You have to
await
forresponse.json()
too.Try
return await response.json();
, instead ofreturn response.json();
I was able to reproduce your problem, and then I was able to fix it.
It was a CORS issue. You need to enable CORS on both the front and the back end.
On the front end you need to set the content security policy with a meta tag in your page’s
<head>
:(Don’t forget to change
localhost
to whatever your real domain is.)On the back you need to add the CORs header:
As a side note, none of the settings you’re passing into
fetch
are necessary. And since you’re awaiting the response and then returning another promise anyway, there is really no reason for that to even be a an async function.Until you’re ready to do something with the unused
data
argument, the following code will suffice: