Im vorherigen Artikel haben wir erklärt, wie nginx die Daten der Anforderungszeile liest und die Anforderungszeile analysiert. In diesem Artikel erklären wir hauptsächlich, wie nginx die vom Client gesendeten Anforderungsheaderdaten liest und diese Daten analysiert. Im Wesentlichen ist der Datenlesevorgang der Anforderungszeile und des Anforderungsheaders grundsätzlich derselbe, da in beiden Fällen das Problem auftritt, wie Daten aus intermittierenden Datenströmen gelesen und wie die Daten verarbeitet werden. 1. Fordern Sie den Header-Lesen-Hauptprozess an Bevor wir den Lesevorgang des Anforderungsheaders vorstellen, zeigen wir zunächst ein Beispiel einer HTTP-Anforderungsnachricht: POST /web/buch/lesen HTTP/1.1 Host: localhost Verbindung: Keep-Alive Inhaltslänge: 365 Akzeptieren: application/json, text/plain, */* Die erste Datenzeile im Beispiel ist die Anforderungszeile und die folgenden Zeilen sind Anforderungsheader. Jeder Anforderungsheader wird im Name:Wert-Format zusammengestellt und jeder Anforderungsheader nimmt eine Zeile ein. Im vorherigen Artikel, in dem der Lesevorgang der Anforderungszeile vorgestellt wurde, haben wir erwähnt, dass nginx nach dem Lesen der Anforderungszeile die Rückruffunktion des aktuellen Lese-Ereignisses in die Methode ngx_http_process_request_headers() ändert und diese Methode direkt aufruft, um zu versuchen, die Header-Daten der Anforderung zu lesen. Diese Methode ist der Hauptprozess zum Lesen der Anforderungszeilendaten. Im Folgenden finden Sie den Quellcode dieser Methode: /** * Analysieren Sie die vom Client gesendeten Headerdaten*/ statischer void ngx_http_process_request_headers(ngx_event_t *rev) { u_char *p; Größe_t Länge; ssize_t n; ngx_int_t rc, rv; ngx_table_elt_t *h; ngx_connection_t *c; ngx_http_header_t *hh; ngx_http_request_t *r; ngx_http_core_srv_conf_t *cscf; ngx_http_core_main_conf_t *cmcf; c = rev->Daten; r = c->Daten; wenn (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "Zeitüberschreitung beim Client"); c->Zeitüberschreitung = 1; ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); zurückkehren; } cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); rc = NGX_AGAIN; für (;;) { wenn (rc == NGX_AGAIN) { // Wenn im aktuellen Header-Puffer kein freier Platz mehr vorhanden ist, neuen Platz beantragen, if (r->header_in->pos == r->header_in->end) { // Neuen Speicherplatz beantragen rv = ngx_http_alloc_large_header_buffer(r, 0); wenn (rv == NGX_ERROR) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); zurückkehren; } // Der vom Client gesendete Header ist zu lang und überschreitet die durch large_client_header_buffers angegebene Maximalgröße if (rv == NGX_DECLINED) { p = r->Headername_Start; r->lingering_close = 1; wenn (p == NULL) { ngx_log_error(NGX_LOG_INFO, c->log, 0, „Client hat zu große Anfrage gesendet“); ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_ZU_GROSS); zurückkehren; } Länge = r->header_in->end - p; wenn (Länge > NGX_MAX_ERROR_STR - 300) { Länge = NGX_MAX_ERROR_STR – 300; } ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_ZU_GROSS); zurückkehren; } } // Versuchen Sie, die neu gesendeten Daten vom verbundenen Client zu lesen n = ngx_http_read_request_header(r); wenn (n == NGX_AGAIN || n == NGX_ERROR) { zurückkehren; } } cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); // Hier konvertieren wir hauptsächlich die gelesenen Daten rc = ngx_http_parse_header_line(r, r->header_in, cscf->underscores_in_headers); // NGX_OK zeigt an, dass die Analyse und der Abruf von Header-Daten erfolgreich waren, wenn (rc == NGX_OK) { r->Anforderungslänge += r->Header_in->Pos - r->Header_Name_Start; // Ungültige Header filtern wenn (r->ungültiger_Header und cscf->ungültige_Header_ignorieren) { weitermachen; } // Erstellen Sie eine Struktur zum Speichern von Headern h = ngx_list_push(&r->headers_in.headers); wenn (h == NULL) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); zurückkehren; } h->Hash = r->Header_Hash; //Verwende den Header-Namen als Schlüssel der Hash-Tabelle h->Schlüssel.Länge = r->Headername_Ende - r->Headername_Start; h->Schlüssel.Daten = r->Headername_Start; h->Schlüssel.Daten[h->Schlüssel.Länge] = '\0'; //Verwende den Header-Wert als Hash-Tabellenwert h->Wert.Länge = r->Header_Ende - r->Header_Start; h->Wert.Daten = r->Header_Start; h->Wert.Daten[h->Wert.Länge] = '\0'; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); wenn (h->lowcase_key == NULL) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); zurückkehren; } wenn (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); } anders { ngx_strlow(h->lowcase_key, h->key.data, h->key.len); } // headers_in_hash speichert alle Header. Hier prüfen wir, ob der vom aktuellen Client gesendete Header ein gültiger Header ist. hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); // Der Handler ist hier die für jeden Header in ngx_http_headers_in definierte Verarbeitungsmethode. Nach der Verarbeitung durch die // handler()-Methode jedes Headers wird der vom Client gesendete Header in die verschiedenen Attribute in der Struktur r->headers_in konvertiert, wenn (hh && hh->handler(r, h, hh->offset) != NGX_OK) { zurückkehren; } weitermachen; } // NGX_HTTP_PARSE_HEADER_DONE bedeutet, dass alle Header verarbeitet wurden, wenn (rc == NGX_HTTP_PARSE_HEADER_DONE) { r->Anforderungslänge += r->Header_in->Pos - r->Header_Name_Start; r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; // Überprüfen Sie die Legitimität der vom Client gesendeten Header-Daten rc = ngx_http_process_request_header(r); wenn (rc != NGX_OK) { zurückkehren; } ngx_http_process_request(r); zurückkehren; } // NGX_AGAIN zeigt an, dass die gelesenen Kopfzeilendaten unvollständig sind und weiter gelesen werden müssen, wenn (rc == NGX_AGAIN) { weitermachen; } ngx_log_error(NGX_LOG_INFO, c->log, 0, "Client hat ungültige Headerzeile gesendet"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); zurückkehren; } } Das Lesen des Anforderungsheaders gliedert sich hierbei im Wesentlichen in folgende Schritte:
2. Lesen der Anforderungsheaderdaten Wie Sie sehen, gibt es zwei Hauptmethoden zum Lesen des Anforderungsheaders: ngx_http_read_request_header() und ngx_http_parse_header_line(). Die zweite Methode hier ist relativ lang, aber ihre Logik ist sehr einfach. Sie analysiert hauptsächlich die gelesenen Daten, um zu sehen, ob sie einen vollständigen Anforderungsheader bilden können (in der Form Name: Wert und nimmt eine Zeile ein). Wenn ja, gibt sie NGX_OK zurück, andernfalls gibt sie NGX_AGAIN zurück, in der Hoffnung, mit dem Lesen der Daten fortzufahren. Wir werden diese Methode hier nicht erklären. Leser können den Quellcode selbst lesen. Wir werden hauptsächlich erklären, wie die Methode ngx_http_read_request_header() die vom Client gesendeten Anforderungsheaderdaten liest: statische ssize_t ngx_http_read_request_header(ngx_http_request_t *r) { ssize_t n; ngx_event_t *rev; ngx_connection_t *c; ngx_http_core_srv_conf_t *cscf; c = r->Verbindung; rev = c->lesen; // Berechnen, wie viele Daten noch nicht verarbeitet wurden n = r->header_in->last - r->header_in->pos; // Wenn n größer als 0 ist, bedeutet dies, dass noch unverarbeitete Daten vorhanden sind. Dann gib n direkt zurück wenn (n > 0) { Rückkehr n; } // Wenn Sie hierher gehen, bedeutet dies, dass die aktuell gelesenen Daten verarbeitet wurden. Daher wird hier eine Beurteilung vorgenommen. Wenn der Bereitschaftsparameter des aktuellen Ereignisses 1 ist, // Dies bedeutet, dass der Handle der aktuellen Verbindung ungelesene Daten speichert, sodass die Methode c->recv() aufgerufen wird, um die Daten zu lesen. Andernfalls wird das aktuelle Ereignis zur // Ereigniswarteschlange hinzugefügt und das Leseereignis des aktuellen Verbindungs-Handles wird weiterhin überwacht, wenn (rev->ready) { // Daten im Verbindungsdateideskriptor lesen n = c->recv(c, r->header_in->last, r->header_in->end - r->header_in->last); } anders { n = NGX_AGAIN; } // Wenn n NGX_AGAIN ist, füge das aktuelle Ereignis dem Ereignislistener hinzu und höre weiterhin auf das Leseereignis des aktuellen Epoll-Handles, wenn (n == NGX_AGAIN) { wenn (!rev->timer_set) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ngx_add_timer(rev, cscf->client_header_timeout); } wenn (ngx_handle_read_event(rev, 0) != NGX_OK) { ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); gib NGX_ERROR zurück; } gib NGX_AGAIN zurück; } // Wenn n 0 ist, bedeutet dies, dass der Client die Verbindung geschlossen hat, if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, „Client hat Verbindung vorzeitig geschlossen“); } // Wenn der Client die Verbindung schließt oder abnormal liest, recyceln Sie die aktuelle Anforderungsstruktur, wenn (n == 0 || n == NGX_ERROR) { c->Fehler = 1; c->log->action = "Client-Anforderungsheader lesen"; ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); gib NGX_ERROR zurück; } //Aktualisiere den aktuell gelesenen Datenzeiger r->header_in->last += n; Rückkehr n; } Das Lesen der Anforderungsheaderdaten gliedert sich hierbei im Wesentlichen in die folgenden Schritte:
3. Zusammenfassung In diesem Artikel wird hauptsächlich erläutert, wie nginx den Anforderungsheader liest und analysiert, und der Schwerpunkt liegt auf dem Hauptprozesscode zum Lesen von Daten und den detaillierten Schritten des Lesens. Dies ist das Ende dieses Artikels mit der detaillierten Erklärung des Nginx-Anforderungsheaderdaten-Lesevorgangs. Weitere relevante Inhalte zum Nginx-Anforderungsheaderdaten-Lesevorgang finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder durchsuchen Sie die folgenden verwandten Artikel weiter. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird! Das könnte Sie auch interessieren:
|
<<: Lebenszyklus und Ausführungsreihenfolge von React-Class-Komponenten
>>: Ausführliches Tutorial zur Installation von WinX64 unter MySQL8.0.18 (mit Bildern und Text)
Das Folgende ist mein Urteil basierend auf der Da...
Inhaltsverzeichnis Variable Datentypen Erweiterun...
Ich habe schon lange keinen Blog mehr geschrieben...
Logo-Optimierung: 1. Das Logobild sollte so klein...
Ein allgemeiner Vorschlag besteht darin, Indizes ...
MySQL Installer bietet eine benutzerfreundliche, ...
Nachteile von Tabellen 1. Tabellen nehmen mehr Byt...
Ein ES-Image vom Docker-Hub heruntergeladen, Vers...
Download von der offiziellen Website: https://www...
yum-Befehl Yum (vollständiger Name Yellow Dog Upd...
Die Web-Farbauswahlfunktion in diesem Beispiel ve...
In diesem Artikel wird der spezifische Code von J...
Mit der kontinuierlichen Entwicklung der Internetw...
Inhaltsverzeichnis 1. Proxy im LAN 2. Intranet-Pe...
Wenn Sie Magento häufig ändern, stoßen Sie möglich...