Nginx 415 error

Модуль ngx_http_image_filter_module (0.7.54+) — это фильтр для преобразования изображений в форматах JPEG, GIF, PNG и WebP.

Модуль ngx_http_image_filter_module (0.7.54+) — это фильтр
для преобразования изображений в форматах JPEG, GIF, PNG и WebP.

По умолчанию этот модуль не собирается, его сборку необходимо
разрешить с помощью конфигурационного параметра
--with-http_image_filter_module.

Для сборки и работы этого модуля необходима библиотека
libgd.
Рекомендуется использовать самую последнюю версию библиотеки.

Поддержка формата WebP появилась в версии 1.11.6.
Для преобразования изображений в данном формате
библиотека libgd должна быть собрана с поддержкой WebP.

Пример конфигурации

location /img/ {
    proxy_pass   http://backend;
    image_filter resize 150 100;
    image_filter rotate 90;
    error_page   415 = /empty;
}

location = /empty {
    empty_gif;
}

Директивы

Синтаксис: image_filter off;
image_filter test;
image_filter size;
image_filter
rotate
90 | 180 |
270;

image_filter
resize
ширина
высота;

image_filter
crop
ширина
высота;
Умолчание:
image_filter off;
Контекст: location

Задаёт тип преобразования изображения:

off
отключает обработку данным модулем во вложенном location.
test
проверяет, что ответ действительно является изображением
в формате JPEG, GIF, PNG или WebP.
В противном случае возвращается ошибка
415 (Unsupported Media Type).
size
выдаёт информацию об изображении в формате JSON, например:

{ "img" : { "width": 100, "height": 100, "type": "gif" } }

В случае ошибки выдаётся

{}
rotate
90|180|270
поворачивает изображение против часовой стрелки на указанное число градусов.
В значении параметра допустимо использование переменных.
Можно использовать как отдельно, так и совместно с преобразованиями
resize и crop.
resize
ширина
высота
пропорционально уменьшает изображение до указанных размеров.
Если требуется уменьшить только по одному измерению, то в качестве второго
можно указать “-”.
В случае ошибки сервер возвращает код
415 (Unsupported Media Type).
В значениях параметров допустимо использование переменных.
При использовании совместно с rotate,
поворот изображения происходит после
уменьшения размеров изображения.
crop
ширина
высота
пропорционально уменьшает изображение до размера большей стороны
и обрезает лишние края по другой стороне.
Если требуется уменьшить только по одному измерению, то в качестве второго
можно указать “-”.
В случае ошибки сервер возвращает код
415 (Unsupported Media Type).
В значениях параметров допустимо использование переменных.
При использовании совместно с rotate,
поворот изображения происходит до
уменьшения размеров изображения.
Синтаксис: image_filter_buffer размер;
Умолчание:
image_filter_buffer 1M;
Контекст: http, server, location

Задаёт максимальный размер буфера для чтения изображения.
При превышении размера сервер вернёт ошибку
415 (Unsupported Media Type).

Синтаксис: image_filter_interlace on | off;
Умолчание:
image_filter_interlace off;
Контекст: http, server, location

Эта директива появилась в версии 1.3.15.

Если включено, то итоговые изображения будут с чересстрочностью.
В случае JPEG итоговые изображения будут в формате “progressive JPEG”.

Синтаксис: image_filter_jpeg_quality качество;
Умолчание:
image_filter_jpeg_quality 75;
Контекст: http, server, location

Задаёт желаемое качество преобразованного изображения
в формате JPEG.
Допустимые значения находятся в диапазоне от 1 до 100.
Меньшим значениям обычно соответствует худшее качество изображения
и меньший объём передаваемых данных.
Максимальное рекомендуемое значение — 95.
В значении параметра допустимо использование переменных.

Синтаксис: image_filter_sharpen процент;
Умолчание:
image_filter_sharpen 0;
Контекст: http, server, location

Повышает резкость итогового изображения.
Процент резкости может быть больше 100.
Значение 0 отключает повышение резкости.
В значении параметра допустимо использование переменных.

Синтаксис: image_filter_transparency on|off;
Умолчание:
image_filter_transparency on;
Контекст: http, server, location

