5

Supporting HTTP 100 Continue with PHP raised this issue back in 2010 with a slightly different focus (it sought a PHP solution as opposed to an Apache solution) but was never resolved.

Context

The HTTP/1.1 specification created the request header 'Expect' which has one defined value; namely '100-Continue'. The revised HTTP/1.1 RFCs (see RFC 7231 Section 5.1.1) released in June 2014 state the following:

A 100-continue expectation informs recipients that the client is about to send a (presumably large) message body in this request and wishes to receive a 100 (Continue) interim response if the request-line and header fields are not sufficient to cause an immediate success, redirect, or error response. This allows the client to wait for an indication that it is worthwhile to send the message body before actually doing so, which can improve efficiency when the message body is huge or when the client anticipates that an error is likely (e.g., when sending a state-changing method, for the first time, without previously verified authentication credentials).

It is also a generally accepted statement that this part of the specification has been imperfectly implemented both by servers and by clients. The revised specification even alludes to this:

...However, the extension mechanism has not been used by clients and the must-understand requirements have not been implemented by many servers...

emphasis is mine, not from the specification

Even excluding the extension mechanism for this header, the 100-continue value also seems to be poorly implemented. If we consider a standard PHP/Apache stack, Apache does provide the 100-continue interim response if the client requests it.

However, it does this based solely on its own processing of the request, i.e. without consulting the PHP resource. This seems to defeat the purpose of the header as most requests will fail due to invalid request parameters or permissions; not due to a malformed HTTP request. So, even if the client declares a 100-continue expectation and receives a 100-continue response, it does not mean that the request head is valid.

Intention

As part of a broader intention to more fully implement HTTP specification (for the purpose improved network efficiency, security, and clarity), I intend to more properly validate the request header before sending a 100-continue response.

This means that the request must be passed to my PHP resource controller to be validated before the 100-continue response is sent. This allows invalid parameters and improper permissions to be identified before the client wastes time and resources sending a large message body.

I expect that the exchange would look something like this:

Client                    Apache                      Resource
->|                         |                            |
  |------Request Head------>|                            |
  |                         |-[Parse]                    |
  |<-----400 bad request----|                            |
  |                         |-[Route]                    |
  |                         |-------Request Head-------->|
  |                         |                            |-[Validate]
  |                         |<---Error / 100 Continue----|
  |<--Error / 100 Continue--|                            |
<-|[End or...]              |                            |
  |------Request Body------>|                            |
  |                         |--------Full Request------->|
  |                         |                            |-[Process]
  |                         |<---------Response----------|
  |<--------Response--------|                            |
<-|                         |                            |

Obviously, this requires greater inter-operation between the PHP application and the apache web server.

Strategy

Due to the extent of the integration required, the only solution appears to be an Apache module/extension designed to hook into the request immediately before the 100-continue response is sent and perform the additional step of passing the request head to the PHP resource for parsing.

From there, normal Apache processing can resume, with the 100-continue response being sent, Apache waiting for the message body and then passing the completed request to the PHP resource.

Questions

  1. Would an Apache module as described above be an improvement to the current implementation?

  2. Are there any modules that have sought to address this in the past?

Also, regarding the technical details of developing Apache modules:

  1. What Apache hooks are available? I cannot find a resource that identifies the available hooks and the order in which they are processed. Found it Apache2: Apache Hooks

  2. How should an Apache module interact with PHP? I am aware that it depends upon the installation method (e.g. multiple threads within the Apache process or individual processes per execution etc.). But am unsure of how exactly Apache manages its other interactions with PHP processes.

Community
  • 1
  • 1

1 Answers1

2

What you describe is not going to work with most handlers, including PHP. HTTP is a message based protocol, and normally its a request-reply method - the only exceptions being the connect request, web sockets and the expect/100 response. Hence implementing this will require re-engineering the internals of the webserver, the interface(s) to the handler and the handler itself: for CGI, fastcgi and the isapi module PHP does not see the request until it has been marshalled in the webserver.

And you will have to implement your own client too (at least as an AJAX/SJAX JavaScript).

Consider instead pre-flighting your request:

 Client: can I send a really big file?
 Server: 204
 Client: here's a really big file

There is only a single extra set of headers, notably no extra RTT compared with the expect/100 method. Take some time to calculate the resultant cost per request. It's tiny. And it will work with all servers today. And it doesn't take months of effort to develop. Without wishing to get too bogged down in the details of an alternative solution to the problem, clearly we would want the URL to be the same in both client requests, so the difference in intent of the 2 client requests would need to be expressed elsewhere, e.g. by using the OPTIONS verb in the first request and PUT/POST/GET/DELETE in the second.

There's little difference in the client code for this.

But supposing you have an army of developers and testers with nothing better to do than develop your proposed module, and that it does not require extensive changes to the handlers or that the maintainers of aforesaid handlers build support for expect/100 themselves... Why should I, as webserver admin want to install such a module when I can get the same result without having to install additional modules, increase the attack surface of my webserver and adapt any code I am already using?

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • 1
    Yes, this was the first time I'd looked at Apache modules and having now read a bit about it my general conclusion is... this is not going to be worth it. I had hoped that there would be a fairly simple apache hook-in and that the rest could be handled in PHP, but it appears not. I am a little irritated by not being able to use 100-continue (even though it is manifestly applicable) but my irritation has very little economic value and, as you describe, the time it would take to satisfy it has very substantial costs. –  Feb 21 '16 at 00:41