Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: November 27, 2022
Nginx is a popular web server that we can also use as a load balancer, forward proxy, or reverse proxy. Reverse proxies are applications that stand between clients and internal servers. They accept network traffic from clients and forward it to the internal network. As a result, clients can’t directly access internal servers. Instead, they can reach them only through the reverse proxy.
In this tutorial, we’ll learn how we can configure Nginx to serve multiple endpoints under the same location. To that end, we’ll use the reverse proxy settings of the Nginx server.
Nginx uses configuration files where we can define how the server processes HTTP requests. The main Nginx configuration file is nginx.conf. On Ubuntu systems, we can find it under the /etc/nginx directory. We can enter Nginx directives into this file.
Furthermore, directives can be grouped into blocks. These blocks are called contexts.
The server block defines a virtual server. To set a listening port and a hostname or IP address, we use the listen directive:
server {
listen 127.0.0.1:8080;
}
Here, we created a virtual server that listens on port 8080 on the localhost address (127.0.0.1).
A location block contains configuration for how the server should handle a set of matched HTTP requests. We define a location with either a prefix string or a regular expression. So, Nginx tries to match the URL of an incoming HTTP request to the string prefix or the regular expression of a location block. If there’s a match, it selects this location block to process the HTTP request.
Also, we can use the root directive to set a filesystem directory to serve the content:
server {
listen 127.0.0.1:8080;
location /books {
root /data/categories;
}
}
In the above example, we added a location that returns files from the /data/categories directory of the local filesystem. Moreover, we set the prefix string /books to location. Consequently, we’ll match URLs starting with /books.
Notably, the Nginx root directive appends the whole HTTP request’s URL path to the local directory path. For example, the URL path /books/echo.json will be translated to the /data/categories/books/echo.json path of the local filesystem.
An alternative to the root directive is the alias directive. The alias directive appends the HTTP request’s URL to the local directory path, but omits the string prefix:
location /books {
alias /data/categories;
}
So, the above block translates the URL path /books/echo.json to /data/categories/echo.json.
A nice feature of the Nginx server is that we can reload the configuration without restarting the server:
$ sudo nginx -s reload
Here, we use the -s option to send a reload signal to the Nginx server. Thus, we reload the configuration files. So, we can use this option instead of restarting the server, avoiding downtime.
In this example, first, we’ll create two virtual servers that simulate two endpoints. Then, we configure the Nginx server to proxy requests to the endpoints under the same URL path.
Let’s create the two dummy endpoints:
server {
listen 8081;
location /client1 {
alias /data/client1;
}
}
server {
listen 8082;
location /client2 {
alias /data/client2;
}
}
As we can see, we defined two virtual servers. Each server block contains a location:
Now, we can set the forwarding.
To set up forwarding, we insert the proxy_pass directive inside a location block. The proxy_pass directive forwards HTTP requests to a specified network address. The latter can be an IP address or a domain name:
server {
listen 8000;
location /api {
proxy_pass http://127.0.0.1:8081/client1;
}
location /api/client2 {
proxy_pass http://127.0.0.1:8082/client2;
}
}
Here, we created a virtual server that listens on port 8000. Moreover, we created two locations inside the virtual server:
Another key point is how proxy_pass forwards URL paths. There are two cases:
In the first case, the request URL path is appended to the proxy_pass address without the location prefix string. So, /api/echo.json will be forwarded to http://127.0.0.1:8081/client1/echo.json. In other words, /api is replaced by /client1.
In the second case, the request URL path is appended to the proxy_pass address with the location prefix string:
location /api {
proxy_pass http://127.0.0.1:8081;
}
Here, a request URL path /api/echo.json will be proxied to http://127.0.0.1:8081/api/echo.json.
Before we test our settings, we should create some test files in the /data/client1 and /data/client2 directories:
$ sudo echo { 'message' : 'Hello from client1' } | sudo tee /data/client1/echo.json
{ message : Hello from client1 }
$ sudo echo { 'message' : 'Hello from client2' } | sudo tee /data/client2/echo.json
{ message : Hello from client2 }
It’s worth noting that we should have sudo rights to create files or sub-directories in the /data directory.
Now we’re ready to test:
$ curl http://127.0.0.1:8000/api/echo.json
{ message : Hello from client1 }
$ curl http://127.0.0.1:8000/api/client2/echo.json
{ message : Hello from client2 }
As expected, the requested JSON files were printed to the output. To sum up, let’s look at the processing of the first HTTP request:
Moreover, the second message had similar processing. In fact, the only difference is that the HTTP request path /api/client2/echo.json is translated to /client2/echo.json.
In this article, we learned how we can use the Nginx server as a reverse proxy. Also, we saw an example where we proxied two endpoints under a single location path.