Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>A little inspection of the source code yields the answers.</p> <p>First, yes, you're limited to one read per handle because the underlying stream does not implement the <code>seek</code> handler:</p> <pre><code>php_stream_ops php_stream_input_ops = { php_stream_input_write, /* ... */ "Input", NULL, /* seek */ /* ... */ }; </code></pre> <p>Second, the read handler has two different behaviors depending on whether the "POST data" has been read and stored in <code>SG(request_info).raw_post_data</code>.</p> <pre><code>if (SG(request_info).raw_post_data) { read_bytes = SG(request_info).raw_post_data_length - *position; /* ...*/ if (read_bytes) { memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes); } } else if (sapi_module.read_post) { read_bytes = sapi_module.read_post(buf, count TSRMLS_CC); /* ... */ } else { stream-&gt;eof = 1; } </code></pre> <p>So we have three possibilities here:</p> <ol> <li>The request body data has already been read and stored in <code>SG(request_info).raw_post_data</code>. In this case, since the data is stored, we can open and read multiple handles for <code>php://input</code>.</li> <li>The request body data has been read, but its contents were not stored anywhere. <code>php://input</code> cannot give us anything.</li> <li>The request data hasn't been read yet. This means we can open <code>php://input</code> and read it only once.</li> </ol> <p><strong>NOTE: What follows is the default behavior. Different SAPIs or additional extensions may change this behavior.</strong></p> <p>In case of POST requests, PHP defines a different POST reader and a POST handler depending on the content-type.</p> <p><strong>Case 1.</strong> This happens when we have a POST request:</p> <ul> <li><em>With content-type <code>application/x-www-form-encoded</code></em>. <code>sapi_activate</code> detects a POST request with a content-type and calls <code>sapi_read_post_data</code>. This detects the content-type and defines the POST reader/handler pair. The POST reader is <code>sapi_read_standard_form_data</code>, which is immediately called and just copies the request body to <code>SG(request_info).post_data</code>. The default post reader <code>php_default_post_reader</code> is then called, which fills <code>$HTTP_RAW_POST_DATA</code> if the ini setting <code>always_populate_post_data</code> is set and then copies <code>SG(request_info).post_data</code> to <code>SG(request_info).raw_post_data</code> and clears the first. The call to the handler doesn't matter here and is deferred until the superglobals are built (which may not happen, in case JIT is activated and the superglobals are not used).</li> <li><em>With an unrecognized or inexistent content-type</em>. In this case, there's no defined POST reader and handler. Both cases end up in <code>php_default_post_reader</code> without any data read. Since this is a POST request and there's no reader/handler pair, <code>sapi_read_standard_form_data</code> will be called. This is the same function as the read handler the content type <code>application/x-www-form-encoded</code>, so all the data gets swallowed to <code>SG(request_info).post_data</code>. The only differences from now on is that <code>$HTTP_RAW_POST_DATA</code> is always populated (no matter the value of <code>always_populate_post_data</code>) and there's no handler for building the superglobals.</li> </ul> <p><strong>Case 2.</strong> This happens when we have a form request with content-type "multipart/form-data". The POST reader is <code>NULL</code>, so the handler, which is <code>rfc1867_post_handler</code> acts as a mixed <code>reader/handler</code>. No data whatsoever is read in the <code>sapi_activate</code> phase. The function <code>sapi_handle_post</code> is eventually called in a later phase, which, in its turn calls the POST handler. <code>rfc1867_post_handler</code> reads the request data, populates <code>POST</code> and <code>FILES</code>, but leaves nothing in <code>SG(request_info).raw_post_data</code>.</p> <p><strong>Case 3.</strong> This last case takes place with requests different from POST (e.g. PUT). <code>php_default_post_reader</code> is directly called. Because the request is not a POST request, the data is swallowed by <code>sapi_read_standard_form_data</code>. Since no data is read, there's not anything left to be done.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload