-
Notifications
You must be signed in to change notification settings - Fork 7.4k
HTTP/2 to upstream #771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
HTTP/2 to upstream #771
Conversation
5dedbca
to
cc47b74
Compare
Hi @arut, |
66338f9
to
63a769c
Compare
We must avoid sending the |
8e79530
to
a1c2cd9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @hongzhidao just some minor things I noticed...
HTTP/2: ngx_http_v2_proxy_module.
The module allows to use HTTP/2 protocol for proxying.
HTTP/2 proxying is enabled by specifying "proxy_http_version 2.0".
...
Blank line between the subject and body...
...
diff --git a/src/http/v2/ngx_http_v2_proxy_module.c b/src/http/v2/ngx_http_v2_proxy_module.c
new file mode 100644
index 0000000000..a69ffcc406
--- /dev/null
+++ b/src/http/v2/ngx_http_v2_proxy_module.c
...
+ngx_int_t
+ngx_http_v2_proxy_handler(ngx_http_request_t *r)
+{
...
+#if (NGX_HTTP_SSL)
+ u->ssl = plcf->ssl;
+
+ if (u->ssl) {
+ ngx_str_set(&u->schema, "https://");
+
+ } else {
+ ngx_str_set(&u->schema, "https://");
+ }
+#else
+ ngx_str_set(&u->schema, "https://");
+#endif
Maybe I'm not understanding what the checks for 'ssl' here are for but in
the non-ssl cases shouldn't the schema be 'http://' ? (Otherwise all the
checks seem redundant as we set 'https://' regardless...)
...
+static ngx_int_t
+ngx_http_v2_proxy_body_output_filter(void *data, ngx_chain_t *in)
+{
...
+ /*
+ * We have already got the response and were sending some additional
s/were/we're/
+ * control frames. Even if there is still something unsent, stop
+ * here anyway.
+ */
...
ngx_http_v2_proxy_parse_frame(ngx_http_request_t *r,
+ ngx_http_v2_proxy_ctx_t *ctx, ngx_buf_t *b)
+{
...
+ /* suppress warning */
+ case ngx_http_v2_proxy_st_payload:
+ case ngx_http_v2_proxy_st_padding:
+ break;
You could just use 'default:' here. Of course you won't get warned if you add
more enum values and don't handle them, but maybe you aren't planning on
adding any more or it's not a concern...
+ }
...
+static ngx_int_t
+ngx_http_v2_proxy_parse_header(ngx_http_request_t *r,
+ ngx_http_v2_proxy_ctx_t *ctx, ngx_buf_t *b)
+{
...
+ if (state < sw_fragment) {
+
+ if (b->last - b->pos < (ssize_t) ctx->rest) {
Or even (ptrdiff_t) to be more explicit about _why_ we're casting...
+ last = b->last;
...
+ if (state == sw_padding) {
+
+ if (b->last - b->pos < (ssize_t) ctx->rest) {
... and here ... and likely a few other places...
+ ctx->rest -= b->last - b->pos;
...
Hi @ac000,
I feel it should be touched again, I'm looking into @arut implementation about the proxy http3.
|
|
c32eeeb
to
731645c
Compare
Hi @arut, take a look plz, did you mean something like this?
|
731645c
to
6498c2c
Compare
Good to learn, I added it into the proxy refactoring patch. |
#if (NGX_HTTP_V2) | ||
|
||
if (plcf->http_version == NGX_HTTP_VERSION_20) { | ||
|
||
if (u.family != AF_UNIX) { | ||
|
||
if (u.no_port) { | ||
plcf->host = u.host; | ||
|
||
} else { | ||
plcf->host.len = u.host.len + 1 + u.port_text.len; | ||
plcf->host.data = u.host.data; | ||
} | ||
|
||
} else { | ||
ngx_str_set(&plcf->host, "localhost"); | ||
} | ||
} | ||
|
||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code is almost identical to what we have in ngx_http_proxy_set_vars()
. We can use host from ctx->host_header
. In fact, it's used by default if using HTTP/1 headers ngx_http_proxy_headers
/ ngx_http_proxy_cache_headers
instead of grpc-specific ngx_http_grpc_headers
, which you are already using.
These header sets are not fully compatible though. For example, the following header is empty in HTTP/1:
{ ngx_string("TE"), ngx_string("$grpc_internal_trailers") },
We may think about adding something similar to ng_http_proxy_module
, but do it natively, NOT under HTTP/2 ifdef. I think this deserves a separate patch. And I'm not sure if we want client trailers to be sent by default to upstream. Anyway, this looks like a separate feature we can think about later.
4ca718e
to
87fb0ef
Compare
87fb0ef
to
682c9ee
Compare
I suggest skipping the paragraph about sibling location, those details don't matter here. |
The refactoring patch has no |
Also, |
This commit is prepared for HTTP/2 and HTTP/3 support. The ALPN protocol is now set per-connection in ngx_http_upstream_ssl_init_connection(), allowing proper protocol negotiation for each individual upstream connection regardless of SSL context sharing.
682c9ee
to
0c3897b
Compare
4e0dd9b
to
6694c01
Compare
@@ -3877,3 +4386,4 @@ ngx_http_v2_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc) | |||
"finalize proxy http2 request"); | |||
return; | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trailing empty line here.
@hongzhidao the grpc module has two specific configuration values
Regarding the first one, there's a directive The second one is needed for unbuffered bidirectional grpc proxying and probably needs to be enabled only in this case.A possible solution is a new proxy directive like |
Upon closer inspection, it seems like at least part of |
The module allows to use HTTP/2 protocol for proxying. HTTP/2 proxying is enabled by specifying "proxy_http_version 2.0". Example: server { listen 8000; location / { proxy_http_version 2.0; proxy_pass https://127.0.0.1:8443; } } server { listen 8443 ssl; http2 on; ssl_certificate certs/example.com.crt; ssl_certificate_key certs/example.com.key; location / { return 200 foo; } }
6694c01
to
bb2679d
Compare
@hongzhidao, a few points regarding testing.
|
@@ -2155,6 +2169,501 @@ ngx_http_v2_proxy_non_buffered_filter(void *data, ssize_t bytes) | |||
} | |||
|
|||
|
|||
static ngx_int_t | |||
ngx_http_v2_proxy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function resembles its unbuffered counterpart ngx_http_v2_proxy_non_buffered_filter()
, which it of course should. However, the amount of code copied is too large. I suggest moving the common code which handles HTTP/2 internals to a separate function and only leave buffer-related code outside. I'm pretty sure this will make the code much more readable.
u->process_header = ngx_http_v2_proxy_process_header; | ||
u->abort_request = ngx_http_v2_proxy_abort_request; | ||
u->finalize_request = ngx_http_v2_proxy_finalize_request; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a part that's missing in this module compared to ngx_http_proxy_module
:
+ if (plcf->redirects) {
+ u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
+ }
+
+ if (plcf->cookie_domains || plcf->cookie_paths || plcf->cookie_flags) {
+ u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
+ }
+
Also, this line is missing as well:
+ u->accel = 1;
TODO:
buffering
cache