Puncte:0

Nginx returnează 415 când folosește image_filter cu webp

drapel za

Am câteva fișiere jpg/png care sunt redimensionate într-o locație (cu filtru_imagine modul) și funcționează bine.Dar, am și un webp versiunea unor imagini și vreau să servesc webp unul dacă există. Daca nu, originalul jpg/png imaginea trebuie servită.

Eu folosesc următoarea configurație:

harta $http_accept $webp_sufx {
    Mod implicit        "";
    „~imagine/webp” „webp”;
}

locație ~ „/@s/(.*)(png|jpe?g)” {
    alias $BASE_PATH/$1;
    try_files $webp_sufx $2 $uri;

    redimensionare image_filter 1200 -;
    image_filter_jpeg_quality 80;
    imagine_filter_buffer 10M;
}

Dar nginx returnează a 415 Tip media neacceptat eroare când este găsită versiunea webp. Dacă webp fișierul lipsește, servește fișierul jpg/png fără nicio eroare. Versiunea Nginx este 1.16.1.

Ivan Shatsky avatar
drapel gr
Răspunde asta la întrebarea ta? [NGINX: map and try\_files nu funcționează](https://serverfault.com/questions/1036804/nginx-map-and-try-files-not-working)
Ivan Shatsky avatar
drapel gr
Pe lângă faptul că utilizați incorect directiva `try_files`, există încă o avertizare folosind variabile derivate `map` în locația expresiei regulate cu grupurile de captură numerotate. O explicație și un exemplu de lucru sunt oferite aici: [NGINX: map and try_files not working](https://serverfault.com/questions/1036804/nginx-map-and-try-files-not-working).
Erfun avatar
drapel za
@IvanShatsky Am schimbat variabilele numerice în variabile numite, dar nu văd nicio diferență. Încă se primește „415 Unsupported Media Type”.
drapel us
S-ar putea ca `image_filter` să citească numele fișierului din variabila `$uri` și să creadă că imaginea este JPEG.
Erfun avatar
drapel za
@TeroKilkanen După cum este descris în documente, WEBP ar trebui să fie acceptat în image_filter, dar din anumite motive, nu funcționează.
drapel us
Bănuiesc că acceptă corect formatul WEBP atunci când adresa URL de solicitare reală conține extensia `.webp`. În configurația dvs., adresa URL a solicitării este `.png` sau `.jpg`, oricare este extensia originală. Prin urmare, `image_filter` încearcă să acceseze imaginea folosind un decodor greșit. Este posibil să nu fie posibilă combinarea modulelor de mapare și `image_filter`.
drboczek avatar
drapel dk
ți-ai rezolvat problema cu nginx și webp? Am aceeasi problema :) centos 7 de asemenea, epel nginx 1.20 Încerc nginx repo cu nginx 1.21, dar fără efect.
Erfun avatar
drapel za
@drboczek Din păcate nu, nu am putut. În schimb, am folosit funcția de conversie WEBP a furnizorului nostru CDN, care este disponibilă și pe Cloudflare.
Puncte:0
drapel us

A more streamlined configuration for this is:

map $http_accept $webpuri {
    ~image/webp    $uri.webp;
    default        "";
}

location ~ \.png|jpe?g$ {
    try_files    $webpuri $uri;
    ...
}

Your root directive is used here to get the full path to files on your filesystem.

Erfun avatar
drapel za
Nu înțeleg unde este diferența. Am folosit `alias` în loc de `root` pentru a adresa calea fișierului pe sistemul de fișiere.
drapel us
Codul de mai sus nu folosește expresii regulate pentru a împărți URI-ul în partea de bază și extensie a numelui de fișier, ceea ce este destul de hacker. În schimb, luăm calea completă a fișierului și adăugăm `.webp` după întreaga cale.
Erfun avatar
drapel za
Cred că `image_filter` a cauzat problema, nu expresia regulată. Dacă elimin image_filter, propriul meu cod funcționează. Deci, evident că nu este nimic în neregulă cu adresarea fișierului.
Puncte:0
drapel gr

Nu este un răspuns, dar prea lung pentru a fi un comentariu.

@TeroKilkanen a făcut o presupunere:

S-ar putea să fie asta filtru_imagine citește numele fișierului din $uri variabilă și crede că imaginea este JPEG.

Să verificăm dacă este adevărat. Din fericire, nginx este un software open source și codul sursă al ngx_http_image_filter_module este disponibil Aici.

Principalul ngx_http_image_body_filter funcţie a început la linia 291.Să ne uităm la început:

    ...
    comutator (ctx->faza) {

    caz 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);

        dacă (ctx->type == NGX_HTTP_IMAGE_NONE) {

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

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

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

            returnează ngx_http_filter_finalize_request(r,
                                              &ngx_http_image_filter_module,
                                              NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
        }
        ...

Vedem că este ngx_http_image_test funcție care este responsabilă pentru decizia privind validitatea imaginii. Să ne uităm la acea funcție (a început la linia 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 (în->buf->last - p < 16) {
        returnează NGX_HTTP_IMAGE_NONE;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "filtru de imagine: \"%c%c\"", p[0], p[1]);

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

        /* JPEG */

        returnează NGX_HTTP_IMAGE_JPEG;

    } else if (p[0] == „G” && p[1] == „I” && p[2] == „F” && p[3] == „8”
               && p[5] == „a”)
    {
        dacă (p[4] == '9' || p[4] == '7') {
            /* GIF */
            returnează 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 */

        returnează 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 */

        returnează NGX_HTTP_IMAGE_WEBP;
    }

    returnează NGX_HTTP_IMAGE_NONE;
}

Cred că este destul de clar că funcția de mai sus analizează primii 16 octeți ai tamponului încercând să găsească una dintre cele patru semnături cunoscute. Deci problema nu este legată de $uri valoare variabilă.

Care poate fi cauza? Bine, ngx_http_image_filter_module documentație spune următoarele:

Acest modul utilizează libgd bibliotecă. Este recomandat să utilizați cea mai recentă versiune disponibilă a bibliotecii.

Suportul formatului WebP a apărut în versiunea 1.11.6. Pentru a transforma imaginile în acest format, libgd biblioteca trebuie să fie compilată cu suportul WebP.

Poate că problema este în versiunea ta nginx. Verificați WebP-ul și filtru_imagine compatibilitate fără transformări suplimentare URI, ceva de genul

locație ~ \.webp$ {
    redimensionare image_filter 1200 -;
    image_filter_jpeg_quality 80;
    imagine_filter_buffer 10M;
}

și apoi solicitarea fișierului WebP existent în mod explicit. Dacă tot vei primi un 415 Tip media neacceptat eroare, problema este cel mai probabil în versiunea dvs. nginx.

Erfun avatar
drapel za
Am testat `image_filter` cu `webp` și a existat aceeași problemă `415 Unsupported Media Type`. Deci, probabil că există o problemă cu `libgd`. Mi-am instalat `nginx` din depozitul oficial yum. Ar trebui să-l construiesc manual cu orice configurație personalizată?
Ivan Shatsky avatar
drapel gr
Ce distribuție Linux folosești?
Erfun avatar
drapel za
Este un server Centos 7.
Ivan Shatsky avatar
drapel gr
Și încă o întrebare, ce repo folosești? Este depozitul oficial nginx sau EPEL sau altceva?
Erfun avatar
drapel za
Este repo-ul EPEL.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.