Error response contains extra newline
When sending the response after an internal error the web server includes an incorrect trailing newline after the response message. The newline is not included in the size sent in Content-Length. That causes the newline to be read as the start of the next message, which results in an error when client reads that message:
java.net.ProtocolException: Unexpected status line:
Note the empty unexpected status line.
Environment
YDB Web server version: Current master
YottaDB version: r2.00
How to reproduce
First start the web server:
$ ydb -run start^%ydbwebreq
Starting Server at port 9080 in directory /my/working/dir at logging level 0
The endpoint /test/error includes a trailing newline in the response body. /test/customerror does not.
The problem can be seen using Netcat:
$ printf 'GET /test/error HTTP/1.1\r\n\r\n' | nc localhost 9080
HTTP/1.1 500 Internal Server Error
Date: Thu, 02 Jan 2025 13:47:02 GMT
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: *
Content-Length: 283
{"apiVersion":1.1,"error":{"code":500,"errors":[{"mcode":" new x set x=1\/0","message":"150373210,err1+1^%ydbwebapi,%YDB-E-DIVZERO, Attempt to divide by zero","place":"err1+1^%ydbwebapi","reason":",M9,Z150373210,"}],"request":"GET \/test\/error ","toperror":"Internal Server Error"}}
$
Note how the $ prompt is printed on a new line.
This is how it should look:
$ printf 'GET /test/customerror HTTP/1.1\r\n\r\n' | nc localhost 9080
HTTP/1.1 400 Bad Request
Date: Thu, 02 Jan 2025 13:48:25 GMT
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: *
Content-Length: 115
{"issue":[{"code":"processing","diagnostics":"Test message","severity":"error"}],"resourceType":"OperationOutcome"}$
Note how the $ prompt is printed on the same line as the response body.
The problem can also be seen using Curl. This command calls first /test/error and then /test/customerror:
mikrolisqa@gtm-box:~$ curl -v http://localhost:9080/test/error http://localhost:9080/test/customerror
* Trying 127.0.0.1:9080...
* Connected to localhost (127.0.0.1) port 9080 (#0)
> GET /test/error HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Date: Thu, 02 Jan 2025 13:30:58 GMT
< Content-Type: application/json; charset=utf-8
< Access-Control-Allow-Origin: *
< Content-Length: 283
<
* Excess found in a read: excess = 2, size = 283, maxdownload = 283, bytecount = 0
* Closing connection 0
{"apiVersion":1.1,"error":{"code":500,"errors":[{"mcode":" new x set x=1\/0","message":"150373210,err1+1^%ydbwebapi,%YDB-E-DIVZERO, Attempt to divide by zero","place":"err1+1^%ydbwebapi","reason":",M9,Z150373210,"}],"request":"GET \/test\/error ","toperror":"Internal Server Error"}}* Hostname localhost was found in DNS cache
* Trying 127.0.0.1:9080...
* Connected to localhost (127.0.0.1) port 9080 (#1)
> GET /test/customerror HTTP/1.1
> Host: localhost:9080
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 400 Bad Request
< Date: Thu, 02 Jan 2025 13:30:58 GMT
< Content-Type: application/json; charset=utf-8
< Access-Control-Allow-Origin: *
< Content-Length: 115
<
* Connection #1 to host localhost left intact
{"issue":[{"code":"processing","diagnostics":"Test message","severity":"error"}],"resourceType":"OperationOutcome"}mikrolisqa@gtm-box:~$
Curl prints this to indicate that extra characters were found:
* Excess found in a read: excess = 2, size = 283, maxdownload = 283, bytecount = 0
* Closing connection 0
Curl ignores the extra characters without generating an error, only printing a diagnostic message. Our Java based web client (OkHttp) instead generated an error.