1. Overview

Nginx is a powerful web server and reverse proxy server that serves static and dynamic content on the web. One of the features of Nginx is its ability to rewrite URLs, allowing us to redirect or modify incoming requests to the server.

In this tutorial, we’ll explore how to forward HTTP POST requests via rewrite in Nginx.

2. HTTP POST Requests and URL Rewriting

HTTP POST requests submit data to a web server. When a user submits a form on a website, for example, the data goes to the server using an HTTP POST request.

HTTP POST requests consist of submitting forms and uploading files to a server in the form of key-value pairs. This data goes in the body of the request, rather than in the URL. This uses the proxy_pass directive in Nginx.

URL rewriting, on the other hand, is the process of modifying the URL of a web page to make it more user-friendly or to redirect traffic to a different URL.

In Nginx, URL rewriting uses the rewrite directive. This directive allows us to specify a regular expression that matches the original URL and a replacement string that defines the new URL. The rewrite directive modifies both the URL and the HTTP method of the request. This can be done using a variety of methods, including server-side scripting, .htaccess files, and web server configuration files.

3. What Is Rewrite in Nginx?

We know that the proxy_pass directive only works for HTTP GET requests by default. To forward HTTP POST requests, we need to use Nginx’s URL rewriting capabilities. This uses the rewrite directive in combination with the proxy_pass directive.

Before we dive into the configuration details, let’s take a look at the basic syntax of the rewrite directive in Nginx:

rewrite regex replacement [flag];

Here, regex is a regular expression that matches the part of the URL we want to modify, replacement is the new value we want to replace it with, and flag is an optional parameter that modifies the behavior of the rewrite rule.

Now, let’s see how we can forward HTTP POST requests via rewrite in Nginx:

URL Rewriting in Nginx

In this simplified representation, the client initiates an HTTP POST request to Nginx. Nginx receives the HTTP POST request from the client, applies the rewrite rules and modifies the request URL. Nginx forwards the modified request to the destination server. The destination server processes the forwarded request. The destination server generates an HTTP response. Nginx receives the HTTP response from the destination server. It eventually relays the HTTP response back to the client.

4. How to Forward HTTP POST Request via Rewrite

We typically create an HTML form or application code with the required fields, setting the submit method to POST. This allows users to input data and submit it securely:

<form action="/submit" method="post">
    <!-- Add form fields -->
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="submit" value="Submit" />
</form>

Then onwards, forwarding an HTTP POST request via rewrite is achieved in Nginx by following a set of steps. These steps ensure effective communication between clients and the desired destination, allowing for smooth request handling and processing. In certain situations, it becomes necessary to forward such requests using the rewrite module. This functionality allows for URL modification and redirection of the request to another location or server, enabling advanced routing and handling.

4.1. Configure the Upstream Server

Before setting up the rewrite rules, we need to configure in Nginx the upstream server where we want to forward the HTTP POST requests. This server can be another backend server or an application that will process the requests. We can do this using the upstream directive in Nginx. The following is an example configuration for an upstream server:

upstream backend { server 10.0.0.1:8080; }

Here, backend is the name of the upstream server, and 10.0.0.1:8080 is the IP address and port of the server we want to forward the HTTP POST request to.

4.2. Create a Location Block

In the Nginx configuration file, we create a location block that specifies the URL path or pattern for which we want to handle the incoming HTTP POST requests. We can do this using the location directive in Nginx:

location /process {
    # Add relevant configuration directives
}

Here’s an example configuration for a location block:

location /submit { 
  if ($request_method = POST) { 
    rewrite ^/submit(.*) /api$1 break; 
    proxy_pass http://backend; 
   } 
}

Here, /submit is the URL path from which we want to forward the HTTP POST request via rewrite. The if directive checks whether the request method is POST. If it is, we use the rewrite directive to modify the URL and append /api to the beginning of the URL. The break flag tells Nginx to stop processing the rewrite rules and move on to the next directive.

Finally, we use the proxy_pass directive to forward the modified HTTP POST request to the upstream server we configured in Step 1.

4.3. Define a Rewrite Rule

Within the location block, we define a rewrite rule that redirects or forwards the incoming HTTP POST requests to the upstream server. The rewrite rule should preserve the request method as POST:

location /process {
  rewrite ^/process(.*)$ /backend$1 break;
  proxy_pass http://backend;
  proxy_set_header Host $host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

In this example, the rewrite directive rewrites the URL path, appending any additional path parameters to /backend. The proxy_pass directive specifies the upstream server to forward the request to. Additional proxy_set_header directives set relevant headers for the request forwarding.

4.4. Process Data in Processing Page

On the upstream server or application, we implement the necessary logic to process the forwarded HTTP POST requests received at the defined location. We then retrieve the data from the request parameters and perform the desired processing:

$name = $_POST['name'];
// Do something with the data

5. Forwarding HTTP POST Request via Rewrite

When forwarding HTTP POST requests via rewrite in Nginx, we can employ many approaches.

5.1. Using the post_action Directive

The post_action directive is one of the methods used to forward HTTP POST requests via rewrite in Nginx. It’s a powerful directive that enables the creation of subrequests after the processing of the main request. 

Let’s go through the steps to use the post_action directive to forward HTTP POST requests via rewrite.

Firstly, let’s define a location block that matches the original request URI:

location /original-uri {
   # ... 
}

Then we use the rewrite directive to change the URI to the new destination:

location /original-uri {
   rewrite /original-uri /new-uri;
}

Let’s now define a new location block that matches the new URI and set the post_action directive to create a subrequest that sends the request body to the new destination:

location /new-uri {     
   post_action /forward-request; 
}

Finally, we define a third location block that matches the URI specified in the post_action directive and use the proxy_pass directive to forward the subrequest to the new destination server:

location /new-uri {     
   post_action /forward-request; 
}

This configuration ensures that when a POST request is sent to the original URI, it will be matched by the first location block and rewritten to the new URI. The second location block will match the new URI and create a subrequest using the post_action directive. Finally, the third location block will match the URI specified in the post_action directive and use the proxy_pass directive to forward the subrequest to the new destination server.

5.2. Using the proxy_pass Directive

The proxy_pass method involves using the proxy_pass directive to forward the request to a different server. This method is commonly meant for load balancing and caching.

We need to follow these steps to forward HTTP POST request via rewrite using the proxy_pass method:

Firstly, let’s open the Nginx configuration file to add to it a new server block that listens on the desired port and server name:

server {  
   listen 80; 
   server_name example.com; 
}

This file is typically located at /etc/nginx/nginx.conf. Then, we add a new location block to the server block that matches the original URL and uses the rewrite directive to modify the URL:

location /original-url { 
   rewrite ^/original-url /new-url break; 
   proxy_pass http://backend-server; 
}

In this example, the rewrite directive replaces “*/original-url” with “/new-url*“. The break flag prevents further processing of the rewritten URL. The proxy_pass directive forwards the request to the backend-server.

5.3. Using the rewrite_by_lua_block Directive

The rewrite_by_lua_block directive is a powerful feature of Nginx that allows us to execute Lua code in the context of an Nginx location block. It dynamically rewrites URIs, including forwarding HTTP POST requests via rewrite.

We need to follow these steps to use the rewrite_by_lua_block directive to forward HTTP POST requests via rewrite:

Firstly, let’s define a location block that matches the original request URI:

location /original-uri { 
   # ... 
}

Then let’s use the rewrite_by_lua_block directive to execute a Lua script that changes the URI to the new destination:

location /original-uri { 
   rewrite_by_lua_block { ngx.req.set_uri("/new-uri") } 
   # ... 
}

Next, we define a new location block that matches the new URI and handles the request:

location /new-uri { 
   # handle the request 
   # ... 
}

In this configuration, when a POST request is sent to the original URI, it will be matched by the first location block and the Lua script will execute, changing the URI to the new destination. The request will then be processed by the new location block.

One benefit of using the rewrite_by_lua_block directive is the ability to write complex Lua scripts that can modify the request in a variety of ways. Likewise, we can do so by changing request headers, modifying request parameters, or performing custom authentication. Additionally, Lua code can access external resources such as databases or web APIs, which can be useful for more advanced use cases.

5.4. Using the fastcgi_pass Directive

The fastcgi_pass directive is another method that can be used to forward HTTP POST requests via rewrite in Nginx. FastCGI is a protocol that enables communication between a web server and a backend application server, such as PHP-FPM or Python. By using the fastcgi_pass directive, Nginx can forward requests to a FastCGI server, which can process the request and send a response back to Nginx.

We need to take the following steps to use the fastcgi_pass directive to forward HTTP POST requests via rewrite:

Firstly, let’s define a location block that matches the original request URI:

location /original-uri {
  # ...
}

Then we use the rewrite directive to change the URI to the new destination and set the FastCGI parameters for the request:

location /original-uri {
  rewrite /original-uri /new-uri;
  fastcgi_param REQUEST_METHOD POST;
  fastcgi_param CONTENT_TYPE $content_type;
  fastcgi_param CONTENT_LENGTH $content_length;
  fastcgi_pass unix:/var/run/php-fpm.sock;
}

Finally, we define a new location block that matches the new URI and use the fastcgi_pass directive to forward the request to the FastCGI server:

location /new-uri {
  fastcgi_pass unix:/var/run/php-fpm.sock;
}

This configuration will ensure that when a POST request is sent to the original URI, it will be matched by the first location block and rewritten to the new URI. The FastCGI parameters are set to ensure that the request method and headers are correctly forwarded to the FastCGI server. Finally, the fastcgi_pass directive is used to forward the request to the FastCGI server.

5.5. Using the proxy_pass_request_body Directive

When an HTTP POST request is made, the request body may contain important data that needs to be processed by the destination server. However, when using the proxy_pass directive to forward the request to a new location, the request body may not be included by default. This can result in missing data on the destination server and errors in processing the request.

The proxy_pass_request_body directive is an Nginx directive that can be used to forward the request body of an HTTP POST request when using the proxy_pass directive to forward requests via rewrite.

We need to follow these steps to use the proxy_pass_request_body directive to forward the request body of an HTTP POST request:

We first define a location block that matches the original request URI:

location /original-uri { 
  # ... 
}

Then, let’s use the rewrite directive to change the URI to the new destination:

location /original-uri { 
   rewrite /original-uri /new-uri; 
   # ... 
}

Now, we define a new location block that matches the new URI and handles the request:

location /new-uri {
   # handle the request
   # ...
}

6. Conclusion

In this article, we learned how forwarding HTTP POST requests via rewrite can be a useful technique when we need to process data on a different page without the user having to navigate away from the original page.

We also understood that with the right tools and knowledge, we can easily set up a system to accomplish this task.

While this technique requires some server-side scripting knowledge, it can be a powerful tool in our web development arsenal.