Tecnología · GUÍA PRÁCTICA
¿curl da Empty reply después de 100 o 103? Comprueba la respuesta final
Recibir cabeceras no siempre significa completar la respuesta. Seis pruebas con curl 8.5.0 separan respuestas informativas, cuerpos vacíos válidos y el error 52.

Una traza HTTP/1.1 puede mostrar 100 Continue o 103 Early Hints y terminar con curl: (52) Empty reply from server. En nuestra prueba controlada con curl 8.5.0, enviar solo 103 produjo 71 bytes de cabeceras guardadas y response_code 103, pero el proceso terminó con 52. Ni un archivo de cabeceras no vacío ni un código distinto de 000 demostraron que hubiera llegado una respuesta final.
La comprobación útil es si a la respuesta informativa le sigue una final y si se completan la transferencia y el resultado esperado de la aplicación. Esta guía añade esa excepción concreta a las explicaciones existentes; el código por sí solo no identifica qué componente interrumpió la conexión.
Separa la salida del proceso del estado HTTP
Conserva curl --version, el método y URL exactos, entorno, selección de proxy, error completo y marcas de tiempo. Para una petición inocua autorizada, guarda cabeceras y cuerpo por separado. Por ejemplo: curl -sS -D response.headers -o response.body -w 'code=%{response_code} headers=%{size_header} body=%{size_download}\n' 'https://example.com/'; guarda inmediatamente el estado de salida del shell, por ejemplo con rc=$? en un shell POSIX. Sustituye el destino correcto y conserva en privado la autenticación necesaria.
En esta primera comparación no pases el cuerpo por una tubería a otro programa ni deduzcas la salida de curl a partir del último comando de la tubería. El código HTTP de write-out y la salida del proceso expresan cosas distintas. El ejemplo no añade --fail: una respuesta HTTP 4xx/5xx completa puede terminar con salida 0 de curl y seguir siendo un fallo de la aplicación. Inspecciona el estado final real y el contenido esperado.
Lee todos los bloques de respuesta en orden
RFC 9110 distingue las respuestas provisionales 1xx de la final; RFC 8297 aclara que las pistas de las cabeceras 103 no sustituyen las cabeceras finales. Revisa todos los bloques guardados, no solo la primera línea de estado HTTP. Para este problema, recibir 100 o 103 y después un cierre es distinto de recibir 103 y luego un 200 final.
Una respuesta CONNECT del proxy y el historial de redirecciones también pueden generar varios bloques: conserva método, interlocutor y secuencia. No clasifiques todos los bloques anteriores como informativos. Un 100 Continue describe el progreso de la petición, no demuestra que la operación de una subida haya terminado. Un Link en 103 es una pista, no prueba que el recurso indicado o la petición principal hayan tenido éxito.
Compara seis controles con bytes conocidos
Con Python 3.12.14 servimos seis respuestas sintéticas en 127.0.0.1, leyendo las cabeceras GET completas antes de cerrar ordenadamente la conexión. El cliente fue Ubuntu curl 8.5.0-2ubuntu10.13 con --http1.1, --noproxy '*', límite de conexión de dos segundos y límite total de tres. La configuración de proxy aísla esta prueba local; no indica que debas omitir un proxy obligatorio en producción. No probamos TLS, un servidor de aplicaciones ni un intermediario.
Sin bytes de respuesta obtuvimos código 000, cero bytes de cabeceras y cuerpo, y salida 52. El 204 final dio código 204, 46 bytes de cabeceras, cuerpo vacío y salida 0; el 200 final con Content-Length: 0 dio código 200, 57 bytes de cabeceras, cuerpo vacío y salida 0. Solo 100 dio código 100, 25 bytes de cabeceras y salida 52; solo 103 dio código 103, 71 bytes y salida 52. Ambos carecían de cuerpo. Añadir tras ese 103 un 200 final con Content-Length: 2 y cuerpo OK produjo código 200, 128 bytes de cabeceras, dos bytes de cuerpo y salida 0. El caso de solo 100 es una entrada deliberadamente incompleta para el analizador, no una respuesta completa normal. Los recuentos exactos dependen de las cabeceras elegidas.
Localiza dónde dejó de llegar la respuesta final
Una publicación histórica de la comunidad OpenLiteSpeed muestra precisamente la duda: el cliente recibió 100 y luego el error 52 mientras el registro del servidor ascendente mostraba 200. Es evidencia de una pregunta real, no de un defecto confirmado del producto actual. Las pruebas locales reproducen solo las formas de respuesta visibles para el cliente, no aquel despliegue ni su causa.
En sistemas que administras, correlaciona una petición segura entre cliente, proxy y origen mediante tiempo e identificador de petición. Averigua qué límite registró una respuesta final real y cuál la entregó hacia el cliente. Un 200 en el registro del origen no demuestra que curl recibiera esos bytes. Conserva la compilación real: otro intercambio de curl-library de 2026 trata los códigos 52 y 56 en un caso distinto, así que no prometas códigos idénticos entre versiones o modos de fallo.
Valida la reparación con el resultado final
Tras una única reparación limitada y reversible, repite la petición segura prevista por su ruta real. Exige el estado final esperado, una transferencia curl completa y el cuerpo previsto o su ausencia legítima. Un 204 no tiene contenido de respuesta; un 200 con longitud cero explícita también puede ser válido. Ninguno equivale a recibir solamente un bloque informativo.
Para una subida o API que cambia estado, comprueba si la operación ya ocurrió antes de reintentar. El error 52 no demuestra lo contrario. Mantén autenticación y verificación de certificados; no fabriques éxito ocultando stderr, ampliando tiempos ajenos al problema o aceptando 100/103 como finalización. Si el responsable no está claro, entrega los bloques ordenados y depurados de secretos, salida, compilación y registros correlacionados.
