Running a Server

When a client establishes a new WebTransport session it:

  1. First establishes an HTTP/3 connection to the server.
  2. It sends an HTTP request (using the Extended CONNECT protocol) to the server, requesting to establish a WebTransport session.

Accepting a WebTransport Session

To start a WebTransport server, it is necessary to:

  1. Set up an HTTP/3 server.
  2. Set up an HTTP handler for the WebTransport Extended CONNECT request.

The webtransport.Server wraps an http3.Server. For more details on how to set up and configure an HTTP/3 server, see Serving HTTP/3.

Assume a server is running on This code starts an HTTP/3 server on (UDP) port 443. The server can handle regular HTTP/3 requests to

To accept the Extended CONNECT request, the application needs to define an HTTP handler. In this example, we want to accept WebTransport sessions at It is possible to reject an upgrade request by sending a non-2xx status code. Inside the handler, calling webtransport.Server.Upgrade accepts the WebTransport session, and it returns a webtransport.Session.

s := webtransport.Server{
    H3: http3.Server{
      Addr: ":443",
      TLSConfig: &tls.Config{}, // use your tls.Config here

// Create a new HTTP endpoint /webtransport.
http.HandleFunc("/webtransport", func(w http.ResponseWriter, r *http.Request) {
    sess, err := s.Upgrade(w, r)
    if err != nil {
        log.Printf("upgrading failed: %s", err)
    // Handle the session. Here goes the application logic. 

s.ListenAndServeTLS(<certFile>, <keyFile>)

Origin Validation

By default, the Upgrade function checks that the client’s request origin matches the host of the server. This prevents cross-site request forgery (CSRF) attacks, where an attacker could use a malicious web page to establish a WebTransport connection to a vulnerable application, with the application processing the connection as if it were part of the victim user’s session.

Applications can change this default behavior by setting the webtransport.Server.CheckOrigin callback:

s := webtransport.Server{
    H3: http3.Server{Addr: ":443"},
    CheckOrigin: func(r *http.Request) bool {
      // custom validation logic

📝 Future Work

  • Subprotocol Negotiation: #132
  • Properly check Validity of the client’s SETTINGS: #106