- Streaming HTTP response in PHP — turn long-running process into realtime UI
- I was working on something
- Concept Overview
- Streaming
- Output Buffering
- A simple experiment
- Let’s try some streaming
- Explanation
- How to get and process the response in javascript
- Understand PHP HTTP Response: Functions and Constants
- Contents
- PHP HTTP Response: Main Tips
- List of Functions to Manipulate Responses
- PHP HTTP Response: Summary
Streaming HTTP response in PHP — turn long-running process into realtime UI
For a “ not too long ” single server-side request what if you could let the user know how the request is handled at the server’s end, in real-time without them waiting for the entire process being finished !
without any package or WebSocket or anything “ on trend ”
I was working on something
Recently I was working on an multi-vendor large application where the requirement was to make a multi currency payment processing to facilitate transaction from different source to target currency.
The entire flow to make a transaction with parameters like source & target currency, amount, recipient etc is quite lengthy. It consists of different stages like quote creation, recipient handling, transfer creation followed by funding. There are total 4 API requests that are dependent on each other’s response so the entire process takes ⏱ approx. 10 seconds at the server’s end.
I couldn’t bear just a dumb loader holding my attention for that long 🙄, so I started thinking if I could go for Laravel Echo or anything equivalent that uses WebSocket which could help me out pushing events at different stages of processing, then I could inform the user accordingly and it feels more responsive.
Suddenly this idea of streaming came to the mind. Though this was not the first time I used this technique for such kind of situation, it was last year when I was working on an E-commerce application where the app needed a functionality to sync. it’s products database via API.
Concept Overview
Streaming
Streaming is not a new concept, it is a data transfer technique which allows a web server to continuously send data to a client over a single HTTP connection that remains open indefinitely. In streaming response comes in chunk rather than sending them at once. In the traditional HTTP request / response cycle, a response is not transferred to the browser until it is fully prepared which makes users wait.
Output Buffering
Output buffering allows to have output of PHP stored into an memory (i.e. buffer) instead of immediately transmitted, it is a mechanism in which instead of sending a response immediately we buffer it in memory so that we can send it at once when whole content is ready.
Each time using echo we are basically telling PHP to send a response to the browser, but since PHP has output buffering enabled by default that content gets buffered and not sent to the client.
A simple experiment
echo "Hi"; sleep(2); echo "There !";
running this code will execute Hi There ! together after a wait of 2 seconds in total. This is because of output buffering which is on by default in PHP.
instead of sending the response to the browser when the first echo is executed, its contents are buffered.
💡 Since buffered content is sent to the browser if either the buffers get full or code execution ends we’ll get the two echoed response merged & responded by server all together at once.
Since Hi There ! is not enough to occupy more than 4KB (default size of output buffer in PHP) of buffer size, the content is sent when code execution ends.
Let’s try some streaming
Route::get('/mock', function() < // defining a route in Laravel set_time_limit(0); // making maximum execution time unlimited ob_implicit_flush(1); // Send content immediately to the browser on every statement which produces output ob_end_flush(); // deletes the topmost output buffer and outputs all of its contents sleep(1); echo json_encode(['data' => 'test 1']); sleep(2); echo json_encode(['data' => 'test 2']); sleep(1); echo json_encode(['data' => 'test 3']); die(1); >);
Run the example in browser you’ll see response in parts one after another according to the sleep we sprinkled which in real world would be our time consuming data processing like API call or multiple heavy sql execution etc.
Explanation
Output buffers catch output given by the program. Each new output buffer is placed on the top of a stack of output buffers, and any output it provides will be caught by the buffer below it. The output control functions handle only the topmost buffer, so the topmost buffer must be removed in order to control the buffers below it.
✔ The ob_implicit_flush(1) enables implicit flushing which sends output directly to the browser as soon as it is produced.
✔ If you need more fine grained control then use flush() function. To send data even when buffers are not full and PHP code execution is not finished we can use ob_flush and flush . The flush() function requests the server to send it’s currently buffered output to the browser
How to get and process the response in javascript
I found a way to do so with traditional xhr ( XMLHTTPRequest ) request
function testXHR() let lastResponseLength = false; xhr = new XMLHttpRequest(); xhr.open("GET", "/mock", true); xhr.setRequestHeader("Content-Type", "application/json"); xhr.setRequestHeader("Accept", "application/json"); xhr.setRequestHeader('X-CSRF-Token', document.querySelector('meta[name="csrf-token"]').content); xhr.onprogress = function(e) let progressResponse; let response = e.currentTarget.response; progressResponse = lastResponseLength ? response.substring(lastResponseLength) : response; lastResponseLength = response.length; let parsedResponse = JSON.parse(progressResponse); console.log(parsedResponse); if(Object.prototype.hasOwnProperty.call(parsedResponse, 'success')) // handle process success > > xhr.onreadystatechange = function() if (xhr.readyState == 4 && this.status == 200) console.log("Complete = " + xhr.responseText); > > xhr.send(); >;
xhr.onprogress : is the function called periodically with information until the XMLHttpRequest completely finishes
Understand PHP HTTP Response: Functions and Constants
HTTP stands for Hypertext Transfer Protocol. It is called a protocol of request-response type. That means it functions by the server answering various requests it receives from the client (in this case, the Internet browser).
In this tutorial, we will explain in more detail what a PHP HTTP response is, how to set and modify it. Such a response can be modified in numerous ways, but to do that, a developer must have some knowledge on special functions.
Contents
PHP HTTP Response: Main Tips
- HTTP PHP functions allow you to manipulate PHP HTTP response (the information sent by your browser to server) before outputting it.
- These functions are inbuilt into PHP core.
- Easy to use with a learn-by-doing approach
- Offers quality content
- Gamified in-browser coding experience
- The price matches the quality
- Suitable for learners ranging from beginner to advanced
- Free certificates of completion
- Focused on data science skills
- Flexible learning timetable
- Simplistic design (no unnecessary information)
- High-quality courses (even the free ones)
- Variety of features
- Nanodegree programs
- Suitable for enterprises
- Paid Certificates of completion
List of Functions to Manipulate Responses
As we have already covered, exchanging data on the Internet consists of one side (client) asking for specific data and the other (server) supplying the requested information. A piece of data that server issues as an answer to a particular request is called a PHP HTTP response.
Response has the same structure as request. It consists of a status line, header and body. To set a certain PHP HTTP response, you should use http_response_code() function.
Now, there are various ways to control these responses. Let’s see them in a table below:
Function | Description |
---|---|
header() | Send raw HTTP header to client |
headers_list() | Return list of PHP HTTP response headers already sent (or headers that are ready to be sent) |
headers_sent() | Check if / where HTTP headers have been sent |
setcookie() | Set cookie to send along with remaining HTTP headers |
setrawcookie() | Set cookie (without URL encoding) to send along with remaining HTTP headers |
PHP HTTP Response: Summary
- When a client sends a request for certain information to the server, it provides it by sending a PHP HTTP response.
- Before HTTP data that your browser sends to the server is outputted, you can modify it using HTTP PHP functions.
- There’s no need to install these functions separately.