Recently, I’ve been studying the specifics of the Fast-CGI protocol and used TCPDUMP to capture the TCP packets sent from Nginx to PHP-FPM. So, I set up a simple environment on my MAC to run a small demo. I already had Nginx and PHP, just had to configure an Nginx vhost and it should be done, but who knew I’d spend half a day messing with the vhost. Tough times.
Since all my previous Nginx configurations were done on virtual machines provided by the company, it was just a matter of copying a conf file from a previous project, changing the root path and server_name, and then reloading.
Having read the Nginx manual, I understood the roles of the http, server, and location modules, as well as some configurations, so I decided to write one myself.
First, I wrote a test.php file in /Users/zonghay/www/, and then configured the vhost to see the effect.
My first server configuration was as follows:
server {
listen 8848;
server_name localhost;
location / {
root /Users/zonghay/www/;
index index.html index.htm;
}
}
Accessing http://localhost:8848 in the browser, I encountered a 404 error. A 404 error means something couldn’t be found. But what exactly? After thinking for a while, I realized that I wrote a test.php file, but the Nginx configuration was looking for index.html and index.htm. I quickly changed the PHP file name and updated the Nginx configuration file to this:
server {
listen 8848;
server_name localhost;
location / {
root /Users/zonghay/www/;
index index.html index.htm index.php;
}
}
Restart Nginx and send a request. This time it wasn’t a 404, but a blank page, and instead of displaying anything, it downloaded the index.php file. Eh, why is that? After a Bing search, I found out that when Nginx matches the index.php file, it realizes it’s not an HTML resource, so it returns the file with a content-type of application/octet-stream. We can see the HTTP response in the F12 developer tools.
HTTP/1.1 200 OK Server: nginx/1.17.3 Date: Wed, 13 Nov 2019 13:25:25 GMT Last-Modified: Wed, 13 Nov 2019 13:23:34 GMT Content-Type: application/octet-stream Content-Length: 18 ETag: “5dcc03d6-12” Accept-Ranges: bytes
But how to solve this? Of course, you need to tell Nginx to hand over the file to someone else for processing. So, let’s continue building the wall, add a location block to match PHP files, and tell Nginx to hand the file over to PHP-FPM listening on port 9000 of the local machine.
server {
listen 8848;
server_name localhost;
location / {
root /Users/zonghay/www/;
index index.html index.htm index.php;
}
location ~ .*\.php$ {
fastcgi_pass 127.0.0.1:9000;
}
}
Continue with the restart and refresh.
With full of anticipation, I found that it was neither a 404 nor a download this time, but a blank page. I was devastated. But after calming down and analyzing it, why didn’t it return anything? It could be that PHP-FPM didn’t process the file or didn’t process it correctly, returning empty. After carefully comparing my virtual machine’s vhost configuration with this season’s configuration, I realized I might have made a basic mistake. As we all know, what is the full name of PHP-FPM? It’s called PHP Fast-CGI Manager, an application that implements the Fast-CGI protocol. You tell Nginx to process the file, but you don’t tell it what protocol to use. It’s like going to a restaurant, carrying meat and asking them to stir-fry a dish, but if you don’t say what dish, they’ll definitely ignore you. So, I Binged and compared the differences between the two configuration files, and wrote a final version.
server {
listen 8848;
server_name localhost;
root /Users/zonghay/www/;
index index.html index.htm index.php;
location ~ .*\.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
}
}
The included fastcgi_params file contains the necessary K-V key-value pairs for the Fast-CGI protocol. As for the functions of these key-value pairs, I will write another article after I finish researching the Fast-CGI protocol. Finally, my little demo ran successfully with some scares, but seeing the words “Hello World” on the screen, I felt quite embarrassed. I’ve been working for a year, and I can still make such a basic mistake in Nginx configuration.