Reverse proxy that assumes Brotli compression - proxy

I need to create a reverse proxy that assumes Brotli compression as if the upstream provided Content-Encoding: br even despite the upstream provides no Content-Encoding header.
It is to proxy a server that serves Brotli-encoded files and has no Brotli support.

Related

How do I convey Keep-alive metadata when the HTTP/2 protocol is used?

I have an angular web application that uses Spring boot with an embedded tomcat server in the backend. I want to keep established http connections alive longer to improve the response time of subsequent http requests. With http/1.1 a browser is told to keep the http connection alive by adding Connection: Keep-Alive and something like Keep-Alive: timeout=5, max=1000 to the response header. However connection-specific header fields such as Connection and Keep-Alive are prohibited in HTTP/2. Because of that Chrome and Firefox ignore them in HTTP/2 responses. With HTTP/2, connection-specific metadata should be conveyed by other means.
I can't find anywhere what those 'other means' should be though. Nor can i find anywhere how to configure an embedded Tomcat 9 server to add Keep-alive meta data to a HTTP/2 response. This is how tomcat is configured right now:
#Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
return (tomcat) -> tomcat.addConnectorCustomizers((connector) -> {
if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) {
AbstractHttp11Protocol<?> protocolHandler = (AbstractHttp11Protocol<?>) connector
.getProtocolHandler();
protocolHandler.setDisableUploadTimeout(false);
protocolHandler.setConnectionUploadTimeout(5000);
protocolHandler.setKeepAliveTimeout(4000);
protocolHandler.setMaxKeepAliveRequests(200);
protocolHandler.setUseKeepAliveResponseHeader(true);
}
});
}
But these settings aren't going to work if i want to use HTTP/2. Any ideas?
With http/1.1 a browser is told to keep the http connection alive by adding Connection: Keep-Alive and something like Keep-Alive: timeout=5, max=1000 to the response header.
That’s not actually true. Since HTTP/1.1 the Connection: Keep-Alive header is defaulted to be the case unless explicitly set to Close. The fact we even have the header is more a left over from HTTP/1.0 days and shouldn’t need to be set. The response has always been more informative of what the server will do rather than an instruction to the client (“hey, FYI I’m going to be using these settings”) but it was always kind of meaningless too since server (and client) could drop the connection if it wanted too. If a server is running out of TCP connections it shouldn’t really keep and old one that is not being used alive rather than accept a new one, in general.
However connection-specific header fields such as Connection and Keep-Alive are prohibited in HTTP/2. Because of that Chrome and Firefox ignore them in HTTP/2 responses. With HTTP/2, connection-specific metadata should be conveyed by other means.
I can't find anywhere what those 'other means' should be though. Nor can i find anywhere how to configure an embedded Tomcat 9 server to add Keep-alive meta data to a HTTP/2 response. This is how tomcat is configured right now:
In the same way as previous, HTTP/2 just got rid of the rather pointless header and assumed you want to keep it alive. It also made less sense in HTTP/2 as it’s used for multiple requests and responses whereas HTTP/1.1 is only used for one at a time and keep-alive is a connection-level setting. So if an HTTP/2 request could specific a keep-alive: close what would that mean for other requests on that connection that are already in-flight? And similarly setting it to keep-alive is implied by the very nature of HTTP/2’s multiplexing.
It’s up to the client and server to decide when best to drop the connection, based on its own logic and resource constraints, though the HTTP/2 spec does go on to say this later:
HTTP/2 connections are persistent. For best performance, it is expected that clients will not close connections until it is determined that no further communication with a server is necessary (for example, when a user navigates away from a particular web page) or until the server closes the connection.

How do I make a HTTP2-only request over http:// in Go?

I'm using Go 1.6 and want to make a HTTP2-only request over http://.
Attempting to do this currently results in:
Head http://localhost:2076/completed/764c1b6bc55548707507a2dd25570483a7216bf4: http2: unsupported scheme
To force http2, I believe I need http.Client.Transport.TLSConfig.NextProtos set to []string{"h2"}.
What else is required?
You need to use https, not http. The http2 transport doesn't recognize the http scheme.
The HTTP/2.0 by default works on highly secured connections. It uses high quality ciphers. So it can only run on HTTPS connections. Moreover, to make HTTPS connections, you also need to have your SSL enabled and have the required certificates installed.

HTTP2: How to indicate support for it? Is there a "Alternate-Protocol" for HTTP2?

So I just upgraded to nginx 1.9.5 which supports HTTP2.
I replaced all listen spdy by listen http2, removed spdy_headers_comp directive and also removed add_header Alternate-Protocol 443:npn-spdy/3;
Then I opened my site in Firefox, opened network monitor, and voila: Version: HTTP/2.0
But how does Firefox know my site supports HTTP2? Does it always first try to connect via HTTP2 before trying HTTP1.1?
HTTP/2 sites are deployed over TLS.
Browsers use a TLS extension called ALPN to tell the server what protocols they can speak.
Browsers always send this TLS extension, and always include both HTTP/2 and HTTP/1.1 (and may also include the old SPDY protocol).
The server receives the list of protocols that browsers can speak, and if the server supports HTTP/2 (and if a number of other conditions are met - in particular regarding the TLS protocol version and the cipher suite), the server decides to speak HTTP/2 with the browser, and sends the chosen protocol back to the browser, again using the ALPN extension.
If the server does not support HTTP/2 then it will send to the browser that it can only speak HTTP/1.1 via the ALPN extension.
If the server does not support the ALPN extension, then it will not send it to the browser, and the browser will default to speak HTTP/1.1 to that server.

The difference between the X-Forwarded-For header and the Via header

I am developing a proxy and have been investigating the headers by looking at the W3 Guidelines. My proxy adds the incoming REMOTE-ADDR to the X-FORWARDED-FOR header but I'm not sure how this compares with the Via header. I've looked on the wikipedia page and this lists
Via: 1.0 fred, 1.1 example.com (Apache/1.1)
but I have not found any instructions as to how this should be built up.
They're both headers that indicate that content has passed through proxy, and it's fine to include both headers.
The Via header is for protocol version (so you know if connection has been downgraded at any point), hostname of proxy and optional product/version of the proxy (like User-Agent of the proxy). It's just for information/debugging or identifying and working around buggy proxies (e.g. if you wanted to use request pipelining you'd watch that space).
XFF is for forwarding original IP of the client to the server. If the server trusts the proxy (or chain of proxies) it can use it instead of connection's IP.

How will you design a proxy server that supports HTTP 1.1 keep-alive completely?

It seems even nginx only half supports HTTP 1.1 keep-alive requests:
It is an HTTP/1.0 proxy without the
ability for keep-alive requests yet.
(As a result, backend connections are
created and destroyed on every
request.) Nginx talks HTTP/1.1 to the
browser and HTTP/1.0 to the backend
server. As such it handles keep-alive
to the browser. (source)
Were it you,how would you implement this?
The hardest part I think is how to make the response the same order as requested in keep-alive mode.

Resources