Определяет, сохранять ли прозрачность при обработке изображений
в формате GIF и в формате PNG с цветами, заданными палитрой.
Потеря прозрачности позволяет получить более качественное изображение.
Прозрачность альфа-канала в формате PNG сохраняется всегда.

Синтаксис: image_filter_webp_quality качество;
Умолчание:
image_filter_webp_quality 80;
Контекст: http, server, location

Эта директива появилась в версии 1.11.6.

Задаёт желаемое качество преобразованного изображения
в формате WebP.
Допустимые значения находятся в диапазоне от 1 до 100.
Меньшим значениям обычно соответствует худшее качество изображения
и меньший объём передаваемых данных.
В значении параметра допустимо использование переменных.

Not an answer, but too long to be a comment.

@TeroKilkanen made an assumption:

It might be that image_filter reads the filename from $uri variable, and it thinks the image is JPEG.

Lets check out if it is true. Fortunately, nginx is an open source software and the source code of ngx_http_image_filter_module is available here.

The main ngx_http_image_body_filter function started at line 291. Let’s look at the beginning:

    ...
    switch (ctx->phase) {

    case NGX_HTTP_IMAGE_START:

        ctx->type = ngx_http_image_test(r, in);

        conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);

        if (ctx->type == NGX_HTTP_IMAGE_NONE) {

            if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
                out.buf = ngx_http_image_json(r, NULL);

                if (out.buf) {
                    out.next = NULL;
                    ctx->phase = NGX_HTTP_IMAGE_DONE;

                    return ngx_http_image_send(r, ctx, &out);
                }
            }

            return ngx_http_filter_finalize_request(r,
                                              &ngx_http_image_filter_module,
                                              NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
        }
        ...

We see it is the ngx_http_image_test function that is responsible for the decision about image validity. Let’s look at that function (started at line 423):

static ngx_uint_t
ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in)
{
    u_char  *p;

    p = in->buf->pos;

    if (in->buf->last - p < 16) {
        return NGX_HTTP_IMAGE_NONE;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "image filter: "%c%c"", p[0], p[1]);

    if (p[0] == 0xff && p[1] == 0xd8) {

        /* JPEG */

        return NGX_HTTP_IMAGE_JPEG;

    } else if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F' && p[3] == '8'
               && p[5] == 'a')
    {
        if (p[4] == '9' || p[4] == '7') {
            /* GIF */
            return NGX_HTTP_IMAGE_GIF;
        }

    } else if (p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G'
               && p[4] == 0x0d && p[5] == 0x0a && p[6] == 0x1a && p[7] == 0x0a)
    {
        /* PNG */

        return NGX_HTTP_IMAGE_PNG;

    } else if (p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F'
               && p[8] == 'W' && p[9] == 'E' && p[10] == 'B' && p[11] == 'P')
    {
        /* WebP */

        return NGX_HTTP_IMAGE_WEBP;
    }

    return NGX_HTTP_IMAGE_NONE;
}

I think it is pretty clear that the above function analyze first 16 bytes of the buffer trying to find one of the four known signatures. So the problem isn’t related to the $uri variable value.

What can be the cause? Well, ngx_http_image_filter_module documentation says the following:

This module utilizes the libgd library. It is recommended to use the latest available version of the library.

The WebP format support appeared in version 1.11.6. To transform images in this format, the libgd library must be compiled with the WebP support.

Maybe the problem is in your nginx build. Check the WebP and image_filter compatibility without any additional URI transformations, something like

location ~ .webp$ {
    image_filter                resize 1200 -;
    image_filter_jpeg_quality   80;
    image_filter_buffer         10M;
}

and then requesting the existing WebP file explicitly. If you’ll still get a 415 Unsupported Media Type error, the problem is most likely in your nginx build.

This is the second blog post in our series on deploying NGINX Open Source and NGINX Plus as an API gateway.

  • Part 1 provides detailed configuration instructions for several use cases.


  • This post extends those use cases and looks at a range of safeguards that can be applied to protect and secure backend API services in production:

    • Rate limiting
    • Enforcing specific request methods
    • Applying fine‑grained access control
    • Controlling request sizes
    • Validating request bodies

    Originally published in 2018, this post has been updated to reflect current best practice for API configuration, using nested location blocks to route requests instead of rewrite rules.

  • Part 3 explains how to deploy NGINX Open Source and NGINX Plus as an API gateway for gRPC services.

Note: Except as noted, all information in this post applies to both NGINX Open Source and NGINX Plus. For ease of reading, the rest of the blog refers simply to “NGINX”.

Rate Limiting

Unlike browser‑based clients, individual API clients are able to place huge loads on your APIs, even to the extent of consuming such a high proportion of system resources that other API clients are effectively locked out. Not only malicious clients pose this threat: a misbehaving or buggy API client might enter a loop that overwhelms the backend. To protect against this, we apply a rate limit to ensure fair use by each client and to protect the resources of the backend services.

NGINX can apply rate limits based on any attribute of the request. The client IP address is typically used, but when authentication is enabled for the API, the authenticated client ID is a more reliable and accurate attribute.

Rate limits themselves are defined in the top‑level API gateway configuration file and can then be applied globally, on a per‑API basis, or even per URI.

In this example, the limit_req_zone directive on line 4 defines a rate limit of 10 requests per second for each client IP address ($binary_remote_addr), and the one on line 5 defines a limit of 200 requests per second for each authenticated client ID ($http_apikey). This illustrates how we can define multiple rate limits independently of where they are applied. An API may apply multiple rate limits at the same time, or apply different rate limits for different resources.

Then in the following configuration snippet we use the limit_req directive to apply the first rate limit in the policy section of the “Warehouse API” described in Part 1. By default, NGINX sends the 503 (Service Unavailable) response when the rate limit has been exceeded. However, it is helpful for API clients to know explicitly that they have exceeded their rate limit, so that they can modify their behavior. To this end we use the limit_req_status directive to send the 429 (Too Many Requests) response instead.

You can use additional parameters to the limit_req directive to fine‑tune how NGINX enforces rate limits. For example, it is possible to queue requests instead of rejecting them outright when the limit is exceeded, allowing time for the rate of requests to fall under the defined limit. For more information about fine‑tuning rate limits, see Rate Limiting with NGINX and NGINX Plus on our blog.

Enforcing Specific Request Methods

With RESTful APIs, the HTTP method (or verb) is an important part of each API call and very significant to the API definition. Take the pricing service of our Warehouse API as an example:

  • GET /api/warehouse/pricing/item001        returns the price of item001
  • PATCH /api/warehouse/pricing/item001   changes the price of item001

We can update the URI‑routing definitions in the Warehouse API to accept only these two HTTP methods in requests to the pricing service (and only the GET method in requests to the inventory service).

With this configuration in place, requests to the pricing service using methods other than those listed on line 22 (and to the inventory service other than the one on line 13) are rejected and are not passed to the backend services. NGINX sends the 405 (Method Not Allowed) response to inform the API client of the precise nature of the error, as shown in the following console trace. Where a minimum‑disclosure security policy is required, the error_page directive can be used to convert this response into a less informative error instead, for example 400 (Bad Request).

$ curl https://api.example.com/api/warehouse/pricing/item001
{"sku":"item001","price":179.99}
$ curl -X DELETE https://api.example.com/api/warehouse/pricing/item001
{"status":405,"message":"Method not allowed"}

Applying Fine-Grained Access Control

Part 1 in this series described how to protect APIs from unauthorized access by enabling authentication options such as API keys and JSON Web Tokens (JWTs). We can use the authenticated ID, or attributes of the authenticated ID, to perform fine‑grained access control.

Here we show two such examples.

  • The first example controls access to a specific API resource, extending a configuration presented in Part 1 and using API key authentication to verify that a given API client is on the allowlist.
  • The second example which HTTP methods a client is allowed to use. It implements the JWT authentication method mentioned in Part 1, using a custom claim to identify qualified API clients. (Note that JWT support is exclusive to NGINX Plus.)

Of course, other authentication methods are applicable to these sample uses cases, such as HTTP Basic authentication and OAuth 2.0 token introspection.

