Das Hinzufügen des Headers läuft abhängig vom MIME-Typ in Nginx ab

7

Ausführen von nginx 1.4.1 unter Ubuntu 12.10

Das Senden muss den Header unter bestimmten Bedingungen und basierend auf dem MIME-Typ / Inhaltstyp der http-Antwort senden.

Dieser einfache Code wurde in location / {hinzugefügt

if ($sent_http_content_type = "text/css") { 
expires 7d;
}

Der abgelaufene Header wird nicht gesendet, auch wenn $ sent_http_content_type "text / css" enthält.

Wie kann ich das beheben?

Das Überprüfen von Dateierweiterungen reicht nicht aus, da in meiner App js, css Bilder dynamisch aus PHP generiert werden. Sie müssen also die MIME überprüfen und auch darauf basierend Header hinzufügen.

Silbermond
quelle
Warum nicht einfach mit dem Suffix des Dateinamens übereinstimmen?
Jeffatrackaid
@jeffatrackaid in meiner Anwendung js, css, Bilder werden dynamisch aus PHP-Skripten generiert, die nicht mit der Dateierweiterung übereinstimmen. Daher muss ich Expires und andere Header mit MIME-Prüfung hinzufügen.
Silver Moon
Warum sollten Sie den Expires-Header nicht im PHP-Skript selbst festlegen? Dies ist die richtige Ebene, insbesondere wenn sie sich je nach Art der Anforderung und Inhalt ändern kann. Einige CSS haben beispielsweise eine Lebensdauer von 1 Stunde, andere nur 10 Minuten. Ihr Anwendungscode kennt diese Informationen zur Laufzeit, nginx kann sie in Ihrer Geschäftslogik nicht sehen.
Rmalayter

Antworten:

14

Ab Nginx 1.7.9:

map $sent_http_content_type $expires {
  default         off;
  application/pdf 42d;
  ~image/         max;
}

expires $expires;

HINWEIS: $ sent_http_content_type ist gültig, kann jedoch erst aufgerufen werden, wenn der Server die Anforderung verarbeitet hat ...

Die Antwort zeigt auf den Karteneintrag, für application/pdfden ein Datumswert zulässig ist oder der application/pdf modified +42dbeispielsweise sein könnte

Bellasys
quelle
1
Bei neueren NGINX-Installationen ist dies die gewünschte Antwort.
Oliver
Dieses Beispiel und weitere Details wie die Zeitsyntax finden Sie in den Nginx-Dokumenten .
Drakes
7

Die ifDirektive in Nginx wird frühzeitig beim Umschreiben verarbeitet, und daher wurde die $sent_http_content_typeVariable noch nicht initialisiert. Weitere Informationen finden Sie in diesem Nginx- Fehlerbericht .

EDIT : Wenn man Benutzernamen vergleicht, könnte dieser Fehlerbericht tatsächlich Sie sein! (^_^)

In ähnlicher Weise expiresscheint die Direktive Variablen nicht auf die gleiche Weise zu unterstützen, wie dies beispielsweise der add_headerFall ist. Da Sie also nicht in der Lage sind, den Speicherort basierend auf Dateierweiterungen statisch anzugeben, kann ich mir nur zwei grundlegende Ansätze vorstellen.

Eine Möglichkeit wäre, den von Vadim oben vorgeschlagenen Ansatz mapund zu verwenden add_header, um HTTP-Header manuell festzulegen, anstatt dies der expiresDirektive zu erlauben. Dies ist weniger flexibel, da der ExpiresHeader nicht gesetzt wird , aber ich hoffe, dass heutzutage jeder Browser das Richtige tut, wenn er nur Cache-Controlgesetzt wird. Hier ist ein Beispiel, das ich kurz getestet habe:

map $sent_http_content_type $cacheable_types {
    "text/css"    "max-age=864000";
    "image/jpeg"  "max-age=864000";
    default       "";
}

# ...

server {
    # ...
    location / {
        # ...
        add_header "Cache-Control" $cacheable_types;
    }
}

Der Wert 864000 beträgt 10 Tage in Sekunden - Sie müssen ihn nach Belieben ändern. Der Vorteil dieses Ansatzes besteht darin, dass Sie für jeden Dateityp unterschiedliche Zeiten angeben und sogar andere Aspekte des Cache-ControlHeaders überschreiben können. Sie diskutieren diesen Header hier und den offiziellen Teil des HTTP-RFC hier, wenn Sie etwas Formaleres bevorzugen.

Der zweite Ansatz wäre, einfach zu arrangieren, dass Anforderungen, die zu zwischenspeicherbaren Inhalten führen, alle unter einen bestimmten Pfad fallen, den Sie in einer locationDirektive wie dieser verwenden können:

location / {
    # ...
    location /static {
        expires 10d;
    }
}

Dies erleichtert die Nginx-Konfiguration, da Sie die integrierte expiresDirektive verwenden können. Ob dies jedoch eine Option ist, hängt stark davon ab, ob Sie dieses URL-Muster in Ihrem Code erzwingen können.

Cartroo
quelle
Siehe meinen Kommentar zu Vadims ... hatte eine Idee ...
marksyzm
2

$ sent_http_content_type ist ungültig. Request - Header - Werte können über $ HTTP_ zugegriffen werden Namen . Für den Header vom Inhaltstyp hat nginx außerdem die Variable $ content_type eingebettet.

Wenn Sie $ content_type mit einer Reihe von Typen vergleichen möchten, ist es besser, map zu verwenden:

   map $content_type $test_header {
        "text/css"  OK;
        "text/html" OK;
        ...
        default "";
   }

   server {
        location / {
             add_header "X-Test" $test_header;
        }
   }

Wenn $ test_header als leere Zeichenfolge ausgewertet wird, wird der Header nicht gesetzt.

Weitere Informationen finden Sie unter: http://nginx.org/en/docs/http/ngx_http_core_module.html#variables http://nginx.org/en/docs/http/ngx_http_map_module.html http://nginx.org/ de / docs / http / ngx_http_headers_module.html # add_header

Vadim
quelle
danke dafür, es kann verwendet werden, um einen Header hinzuzufügen, aber ich suche nach mehr, muss ablaufen, basierend auf MIME-Typ
Silver Moon
Denken Sie, Sie könnten den abgelaufenen Wert für jeden setzen $content_type? Dh die Karte könnte einen $ content_type-Wert von 30d oder 1y verwenden und dann könnten Sie diesen location /mit platzieren expires $test_header?
Marksyzm
Ignoriere das ... läuft ab unterstützt es nicht. Sie können jedoch gegen eine if-Anweisung testen und einen harten Wert in expires setzen ... Ich
versuche es gerade
2

Wenn Sie den MIME-Typ verwenden müssen, versuchen Sie:

if ($content_type ~= "text/css") { 
expires 7d;
}

Möglicherweise möchten Sie jedoch Folgendes in Betracht ziehen:

location ~ \.(css|js|htc)$ {
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
         log_not_found off;
         access_log off;

}
location ~ \.(html|htm|rtf|rtx|svg|svgz|txt|xsd|xsl|xml)$ {
    add_header Pragma "public";
    add_header Cache-Control "max-age=3600, public, must-revalidate, proxy-revalidate";
         log_not_found off;
        access_log off;

}
location ~ \.(asf|asx|wax|wmv|wmx|avi|bmp|class|divx|doc|docx|eot|exe|gif|gz|gzip|ico|jpg|jpeg|jpe|mdb|mid|midi|mov|qt|mp3|m4a|mp4|m4v|mpeg|mpg|mp
e|mpp|otf|odb|odc|odf|odg|odp|ods|odt|ogg|pdf|png|pot|pps|ppt|pptx|ra|ram|svg|svgz|swf|tar|tif|tiff|ttf|ttc|wav|wma|wri|xla|xls|xlsx|xlt|xlw|zip)$
 {
    add_header Pragma "public";
    add_header Cache-Control "max-age=31536000, public, must-revalidate, proxy-revalidate";
         log_not_found off;
         access_log off;

}

Wir verwenden dies auf einer sehr belebten Website mit sehr guter Wirkung.

jeffatrackaid
quelle
Ich kann nicht auf Dateierweiterung testen. In meiner Anwendung werden JS, CSS und Bilder im laufenden Betrieb aus PHP-Skripten generiert. Daher brauche ich einige MIME-basierte Überprüfung und Aktivierung läuft ab.
Silver Moon