📄 ngx_http_proxy_module.c
字号:
ngx_http_upstream_t *u; enum { sw_start = 0, sw_H, sw_HT, sw_HTT, sw_HTTP, sw_first_major_digit, sw_major_digit, sw_first_minor_digit, sw_minor_digit, sw_status, sw_space_after_status, sw_status_text, sw_almost_done } state; u = r->upstream; state = r->state; for (pos = u->buffer.pos; pos < u->buffer.last; pos++) { ch = *pos; switch (state) { /* "HTTP/" */ case sw_start: switch (ch) { case 'H': state = sw_H; break; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; case sw_H: switch (ch) { case 'T': state = sw_HT; break; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; case sw_HT: switch (ch) { case 'T': state = sw_HTT; break; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; case sw_HTT: switch (ch) { case 'P': state = sw_HTTP; break; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; case sw_HTTP: switch (ch) { case '/': state = sw_first_major_digit; break; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; /* the first digit of major HTTP version */ case sw_first_major_digit: if (ch < '1' || ch > '9') { return NGX_HTTP_PROXY_PARSE_NO_HEADER; } state = sw_major_digit; break; /* the major HTTP version or dot */ case sw_major_digit: if (ch == '.') { state = sw_first_minor_digit; break; } if (ch < '0' || ch > '9') { return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; /* the first digit of minor HTTP version */ case sw_first_minor_digit: if (ch < '0' || ch > '9') { return NGX_HTTP_PROXY_PARSE_NO_HEADER; } state = sw_minor_digit; break; /* the minor HTTP version or the end of the request line */ case sw_minor_digit: if (ch == ' ') { state = sw_status; break; } if (ch < '0' || ch > '9') { return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; /* HTTP status code */ case sw_status: if (ch == ' ') { break; } if (ch < '0' || ch > '9') { return NGX_HTTP_PROXY_PARSE_NO_HEADER; } p->status = p->status * 10 + ch - '0'; if (++p->status_count == 3) { state = sw_space_after_status; p->status_start = pos - 2; } break; /* space or end of line */ case sw_space_after_status: switch (ch) { case ' ': state = sw_status_text; break; case '.': /* IIS may send 403.1, 403.2, etc */ state = sw_status_text; break; case CR: state = sw_almost_done; break; case LF: goto done; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } break; /* any text until end of line */ case sw_status_text: switch (ch) { case CR: state = sw_almost_done; break; case LF: goto done; } break; /* end of status line */ case sw_almost_done: p->status_end = pos - 1; switch (ch) { case LF: goto done; default: return NGX_HTTP_PROXY_PARSE_NO_HEADER; } } } u->buffer.pos = pos; r->state = state; return NGX_AGAIN;done: u->buffer.pos = pos + 1; if (p->status_end == NULL) { p->status_end = pos; } r->state = sw_start; return NGX_OK;}static ngx_int_tngx_http_proxy_process_header(ngx_http_request_t *r){ ngx_int_t rc; ngx_uint_t i; ngx_table_elt_t *h; ngx_http_upstream_header_t *hh; ngx_http_upstream_main_conf_t *umcf; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); for ( ;; ) { rc = ngx_http_parse_header_line(r, &r->upstream->buffer); if (rc == NGX_OK) { /* a header line has been parsed successfully */ h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = r->header_hash; h->key.len = r->header_name_end - r->header_name_start; h->value.len = r->header_end - r->header_start; h->key.data = ngx_palloc(r->pool, h->key.len + 1 + h->value.len + 1 + h->key.len); if (h->key.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->value.data = h->key.data + h->key.len + 1; h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1; ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); if (h->key.len == r->lowcase_index) { ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len); } else { for (i = 0; i < h->key.len; i++) { h->lowcase_key[i] = ngx_tolower(h->key.data[i]); } } hh = ngx_hash_find(&umcf->headers_in_hash, h->hash, h->lowcase_key, h->key.len); if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http proxy header: \"%V: %V\"", &h->key, &h->value); continue; } if (rc == NGX_HTTP_PARSE_HEADER_DONE) { /* a whole header has been parsed successfully */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http proxy header done"); /* * if no "Server" and "Date" in header line, * then add the special empty headers */ if (r->upstream->headers_in.server == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r'); h->key.len = sizeof("Server") - 1; h->key.data = (u_char *) "Server"; h->value.len = 0; h->value.data = NULL; h->lowcase_key = (u_char *) "server"; } if (r->upstream->headers_in.date == NULL) { h = ngx_list_push(&r->upstream->headers_in.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e'); h->key.len = sizeof("Date") - 1; h->key.data = (u_char *) "Date"; h->value.len = 0; h->value.data = NULL; h->lowcase_key = (u_char *) "date"; } return NGX_OK; } if (rc == NGX_AGAIN) { return NGX_AGAIN; } /* there was error while a header line parsing */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "upstream sent invalid header"); return NGX_HTTP_UPSTREAM_INVALID_HEADER; }}static voidngx_http_proxy_abort_request(ngx_http_request_t *r){ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "abort http proxy request"); return;}static voidngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc){ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "finalize http proxy request"); return;}static ngx_int_tngx_http_proxy_host_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data){ ngx_http_proxy_loc_conf_t *plcf; plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); v->len = plcf->host_header.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = plcf->host_header.data; return NGX_OK;}static ngx_int_tngx_http_proxy_port_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data){ ngx_http_proxy_loc_conf_t *plcf; plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module); v->len = plcf->port.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = plcf->port.data; return NGX_OK;}static ngx_int_tngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data){ u_char *p; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; if (r->headers_in.x_forwarded_for == NULL) { v->len = r->connection->addr_text.len; v->data = r->connection->addr_text.data; return NGX_OK; } v->len = r->headers_in.x_forwarded_for->value.len + sizeof(", ") - 1 + r->connection->addr_text.len; p = ngx_palloc(r->pool, v->len); if (p == NULL) { return NGX_ERROR; } v->data = p; p = ngx_copy(p, r->headers_in.x_forwarded_for->value.data, r->headers_in.x_forwarded_for->value.len); *p++ = ','; *p++ = ' '; ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len); return NGX_OK;}static ngx_int_tngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data){ ngx_http_proxy_ctx_t *p; p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); if (p == NULL) { v->not_found = 1; return NGX_OK; } v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = ngx_palloc(r->connection->pool, NGX_SIZE_T_LEN); if (v->data == NULL) { return NGX_ERROR; } v->len = ngx_sprintf(v->data, "%uz", p->internal_body_length) - v->data; return NGX_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -