HTTP/2 on SAP BTP, Cloud Foundry runtime
SAP BTP, Cloud Foundry runtime now supports HTTP/2 🎉. This feature is available for everyone who has deployed an app to the platform. In this blog post we will cover what you need to know before using HTTP/2 and how you can enable it for you application.
What is HTTP/2
HTTP/2 is the next major version of the HTTP protocol. The connection handling and request handling have been completely reworked and are incompatible with HTTP/1. However, this allows many major improvements to make the best use of modern internet connections and optimise resource usage. Websites often load many different resources and make lots of API calls which sometimes block each other. With HTTP/2 these issues have been partially addressed to allow for much better performance.
The more small resources are loaded and the more long-running API calls an application has, the more it will benefit from using HTTP/2.
These are the most notable changes:
With HTTP/1 most browsers make a maximum of six parallel connections to a server. This is done to avoid a single, slow request blocking all other requests (head of line blocking). If the application makes more than six requests at any given time some requests will have to wait for others to complete. Most of the time there is no proper control over the order in which requests are executed which can lead to resources that are not needed immediately blocking other more important files that are required to display an initial loading page to the user.
HTTP/2 solves this issue by multiplexing requests over a single connection. This saves resources on client and server side without blocking requests. Clients will send all request immediately and the server will answer them as soon as the response is ready. This also allows prioritising requests and decide which resources need to be presented first.
Instead of sending the same headers over and over again, as it is the case with HTTP/1, HTTP/2 re-uses previously sent headers. Client and server keep track of the headers that were already sent/received and only headers that have changed (compared to the previous request) will be sent again. This is one of many steps to reduce the size of each request and therefore utilise the available bandwidth as efficiently as possible.
In order to achieve these new functionalities, HTTP/2 had to move away from the text based approach. HTTP/2 now consists of individual frames that make up a full message (request/response). These frames are sent as binary data and therefore cannot be read by a human which can complicate debugging (however, that was already the case with compression in HTTP/1). The frames are organised into streams, each of which can carry one or more messages. The streams can also be prioritised to make sure more important resources are served first.
Due to the incompatibility with HTTP/1, the client and server need to negotiate a protocol before they send data which is usually done during the TLS handshake. During the handshake, the client and server can offer their available versions using Application-Layer Protocol Negotiation (ALPN) which is an extension to TLS.
Since there can also be traffic that does not use TLS but still wants to benefit from HTTP/2 there are two kinds of HTTP/2. HTTP/2 over TLS (also referred to as
h2) and HTTP/2 over cleartext (also referred to as
h2c uses different mechanisms to negotiate the protocol, one is described in section “From the platform to your apps” below.
On top of this new protocol a modern remote procedure calling (RPC) framework has been built: gRPC (gRPC Remote Procedure Calls). It was designed to work in distributed systems with low latency and independent of the underlying programming language (Java, Go, Ruby, …) or the content type of the request (JSON, XML, protobuf, …). By default, it’s using protobuf as the content type which, together with the protoc compiler, allows the developer to generate server and client code in multiple languages from a single definition. You can read more about it on the projects’ website. In order to achieve its goals gRPC utilises HTTP/2 which was built to carry multiple independent streams over a single connection and keep each connection alive as long as possible.
How to enable it on SAP BTP, Cloud Foundry runtime
Before we explain how to enable HTTP/2 for your application please note that currently we do NOT support web sockets over HTTP/2. The HTTP/2 specification includes support for web sockets but due to constraints on internal components of the routing stack we cannot support web sockets on HTTP/2 as of now. However, this might change in the future.
Requests coming into the platform
To benefit from the performance improvements HTTP/2 has over HTTP/1 for requests coming into the platform, for example from browsers, you need to use the Custom Domain Service. This service allows you to use your own domain for apps running on the platform and configure how clients can connect to your custom domain. As well as allowing you to configure custom TLS options, there is a simple checkbox to enable HTTP/2 for requests to your custom domain.
To learn how to set up the Custom Domain Service, please refer to this SAP Help Portal article: Custom Domain Manager – Initial Setup. After the domain is set up you can configure HTTP/2 support by specifying a TLS Configuration as explained in Custom Domain Manager – Manage TLS Configuration. The HTTP/2 option is part of the TLS configuration because the protocol is negotiated during the TLS handshake (as explained above).
When this is enabled, requests to the platform will now use HTTP/2 if the client supports it but requests from the platform to your application will still use HTTP/1. This way you can benefit from performance improvements of HTTP/2 when your users make requests from their browsers without having to re-architect your applications to support HTTP/2.
From the platform to your apps
If you want to use the more advanced features of HTTP/2 such as gRPC or server push, you need to enable HTTP/2 on the application side as well. A major benefit of Cloud Foundry is that TLS termination is handled for you and you don’t need to worry about implementing TLS in your application. As the platform manages encryption for you when you enable HTTP/2 for requests from the platform to your apps, requests are sent unencrypted (just like with HTTP/1). This plaintext version of HTTP/2 is known as
h2c and less popular than versions of HTTP/2 involving TLS, however there is still support for
h2c in most programming languages (see Sample Apps below).
Enabling HTTP/2 for a Cloud Foundry app is fairly easy. You either specify it as part of the manifest:
--- ... routes: - route: example.com protocol: http2
Or you can specify it in the
# Requires CF CLI version 8 or higher cf map-route MY-APP EXAMPLE.COM --hostname EXAMPLE --destination-protocol http2
Please note that the app will receive only
h2c traffic from this route and is expected to be able to handle such traffic. Specifically, the platform will send requests using the “h2c with prior knowledge” as specified in RFC-7540 section 3.4. It will first send the client connection preface which informs the application that from now on traffic will be
h2c. The preface looks like this (newlines are
PRI * HTTP/2.0 SM
The main goal was to make the preface compatible with HTTP/1 servers but use a series of characters that is unlikely to appear in real HTTP/1 communication. This allows a server to handle both (HTTP/1 and HTTP/2) by having a special handler for this HTTP/1 message which starts
h2c communication. After the client connection preface the server is expected to send the server connection preface which consists of a SETTINGS frame. More details on this topic can be found in RFC-7540 section 3.4. Most of the time this handling will be done as part of the server implementation that you are using.
If the route supports HTTP/2 end-to-end (e.g. with custom domain and app side
h2c) you will be able to use the more advanced features of HTTP/2 like gRPC or server push. The routing stack is able to dynamically switch internally to truly support HTTP/2 end-to-end.
Sample apps for
For the most popular programming languages we have set up a repository that contains samples on how to use HTTP/2 and it’s features. Use at your own risk:
We are working on enabling HTTP/2 by default for requests coming into the platform using the default domain (e.g.
some-app.cfapps.<ls>.hana.ondemand.com). This will not affect traffic from the platform to your applications since this would break many applications. We will post an update to the community after we rolled it out.
Hi Maximilian Moehl,
thanks for the informative blog.
As I can see every request against the cFLP will be responsed by http2. Our custom UI5-applications deployed at BTP/HTML5 Application repository response with http1.1.
That means the odataservices from onpremise via destination and UI5-files will be responsed by http 1.1.
Is there a possibility to activate http2 for mta-bundled UI5-only applications, which communicates with OnPremise destinations? Or is the http2 only for CAP-service routes?
Hi M.P. N. ,
you can also use http2 for your custom UI5 applications. The custom domain part is independent of the kind of application/service that you are deploying. As long as you can assign a custom route to that application/service you should also be able to configure http2 for that route/domain. Please refer to the Custom Domain Service for more information about this.
If you also want http2 between the load balancers and you application you need to talk to the people that deploy/maintain that application/service. If you deploy the application using cf push you can check out our example repository to see how this can be achieved in e.g. nodeJS. If you are using a service to deploy the application you have to check the services documentation or reach out to the service owners and ask if http2 is supported.
However, for the most use cases the approach using custom domains should yield the performance bonus http2 has and I don't think UI5 is taking advantage of the additional benefits http2 has.
do you have any information when the Managed Application Router (Approuter) which comes with the Launchpad service will support H2?
It is not likely that approuter will support http2 in the short term. Approuter uses Connect npm and currently nodejs does not support http2 server with Connect (or Express). spdy module works, but unfortunately it is not maintained anymore (it is recommended to use native nodejs support)
Currently there is no clear path forward to move to http2 in approuter. Approuter uses Connect npm (analog to Express) and this is not supported by nodejs native http2 server functionality.
We also tried with spdy ,it works but it is not maintained anymore.
I've did some more research on the http2 support for the connect NPM module and found:
connect will support http2 ? #1097
As the answer was "it is supported" I went ahead and gave it a try. Based on the cf-routing-samples repository I've created a fork and a branch where I've added the approuter:
As you can see I've needed two small adjustments. One for @sap/approuter and another for the compression package.
Hope that helps to get H2 support to the approuter. But did I understand it right that basically it wouldn't be needed as the platform would speak H2 to the client and HTTP1.1 to the approuter? But maybe H2 support for the approuter would reduce also the load on the platform.
Thank you for checking.
I'm quite sure that I tested this too. I can just see this commit. It uses secure server which is not correct as approuter gets http from go_router. I remember that it only worked with spdy, but I will check again.
In any case this flow will be enabled via env. variable to prevent regressions from not interested people.
I commented on your PR to further discuss the state of HTTP/2 in the app-router. If there is any progress on the feature we will provide an update in this thread.
Great Blog Maximilian!
Does the SAP BTP Cloud Connector support http/2? What requirements are necessary for this?
There are actually 2 parts for which Cloud Connector could support HTTP/2:
In neither of them support of HTTP/2 is available at the moment, hence, there are no special requirements I could name
as promised, here is the update: HTTP/2 has recently been enabled for the default domains (*.cfapps.<landscape> and *.cf.<landscape>). If your client supports HTTP/2, it will upgrade from HTTP/1 automatically. Custom Domain configurations were not changed.
thank you for the update. I've directly tried in our launchpad.cfapps.eu10.hana.ondemand.com. Unfortunately I still see all requests hitting the managed aprouter using HTTP 1.1. Anything that needs to be done there?
the change we made applies to apps that have their route directly below the cf and cfapps domain, e.g. test.cfapps.eu10.hana.ondemand.com. The launchpad service has its own subdomain which happens to be below the cfapps domain, e.g. test.launchpad.cfapps.eu10.hana.ondemand.com. The launchpad subdomain has its own configuration that does not enable HTTP/2. The domain is managed by the launchpad service team, please reach out to them if you would like to have HTTP/2 enabled for their subdomain.
thank you for your quick response. I've filed the incident 700821 / 2022 asking about for H2 Support in the Launchpad Service.
any update/news on websocket support for http/2? That'd be the missing piece to really get speed into the stack 🙂
sorry for the late reply. The issues is not with us but rather with GoLang which is the programming language our router is written in. You can track cloudfoundry/gorouter#230 and golang/go#32763 for this issue but it seems unlikely that there will be changes anytime soon.
Just for your information, server push in HTTP/2 is deprecated and the feature has been removed from Chrome. See: https://developer.chrome.com/blog/removing-push/.
Before you proceed with the configuration, it's important to check if your website is using HTTP/2. Google Chrome provides several options to verify this. One quick and easy way is to check if HTTP/2 is supported on your SSL-enabled site.
To do this, open your website in the Google Chrome browser and navigate to the developer tools. Click on the "network" tab and select "all" by the filters. Then scroll down and choose "protocol" to create a new protocol column. This will allow you to see which aspects of your site are using H2 versus another protocol.
Alternatively, you can use online tools like https://http2.pro/ or https://tools.keycdn.com/http2-test to check your website's HTTP/2 configuration. These tools will provide additional information on supported features and any issues or errors.
This will not affect traffic from the platform to your applications since this would break many applications.
I have not enabled HTTP2_SUPPORT in xs-app.json for my @sap/approuter, yet the application is now processing requests over h2 (and breaking things).