Controlling Access to Specific Resources

Let’s say we want to allow only “infrastructure clients” to access the audit resource of the Warehouse API inventory service. With API key authentication enabled, we use a map block to create an allowlist of infrastructure client names so that the variable $is_infrastructure evaluates to 1 when a corresponding API key is used.

In the definition of the Warehouse API, we add a location block for the inventory audit resource (lines 15–20). The if block ensures that only infrastructure clients can access the resource.

Note that the location directive on line 15 uses the = (equals sign) modifier to make an exact match on the audit resource. Exact matches take precedence over the default path‑prefix definitions used for the other resources. The following trace shows how with this configuration in place a client that isn’t on the allowlist is unable to access the inventory audit resource. The API key shown belongs to client_two (as defined in Part 1).

$ curl -H "apikey: QzVV6y1EmQFbbxOfRCwyJs35" https://api.example.com/api/warehouse/inventory/audit
{"status":403,"message":"Forbidden"}

Controlling Access to Specific Methods

As defined above, the pricing service accepts the GET and PATCH methods, which respectively enable clients to obtain and modify the price of a specific item. (We could also choose to allow the POST and DELETE methods, to provide full lifecycle management of pricing data.) In this section, we expand that use case to control which methods specific users can issue. With JWT authentication enabled for the Warehouse API, the permissions for each client are encoded as custom claims. The JWTs issued to administrators who are authorized to make changes to pricing data include the claim "admin":true. We now extend our access control logic so that only administrators can make changes.

This map block, added to the bottom of api_gateway.conf, takes the request method ($request_method) as input and produces a new variable, $admin_permitted_method. Read‑only methods are always permitted (lines 62–64) but access to write operations depends on the value of the admin claim in the JWT (line 65). We now extend our Warehouse API configuration to ensure that only administrators can make pricing changes.

The Warehouse API requires all clients to present a valid JWT (line 7). We also check that write operations are permitted by evaluating the $admin_permitted_method variable (line 25). Note again that JWT authentication is exclusive to NGINX Plus.

Controlling Request Sizes

HTTP APIs commonly use the request body to contain instructions and data for the backend API service to process. This is true of XML/SOAP APIs as well as JSON/REST APIs. Consequently, the request body can pose an attack vector to the backend API services, which may be vulnerable to buffer overflow attacks when processing very large request bodies.

By default, NGINX rejects requests with bodies larger than 1 MB. This can be increased for APIs that specifically deal with large payloads such as image processing, but for most APIs we set a lower value.

The client_max_body_size directive on line 7 limits the size of the request body. With this configuration in place, we can compare the behavior of the API gateway upon receiving two different PATCH requests to the pricing service. The first curl command sends a small piece of JSON data, whereas the second command attempts to send the contents of a large file (/etc/services).

$ curl -iX PATCH -d '{"price":199.99}' https://api.example.com/api/warehouse/pricing/item001
HTTP/1.1 204 No Content
Server: nginx/1.19.5
Connection: keep-alive

$ curl -iX PATCH -d@/etc/services https://api.example.com/api/warehouse/pricing/item001
HTTP/1.1 413 Request Entity Too Large
Server: nginx/1.19.5
Content-Type: application/json
Content-Length: 45
Connection: close

{"status":413,"message":"Payload too large"}

Validating Request Bodies

[Editor – The following use case is one of several for the NGINX JavaScript module. For a complete list, see Use Cases for the NGINX JavaScript Module.]

In addition to being vulnerable to buffer overflow attacks with large request bodies, backend API services can be susceptible to bodies that contain invalid or unexpected data. For applications that require correctly formatted JSON in the request body, we can use the NGINX JavaScript module to verify that JSON data is parsed without error before proxying it to the backend API service.

With the JavaScript module installed, we use the js_import directive to reference the file containing the JavaScript code for the function that validates JSON data.

The js_set directive defines a new variable, $json_validated, which is evaluated by calling the parseRequestBody function.

The parseRequestBody function attempts to parse the request body using the JSON.parse method (line 6). If parsing succeeds, the name of the intended upstream group for this request is returned (line 8). If the request body cannot be parsed (causing an exception), a local server address is returned (line 11). The return directive populates the $json_validated variable so that we can use it to determine where to send the request.

In the URI routing section of the Warehouse API, we modify the proxy_pass directive on line 22. It passes the request to the backend API service as in the Warehouse API configurations discussed in previous sections, but now uses the $json_validated variable as the destination address. If the client body was successfully parsed as JSON then we proxy to the upstream group defined on line 15. If, however, there was an exception, we use the returned value of 127.0.0.1:10415 to send an error response to the client.

When requests are proxied to this virtual server, NGINX sends the 415 (Unsupported Media Type) response to the client.

With this complete configuration in place, NGINX proxies requests to the backend API service only if they have correctly formatted JSON bodies.

$ curl -iX POST -d '{"sku":"item002","price":85.00}' https://api.example.com/api/warehouse/pricing
HTTP/1.1 201 Created
Server: nginx/1.19.5
Location: /api/warehouse/pricing/item002

$ curl -X POST -d 'item002=85.00' https://api.example.com/api/warehouse/pricing
{"status":415,"message":"Unsupported media type"}

A Note about the $request_body Variable

The JavaScript function parseRequestBody uses the $request_body variable to perform JSON parsing. However, NGINX does not populate this variable by default, and simply streams the request body to the backend without making intermediate copies. By using the mirror directive inside the URI routing section (line 16) we create a copy of the client request, and consequently populate the $request_body variable.

The directives on lines 17 and 19 control how NGINX handles the request body internally. We set client_body_buffer_size to the same size as client_max_body_size so that the request body is not written to disk. This improves overall performance by minimizing disk I/O operations, but at the expense of additional memory utilization. For most API gateway use cases with small request bodies this is a good compromise.

As mentioned, the mirror directive creates a copy of the client request. Other than populating $request_body, we have no need for this copy so we send it to a “dead end” location (/_get_request_body) that we define in the server block in the top‑level API gateway configuration.

This location does nothing more than send the 204 (No Content) response. Because this response is related to a mirrored request, it is ignored and so adds negligible overhead to the processing of the original client request.

Summary

In this second blog post of our series about deploying NGINX Open Source and NGINX Plus as an API gateway, we focused on the challenge of protecting backend API services in a production environment from malicious and misbehaving clients. NGINX uses the same technology for managing API traffic that is used to power and protect the busiest sites on the Internet today.

Check out the other post in this series:

  • Part 1 explains how to configure NGINX in some essential API gateway use cases.
  • Part 3 explains how to deploy NGINX as an API gateway for gRPC services.

To try NGINX Plus as an API gateway, start your free 30-day trial today or contact us to discuss your use cases. During your trial, use the complete set of configuration files from our GitHub Gist repo.

While using images, video, and GIFs was not typical in the early days of the web, we now expect that a site offers appealing visuals as well as informative text. It’s also no surprise that when the communication between the browser and server goes awry due to a mismatch in media you’ll see an error. In this case, the “HTTP 415” error.

Because media is almost a prerequisite of the modern web, seeing an error relating to it means you’ll need a fix, fast. However, unlike other error fixes – especially for WordPress websites – this issue is one tough cookie. You may need some coding knowledge to solve this one, but this is something for later on.

Check Out Our Video Guide to Fixing the 415 Error

For this post, we’re going to look into the “HTTP 415” error, and talk about what causes it. From there, we’ll discuss how you’d fix it.

What the HTTP 415 Error Is

The “HTTP 415” error is one of many 4XX status codes. If you understand that it buddies up with errors such as a 404, you’ll begin to understand what’s happening.

In short, 4XX errors all deal with something missing that either the client or the server needs. The full name of the error – a “415 Unsupported Media Type” – gives the game away. The server is receiving a media file type that it doesn’t recognize or can’t accept.

Under most circumstances, you’ll see the “HTTP 415” error when you use an application programming interface (API). It’s a server-side issue, and next, we’ll discuss why this happens in the first place.

When the communication between the browser & server goes awry due to a mismatch in media, you’ll see an error. In this case, the “HTTP 415” error. 😅 Learn how to fix it here ✅Click to Tweet

Why the HTTP 415 Error Happens

Regardless of what you call it – the “HTTP 415” error, the “415 Unsupported Media Type” error – it means that the server refuses to accept a request from the browser. This will often be because whatever the browser sends (the payload) isn’t in the right format.

It’s a similar issue to the “422 Unprocessable Entity” error, as they both deal with the wrong data hitting the server, and the latter freaking out. It’s also worth pointing out that there is a distinction between the data the browser sends, and what the server receives. They may appear to be the same, but there’s a difference.

For example, a general error-catching strategy will stop a user from taking an unrecognized file type and uploading it through an interface that only accepts PNGs. However, if you don’t specify the exact types of media a server can process, it would trigger an error on the back end. On the front end, a user might not see anything at all. WordPress users get an admin screen notification:

The WordPress Upload New Media screen, showing the uploader dialog with a Select Files button, information on the maximum file size, and an admin error that shows a ‘file type not permitted’ error, and details of the file.

The File Type Not Permitted error within WordPress.

The good news is that WordPress has a permissive infrastructure – think of the different file types you can upload to the Media Library, for example.

Even so, this is a developer-level issue rather than user error. As such, we’ll dive into what the fixes might be next.

How To Fix the HTTP 415 Error

To recap, the “HTTP 415” error tells you that the server won’t accept a file type because it doesn’t support that payload. This means there’s an issue within the underlying PHP code that needs a fix.

At this point, if you aren’t the developer of the site or theme, and you don’t have any coding skills, you’ll likely want to contact someone with expertise. Poking around in your theme’s files could cause an issue.

However, the Mozilla documentation on the error gives you two clues to begin your search – two ‘representation headers’: Content-Type, and Content-Encoding.

How the Content-Type and Content-Encoding Headers Work

The Content-Type header provides the client request with the resource before any encoding happens. It indicates the original media type of the resource. For example:


Content-Type: text/html; charset=UTF-8

Content-Type: image/jpeg;

In contrast, Content-Encoding is a list of all of the encodings the payload (i.e. your media) has, which is an indicator of how the file should be decoded in order to get the original payload.


Content-Encoding: gzip

Content-Encoding: br

As you can tell, file compression is a common way to encode data. This isn’t a problem in theory but will be if you don’t code this into the relevant files for your theme or plugin.

Finding a Fix For the HTTP 415 Error Code

Given the above, you’ll have three avenues to explore if you uncover an HTTP 415 error – all of them relating to your PHP code:

  • You’ll want to ensure you send the right Content-Type header value.
  • You will also want to make sure that the server can process whatever you specify for the Content-Type header.
  • Check over what the server can process through the Accept header.

You won’t necessarily do this within core files, although you may do so as part of a REST API request. For example, a user from Stack Overflow had this exact issue when using pure PHP over cURL to make an API request.

There are two places to look. First, specify the correct file types within the Content-Type header:


$headers = array (

    ‘Content-Type’ => ‘application/json’,

   …

Second, this user had a typo while declaring an invalid header key using the wp_remote_post() function:


$arg = array (

    'header' => $headers,

    …

Because “header” misses an “s”, it would throw the “HTTP 415” error. However, you’ll also want to make sure that the client can accept the right file types too. You’ll do this through another header: Accept. For example:


Accept: text/html

Accept: image/*

This makes sure both ends of the chain – the client and server side – can accept and send the right file types, and put a halt to the “HTTP 415” error for good.

Let’s look into the “HTTP 415” error- and talk about what causes it- in this guide 🚀Click to Tweet

Summary

Website errors are often straightforward to fix. We’ve done so a number of times on the Kinsta blog, and the nature of the platform means you can be ready to rock and roll in a short while. However, the “HTTP 415” is different, in that a fix is hard to come by if you’re not a developer.

The solution is to work with the Content-Type header values to make sure you send the right one to the server. You may also have a simple typo. This seems like a “doh” moment, but in this case, they can be tricky to spot, especially if your concern is with the content types you send to the server.

While the “HTTP 415” error is yours to fix, for other issues with your website, Kinsta is on call. We have our support team standing by to help you understand your site on the rare occasions it fails to load.


Get all your applications, databases and WordPress sites online and under one roof. Our feature-packed, high-performance cloud platform includes:

  • Easy setup and management in the MyKinsta dashboard
  • 24/7 expert support
  • The best Google Cloud Platform hardware and network, powered by Kubernetes for maximum scalability
  • An enterprise-level Cloudflare integration for speed and security
  • Global audience reach with up to 35 data centers and 275 PoPs worldwide

Test it yourself with $20 off your first month of Application Hosting or Database Hosting. Explore our plans or talk to sales to find your best fit.

Поставил Ghost, особо не замечал, но тут стал замечать что при большом количестве картинок они очень уж туго подгружаются в браузере, боялся что с сервером что-то не так, а оказалось беда в Ghost, он прямо в оригинальном размере в статьях картинки размещает. Раньше я мало картинок вставлял и не замечал, а тут заметил…

Как же быть? Вспоминаем то что у нас всё идет через NGINX

Проверим что наш nginx собран с нужным модулем, для этого в консоли

nginx -V

Там должен быть параметр сборки

 --with-http_image_filter_module

За это можно особо не париться, в свежих дистрибутивах с этим всё хорошо

Но вот в том же Debian выдаст ошибку

nginx: [emerg] unknown directive "image_filter"

Потомучто нужно установить пакет

apt install libnginx-mod-http-image-filter

А если такой пакет уже утсноавлен, то нужно в самом верху /etc/nginx/nginx.conf прописать

load_module modules/ngx_http_image_filter_module.so;

Открываем конфиг nginx, где прописан наш сайт

У нас там есть что-то типа такого

        location /
        {
        access_log off;
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Nginx-Https "on";
        proxy_connect_timeout 2s;
        }

Перед этим еще один раздел location создадим для картинок (обратите  внимание на порт и на адрес для прокси)

Но у нас сервис находится на локальном сервере, поэтому для картинок не будем ничего проксировать, а сразу прокинем папку локальную

  location ~* ^/content/images/(.+.(?:gif|jpe?g|png))$                      
        {                                                                    
        set $width "-";                                                      
        set $height "-";                                                     
        set $quality "95";                                                   
        if ($arg_w != '')                                                    
        {                                                                    
         set $width $arg_w;                                                  
        }                                                                    
        if ($arg_h != '')                                                    
        {                                                                    
         set $height $arg_h;                                                 
        }                                                                    
        if ($arg_q != '')                                                    
        {                                                                    
         set $quality $arg_q;                                                
        }                                                                    
        #proxy_pass http://localhost:2368;                                   
        #proxy_set_header X-Forwarded-Proto https;                           
                                                                             
        alias /var/www/mysite/content/images/$1;                   
        access_log off;                                                      
        expires 10d;                                                         
        image_filter resize $width $height;                                  
        image_filter_jpeg_quality $quality;                                  
 }                                                                           

Перезагрузим nginx

Тепепь, если открыть любую картинку и добавить к адресу например ?w=100, то увидим что она сразу меньше стала!!!

Если выдает ошибку 415 Unsupported Media Type, значит ваша картинка ну очень огромная, я с таким сталкивался, нужно прописать

image_filter_buffer 6M;

Но тут будет конечно не супер, можете всю оперативку скушать на сервере с такими размерами…

Дальше нужно модифицировать SRC в шаблонах…

Вот тут я запнулся, пришел к выводу, что Ghost нужно или конкретно патчить, или же переходить на альтернативный продукт, жаль что я не имею опыта в NodeJS, но придется его получить! Когда время будет — вернусь к этому вопросу.

Линки

NGINX Docs | Image-Filter

Crop, resize, rotate, and perform other transformations on GIF, JPEG, and PNG images, with the Image-Filter dynamic module supported by NGINX, Inc.

Понравилась статья? Поделить с друзьями:
  • Nfs rivals не работает мода как исправить 2013 года
  • Nfs rivals как изменить управление
  • Nfs rival dx error fixed скачать
  • Nfs read error на телефоне что делать
  • Nfs read error try again что означает