Baeldung Pro – Ops – NPI EA (cat = Baeldung on Ops)
announcement - icon

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.

1. Introduction

In web development, managing how content is served to clients is crucial for ensuring that files are correctly interpreted and displayed. Nginx, a popular web server, allows for detailed configuration of how it serves different types of content.

In particular, one aspect of this configuration is controlling the Content-Type header that Nginx sends with responses. The Content-Type header informs the browser or client about the type of data the server is sending, enabling proper rendering and functionality.

In this tutorial, we’ll explore how to configure Nginx to send specific Content-Type headers for various types of content. Thus, this tutorial will cover practical steps to enforce Content-Type headers, including real-world examples and configurations.

2. Understanding Content-Type

Whether handling static files or dynamic content, setting the correct Content-Type ensures that clients interpret the data correctly.

For context, the Content-Type header, which is part of the HTTP response, specifies the media type of the resource the server returns. For example, some common Content-Type values include:

  • text/html: for HTML documents
  • application/json: for JSON data
  • image/jpeg: for JPEG images
  • application/pdf: for PDF files

So, properly configuring this header in an Nginx web server is crucial for correct content rendering and functionality. For instance, if a server serves a JSON file with the Content-Type set to text/plain, it may cause issues with how the client handles the data.

3. Configuring Content-Type in Nginx

Nginx uses directives within its configuration files to manage various settings, including Content-Type. So, in this section, let’s walk through configuring Nginx to send specific Content-Type headers.

The primary configuration file for Nginx is nginx.conf. This file can be found in the /etc/nginx/ directory on most Linux systems. So, to set specific Content-Type headers, the configuration can be adjusted using the types directive.

Now, to ensure Nginx sends the correct Content-Type for different file types, we can add or modify the types directive in the http block of nginx.conf. Let’s open the /etc/nginx/nginx.conf default configuration file with nano and add the types directive block:

$ sudo nano /etc/nginx/nginx.conf
...
  http {
    include       mime.types;
    default_type  application/octet-stream;

    types {
        text/html                            html htm;
        text/css                             css;
        text/javascript                      js;
        application/json                     json;
        application/xml                      xml;
        image/jpeg                           jpeg jpg;
        image/png                            png;
        application/pdf                      pdf;
        application/x-woff                   woff;
        application/x-font-ttf               ttf;
    }
    ...
}

As shown above, we added the types directive, which specifies all the content types, into the configuration file. With the types directive specified, Nginx knows the content type to return for a request.

Let’s test our configuration to ensure it’s working. First, we need to restart Nginx to apply the new configuration:

$ sudo systemctl restart nginx

With no error output, this means the command was successful. Now, let’s create test files for each file type in the directory where Nginx is serving content, which is usually /var/www/html/:

$ echo "<html><body><h1>HTML Test</h1></body></html>" | sudo tee /var/www/html/test.html
<html><body><h1>HTML Test</h1></body></html>

$ echo "body { background-color: #f0f0f0; }" | sudo tee /var/www/html/style.css
body { background-color: #f0f0f0; }

$ echo "console.log('JavaScript Test');" | sudo tee /var/www/html/script.js
console.log('JavaScript Test');
...

We’ve successfully created a test file for each file type we configured.

Next, we can use curl to request these files and inspect the Content-Type headers that Nginx sends in the response:

$ curl -I http://localhost/test.html
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Sat, 14 Sep 2024 15:11:08 GMT
Content-Type: text/html
...

$ curl -I http://localhost/style.css
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Sat, 14 Sep 2024 15:11:08 GMT
Content-Type: text/css
...

As shown above, we’ve used curl -I to request two of the previous file types we created and grab only their headers to get their Content-Type. In this case, we requested the html and css file types, and the respective results were text/html and text/css.

The above configuration summarizes how to use the global setting where all Content-Type is set using the types directive.

4. Setting Content-Type in a server Block or location Block

In addition to global settings, we can set specific Content-Type values within individual server blocks or location blocks. This is useful when we require different content types for specific parts of a website.

Notably, server block configurations override global settings and provide custom behavior for sections like APIs or static assets. Let’s break this down in more detail and explore how it works.

4.1. server Block

A server block in Nginx handles configurations for a specific domain or website. In addition, the configuration files for Nginx are located in /etc/nginx/sites-available/ for Debian-based systems or /etc/nginx/conf.d/ for CentOS and RHEL.

Let’s create and configure a new configuration file for a hypothetical domain, gbenga.com, for this illustration:

$ sudo nano /etc/nginx/sites-available/gbenga.com
server {
    listen       80;
    server_name  gbenga.com;

    root /var/www/gbenga.com/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

In the server block configuration, we configure Nginx to listen on port 80 for HTTP requests while we specify the domain name, gbenga.com, for this block to handle.

Next, we can create the web directory and test page. Let’s create a test file, set its permissions, and serve it:

$ sudo mkdir -p /var/www/gbenga.com/html
$ sudo chown -R $USER:$USER /var/www/gbenga.com/html
$ sudo nano /var/www/gbenga.com/html/index.html
<html>
<head>
    <title>Welcome to Gbenga.com!</title>
</head>
<body>
    <h1>Success! The server block is working.</h1>
</body>
</html>

We use the last command to create a new file named index.html, where we save the HTML code snippet.

The next step is to enable the server block and test that the configuration is working:

$ sudo ln -s /etc/nginx/sites-available/gbenga.com /etc/nginx/sites-enabled/
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

The output shows that the test is successful and the configuration is correct. Lastly, let’s restart the nginx service:

$ sudo systemctl restart nginx

The command restarted the nginx service successfully without any error output.

To test this server block using the domain gbenga.com, let’s map the domain to the localhost in the hosts configuration file:

$ sudo nano /etc/hosts
127.0.0.1 localhost
127.0.1.1 gbenga.com
# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
...

By placing the hypothetical domain we created beside the 127.0.1.1 entry, we mapped the domain to localhost, which simulates DNS resolution. Now, let’s make a request to the domain to confirm that the server block sets the correct Content-Type:

$ curl -I http://gbenga.com
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Date: Sat, 14 Sep 2024 17:41:55 GMT
Content-Type: text/html
...
Accept-Ranges: bytes

The result demonstrates that Nginx sets the content type properly, which tells the browser how to interpret the file.

4.2. location Block

Inside the server block, we can define location blocks that specify how different parts of the site identified by URLs should behave. In essence, this is where we can set different configurations for content, such as the Content-Type.

Let’s illustrate this with the two most common examples that fall under location blocks: APIs and static Content-Type.

Here’s a sample configuration for a customized API content type:

location /api/ {
    default_type application/json;
    try_files $uri $uri/ =404;
}

The location block tells Nginx how to handle requests that start with /api/. For example, a request to http://gbenga.com/api/data would match this block.

Furthermore, the default_type directive forces all responses served from this location to have the Content-Type set to application/json. This holds true even if the file extension is .txt, .xml, or anything else, as Nginx will override it. Thus, Nginx tells the client that the response is JSON data.

Let’s examine the location block configuration for static file serving. We can also have this in the same server block as our previous configuration:

location /static/ {
    root   /var/www/html;
    try_files $uri $uri/ =404;
}

This block matches any requests that start with /static/. For example, a request to http://gbenga.com/static/logo.png would match this block.

5. Conclusion

In this article, we provided a comprehensive guide to configuring Content-Type in Nginx, including how to enforce Content-Type for files served from specific web directories.

With this knowledge, administrators can ensure the correct Content-Type for different types of content by modifying the nginx.conf file and setting headers in server or location blocks.