Hi,
relayd enforces a rule in rfc section 3.3.2:
rfc 7230 3.3 Message Body
All 1xx (Informational), 204 (No Content), and 304 (Not Modified)
responses do not include a message body. All other responses do
include a message body, although the body might be of zero length.
rfc 7230 3.3.2. Content-Length
A server MUST NOT send a Content-Length header field in any response
with a status code of 1xx (Informational) or 204 (No Content). A
server MUST NOT send a Content-Length header field in any 2xx
(Successful) response to a CONNECT request (Section 4.3.6 of
[RFC7231]).
There is also this paragraph in Section 3.3.3 thats relevant:
4. If a message is received without Transfer-Encoding and with
either multiple Content-Length header fields having differing
field-values or a single Content-Length header field having an
invalid value, then the message framing is invalid and the
recipient MUST treat it as an unrecoverable error. If this is a
request message, the server MUST respond with a 400 (Bad Request)
status code and then close the connection. If this is a response
message received by a proxy, the proxy MUST close the connection
to the server, discard the received response, and send a 502 (Bad
Gateway) response to the client. If this is a response message
received by a user agent, the user agent MUST close the
connection to the server and discard the received response.
There are two problems with this:
* I have found a Tomcat Server that sends "204 No Content" with a
"Content-Length: 0" Header.
* Relayd sends the wrong HTTP Status Code, it should be 502 Bad Gateway
Here is a diff that relaxes the logic: send a 502 Bad Gateway, but
only if Content-Length != 0.
ok?
diff --git usr.sbin/relayd/relay_http.c usr.sbin/relayd/relay_http.c
index 3b6f8e84e37..ad45cf2d5d6 100644
--- usr.sbin/relayd/relay_http.c
+++ usr.sbin/relayd/relay_http.c
@@ -324,19 +324,6 @@ relay_read_http(struct bufferevent *bev, void *arg)
relay_abort_http(con, 400, "malformed", 0);
goto abort;
}
- /*
- * response with a status code of 1xx
- * (Informational) or 204 (No Content) MUST
- * not have a Content-Length (rfc 7230 3.3.3)
- */
- if (desc->http_method == HTTP_METHOD_RESPONSE && (
- ((desc->http_status >= 100 &&
- desc->http_status < 200) ||
- desc->http_status == 204))) {
- relay_abort_http(con, 500,
- "Internal Server Error", 0);
- goto abort;
- }
/*
* Need to read data from the client after the
* HTTP header.
@@ -349,6 +336,23 @@ relay_read_http(struct bufferevent *bev, void *arg)
relay_abort_http(con, 500, errstr, 0);
goto abort;
}
+ /*
+ * response with a status code of 1xx
+ * (Informational) or 204 (No Content) MUST
+ * not have a Content-Length (rfc 7230 3.3.3)
+ * Instead we check for value != 0 because there are
+ * servers that do not follow the rfc and send
+ * Content-Length: 0.
+ */
+ if (desc->http_method == HTTP_METHOD_RESPONSE && (
+ ((desc->http_status >= 100 &&
+ desc->http_status < 200) ||
+ desc->http_status == 204)) &&
+ cre->toread != 0) {
+ relay_abort_http(con, 502,
+ "Bad Gateway", 0);
+ goto abort;
+ }
}
lookup:
if (strcasecmp("Transfer-Encoding", key) == 0 &&