Para mi pequeña aplicación Javascript, escribí la función API del servidor con CGI .
Lo hice muy simple, y el script de ejemplo completo se ve así:
#!/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; } Cuando lo llamo desde el script JS con fetch , no recibe ningún cuerpo de respuesta. Si revisé desde Developers Tools/Network, tampoco tiene cuerpo de respuesta. Si ingreso la misma URL en el navegador, muestra el cuerpo JSON. Si uso curl como
curl -v 'https://example.com/my_api?api=1;test=2;id=32'la respuesta parece tener también el cuerpo correcto:
< 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}} ¿Por qué fetch no lo ve como un cuerpo?
En aras de la exhaustividad, también incluyo la parte 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(); }Usando la función como:
saveData('https://example.com/my_api?api=1;test=2;id=32', { answer: 42 }) .then(data => { console.log(data); }) .catch( error => { console.error( error ); });En la consola veo error:
SyntaxError: Unexpected end of inputUna posible razón de este error es una cadena JSON vacía.
Pude reproducir su problema y luego pude solucionarlo.
Era un problema de CORS. Debe habilitar CORS tanto en la parte delantera como en la trasera.
En la parte delantera, debe configurar la política de seguridad de contenido con una metaetiqueta en el <head> de su página:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://localhost"> (No olvide cambiar localhost a cualquiera que sea su dominio real).
En la parte posterior, debe agregar el encabezado COR:
print $q->header( -status => $status, -type => $type, -charset => $charset, -access_control_allow_origin => '*', # <-- add this line ); Como nota al margen, ninguna de las configuraciones que está pasando a fetch son necesarias. Y dado que está esperando la respuesta y luego devuelve otra promesa de todos modos, realmente no hay razón para que sea una función asíncrona.
Hasta que esté listo para hacer algo con el argumento data no utilizados, el siguiente código será suficiente:
function saveData(url = '', data = {}) { return fetch(url).then(response=>response.json()); }También debe await la response.json() .
Intente return await response.json(); , en lugar de return response.json();