HttpComponents HttpCore
  1. HttpComponents HttpCore
  2. HTTPCORE-296

Server HTTP connections incorrectly handle entity enclosing requests containing neither Content-Length nor Transfer-Encoding headers

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 4.2-alpha2
    • Fix Version/s: 4.2
    • Component/s: HttpCore NIO
    • Labels:
      None

      Description

      If a client submits a POST with Content-Length 0, the HttpCore framework will fire the onContentReceived(...) method of the HttpAsyncRequestConsumer once. However, the decoder (passed as an argument to onContentReceived()) will never enter the "completed" state, because no bytes will actually be received from the client. However, reaching the "completed" stage of the decoder is an requirement for the HttpAsyncServiceHandler to finally process the request (i.e., call the handle(...) method).

      This leads to the (incorrect) behavior that it is impossible to handle a POST request with Content-Length 0 in HttpCore NIO.

        Activity

        Hide
        Roland Hänel added a comment -

        Additional information / correction:

        This does not happen if a Content-Length: 0 header is included with the request. If the request has a CL: 0 header, everything is fine.

        The problem happens if the request (POST) does not include any Content-Length: header. This seems to be the default implementation in the Python 2.7 (sic!) client when sending a POST request with zero bytes of request data.

        In this case (no CL header at all in the request), HttpCore does not select the LengthDelimitedDecoder but the IdentityDecoder, which in turn never reaches the complete state.

        The solution might be to select the the LengthDelimitedDecoder with a target len of 0 in this case.

        Show
        Roland Hänel added a comment - Additional information / correction: This does not happen if a Content-Length: 0 header is included with the request. If the request has a CL: 0 header, everything is fine. The problem happens if the request (POST) does not include any Content-Length: header. This seems to be the default implementation in the Python 2.7 (sic!) client when sending a POST request with zero bytes of request data. In this case (no CL header at all in the request), HttpCore does not select the LengthDelimitedDecoder but the IdentityDecoder, which in turn never reaches the complete state. The solution might be to select the the LengthDelimitedDecoder with a target len of 0 in this case.
        Hide
        Oleg Kalnichevski added a comment -

        An entity enclosing request that does not deliniate its content either with Transfer-Encoding or Content-Length header is invalid per section 4.1 of the HTTP/1.1 spec. The problem is that HttpCore attempts to consume the request by using identity codec instead of rejecting it as invalid.

        Oleg

        Show
        Oleg Kalnichevski added a comment - An entity enclosing request that does not deliniate its content either with Transfer-Encoding or Content-Length header is invalid per section 4.1 of the HTTP/1.1 spec. The problem is that HttpCore attempts to consume the request by using identity codec instead of rejecting it as invalid. Oleg
        Hide
        Roland Hänel added a comment -

        Hi Oleg,

        Thanks for the quick reply. However one might doubt whether the solution is really that easy. I don't think the spec is 100% clear on this issue. Section 4.1 specifies the message body optional; section 4.3 says that "The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers." We all know that POST messages usually have a message body, but I don't think we can read from the spec that it MUST have one.

        If in doubt, might I suggest that a better solution could be to handle an entity enclosing request without message body by using a LengthDelimitedDecoder and a length of 0. This should also work out of the box and ensure the 'obviously expected behavior'.

        -Roland

        Show
        Roland Hänel added a comment - Hi Oleg, Thanks for the quick reply. However one might doubt whether the solution is really that easy. I don't think the spec is 100% clear on this issue. Section 4.1 specifies the message body optional; section 4.3 says that "The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers." We all know that POST messages usually have a message body, but I don't think we can read from the spec that it MUST have one. If in doubt, might I suggest that a better solution could be to handle an entity enclosing request without message body by using a LengthDelimitedDecoder and a length of 0. This should also work out of the box and ensure the 'obviously expected behavior'. -Roland
        Hide
        Roland Hänel added a comment -

        Hi Oleg,

        Thanks for the quick reply. However one might doubt whether the solution is really that easy. I don't think the spec is 100% clear on this issue. Section 4.1 specifies the message body optional; section 4.3 says that "The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers." We all know that POST messages usually have a message body, but I don't think we can read from the spec that it MUST have one.

        If in doubt, might I suggest that a better solution could be to handle an entity enclosing request without message body by using a LengthDelimitedDecoder and a length of 0. This should also work out of the box and ensure the 'obviously expected behavior'.

        -Roland

        Show
        Roland Hänel added a comment - Hi Oleg, Thanks for the quick reply. However one might doubt whether the solution is really that easy. I don't think the spec is 100% clear on this issue. Section 4.1 specifies the message body optional; section 4.3 says that "The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers." We all know that POST messages usually have a message body, but I don't think we can read from the spec that it MUST have one. If in doubt, might I suggest that a better solution could be to handle an entity enclosing request without message body by using a LengthDelimitedDecoder and a length of 0. This should also work out of the box and ensure the 'obviously expected behavior'. -Roland
        Hide
        Oleg Kalnichevski added a comment -

        The way I interpret the spec an entity enclosing request MAY have no content body but it MUST make it clear by including 'Content-Lenght: 0' header. I still think sending back status 400 in such a case is the right thing to do. One can still (quite) easily override the default behavior by using a custom ContentLengthStrategy implementation.

        Oleg

        Show
        Oleg Kalnichevski added a comment - The way I interpret the spec an entity enclosing request MAY have no content body but it MUST make it clear by including 'Content-Lenght: 0' header. I still think sending back status 400 in such a case is the right thing to do. One can still (quite) easily override the default behavior by using a custom ContentLengthStrategy implementation. Oleg
        Hide
        Roland Hänel added a comment -

        Thanks for pointing out the ContentLengthStrategy think. I'll try my luck there.

        Roland

        Show
        Roland Hänel added a comment - Thanks for pointing out the ContentLengthStrategy think. I'll try my luck there. Roland
        Hide
        Oleg Kalnichevski added a comment -

        Curl also does not include 'Content-Length: 0' header if one does not specify any content to post. I think this is wrong, but I'll make sure HttpCore can handle such requests.

        Oleg

        Show
        Oleg Kalnichevski added a comment - Curl also does not include 'Content-Length: 0' header if one does not specify any content to post. I think this is wrong, but I'll make sure HttpCore can handle such requests. Oleg
        Hide
        Oleg Kalnichevski added a comment -

        Fixed in trunk and 4.1.x branch. Please review and re-test.

        Oleg

        Show
        Oleg Kalnichevski added a comment - Fixed in trunk and 4.1.x branch. Please review and re-test. Oleg

          People

          • Assignee:
            Unassigned
            Reporter:
            Roland Hänel
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development