Hi, This patch adds support for proxying Docker's "hijacked" HTTP connections. It shares most logic with websocket's "upgrade" mechanism.
Basically, it detects the 'application/vnd.docker.raw-stream" Content-Type header and marks the connection for upgrade in this case. I also hit a strange behavior with the chunked transfer terminating sequence "0\r\n\r\n" being sent even on this upgraded connection hence the "u->headers_in.chunked = 0;" in "ngx_http_upstream_upgrade". Feedback appreciated. Regards, PS: I failed to register to this mailing list with jt AT yadutaf DOT fr, any idea why ? -- Jean-Tiare
# HG changeset patch # User Jean-Tiare LE BIGOT <j...@yadutaf.fr> # Date 1416064918 -3600 # Sat Nov 15 16:21:58 2014 +0100 # Node ID dd18ab1abb2c0bc55bcbdad04b7d35b98ce15651 # Parent 7d7eac6e31df1d962a644f8093c1fbb8f91620ce RFC: upgrade connection for proxied docker streams Docker 'hijacks' its HTTP connection to raw TCP when streaming a console. It advertises such connections by setting "Content-Type" header to "application/vnd.docker.raw-stream" in the response. Currenttly, Nginx has no special handling and interprets it as a chunked response, which breaks the docker client. A possible approach is to upgrade the connection when this header is detected and force off chunked transfer. diff -r 7d7eac6e31df -r dd18ab1abb2c src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Tue Nov 04 19:56:23 2014 +0900 +++ b/src/http/ngx_http_upstream.c Sat Nov 15 16:21:58 2014 +0100 @@ -89,6 +89,8 @@ ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_content_length(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_process_content_type(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_process_set_cookie(ngx_http_request_t *r, @@ -175,7 +177,7 @@ ngx_http_upstream_copy_header_line, 0, 0 }, { ngx_string("Content-Type"), - ngx_http_upstream_process_header_line, + ngx_http_upstream_process_content_type, offsetof(ngx_http_upstream_headers_in_t, content_type), ngx_http_upstream_copy_content_type, 0, 1 }, @@ -2716,6 +2718,7 @@ u->write_event_handler = ngx_http_upstream_upgraded_write_upstream; r->read_event_handler = ngx_http_upstream_upgraded_read_downstream; r->write_event_handler = ngx_http_upstream_upgraded_write_downstream; + u->headers_in.chunked = 0; if (clcf->tcp_nodelay) { tcp_nodelay = 1; @@ -3849,6 +3852,25 @@ static ngx_int_t +ngx_http_upstream_process_content_type(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ngx_int_t ret = ngx_http_upstream_process_header_line(r, h, offset); + if (ret != NGX_OK) { + return ret; + } + + // is docker header ? + if (ngx_strstrn(h->value.data, + "application/vnd.docker.raw-stream", 34 - 1) != NULL) { + r->upstream->upgrade = 1; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_upstream_process_last_modified(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) {
_______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel