As per the documentation, php://input does not always contain the HTTP request body.
I have some code that always opens the stream when the script starts, to make it available to the user application:
$stream = fopen('php://input', 'rb');
If the user application tries to read from an empty stream, when Content-Length > 0, I want my library to throw an exception:
The request body is not available.
My problem is that:
- If the stream is empty,
feof()returnsfalsewhilefread()has not been called; - I can’t
fread()1 byte thenfseek(), as this stream does not support seeking; - I can’t open another
php://inputand try to read from it beforehand, as we can’t rely on this stream to be available more than once; - I don’t want to blindly copy
php://inputtophp://tempbefore giving the hand to the user application, for performance reasons.
Consequently, is it possible to tell whether php://input contains data right after fopen(), but before any fread()?
The solution I found is to create a class representing the request body, and reading from this class instead of
php://inputdirectly:The class constructor reads the first byte of the stream, storing it for later use, and knowing instantly whether the stream is empty.
read()hides this complexity, by returning the first byte +$length - 1bytes the first time it’s called.