All Projects → thrawn01 → h2c-golang-example

thrawn01 / h2c-golang-example

Licence: other
Example HTTP/2 Cleartext (H2C) server and client in golang

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to h2c-golang-example

Reactnativetemplate
Our example of simple application using ReactNative and some recommendations
Stars: ✭ 127 (+56.79%)
Mutual labels:  example-project
Play Java Starter Example
Play starter project in Java (ideal for new users!)
Stars: ✭ 164 (+102.47%)
Mutual labels:  example-project
Play Scala Websocket Example
Example Play Scala application showing WebSocket use with Akka actors
Stars: ✭ 194 (+139.51%)
Mutual labels:  example-project
Angular9 Example App
Angular 13 Example App + Angular CLI + i18n + GraphQL
Stars: ✭ 1,769 (+2083.95%)
Mutual labels:  example-project
Pyqt5 Qtquick2 Example
A sample of QtQuick 2 providing material and fluent design themes in PyQt5.
Stars: ✭ 159 (+96.3%)
Mutual labels:  example-project
Owin Webapi Service
✅ OWIN / WebAPI windows service example. Includes attribute based routing sample
Stars: ✭ 175 (+116.05%)
Mutual labels:  example-project
Angular5 Example Shopping App
Angular 5 Example Shopping App + Angular Material + Responsive
Stars: ✭ 120 (+48.15%)
Mutual labels:  example-project
Wordpress Plugin Boilerplate Tutorial
Tutorials and Examples for WordPress Plugin Boilerplate, a foundation for WordPress Plugin Development.
Stars: ✭ 232 (+186.42%)
Mutual labels:  example-project
Clean Architecture Swiftui
SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.
Stars: ✭ 2,925 (+3511.11%)
Mutual labels:  example-project
Cppandroidiosexample
An application example using the same C++ code on both an Android project and an iPhone project.
Stars: ✭ 191 (+135.8%)
Mutual labels:  example-project
Android Base Mvp
Android Base MVP Concept with RXJava, Dagger, Event Bus, Retrofit, Glide, OkHTTP
Stars: ✭ 141 (+74.07%)
Mutual labels:  example-project
Play Scala Isolated Slick Example
Example Play Slick Project
Stars: ✭ 155 (+91.36%)
Mutual labels:  example-project
Ueberauth example
Example Phoenix application using Überauth for authentication
Stars: ✭ 180 (+122.22%)
Mutual labels:  example-project
Android Clean Architecture Mvvm Dagger Rx
Implemented by Clean Architecture, Dagger2, MVVM, LiveData, RX, Retrofit2, Room, Anko
Stars: ✭ 138 (+70.37%)
Mutual labels:  example-project
Rxjava3 Android Examples
RxJava 3 Android Examples - Migration From RxJava 2 to RxJava 3 - How to use RxJava 3 in Android
Stars: ✭ 213 (+162.96%)
Mutual labels:  example-project
Vlingo Examples
The VLINGO/PLATFORM examples demonstrating features and functionality available in the reactive components.
Stars: ✭ 121 (+49.38%)
Mutual labels:  example-project
Express Graphql Example
Example project how to use Express and GraphQL
Stars: ✭ 163 (+101.23%)
Mutual labels:  example-project
Play Scala Starter Example
Play Scala Starter Template (ideal for new users!)
Stars: ✭ 238 (+193.83%)
Mutual labels:  example-project
Transport Eta
Twitch streamed 🎥playground repo, README speaks to you.
Stars: ✭ 223 (+175.31%)
Mutual labels:  example-project
Arenagame
A Unity First Person Shooter game made with Forge networking as an example project.
Stars: ✭ 190 (+134.57%)
Mutual labels:  example-project

HTTP/2 Cleartext (H2C) golang example

Since the internet failed me, and the only workable example of a H2C client I can find was in the actual go code test suite I'm going to lay out what I discovered about H2C support in golang here.

First is that the standard golang code supports HTTP2 but does not directly support H2C. H2C support only exists in the golang.org/x/net/http2/h2c package. You can make your HTTP server H2C capable by wrapping your handler or mux with h2c.NewHandler() like so.

h2s := &http2.Server{}

handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil)
})

server := &http.Server{
    Addr:    "0.0.0.0:1010",
    Handler: h2c.NewHandler(handler, h2s),
}

fmt.Printf("Listening [0.0.0.0:1010]...\n")
checkErr(server.ListenAndServe(), "while listening")

The above code allows the server to support H2C upgrade and H2C prior knowledge along with standard HTTP/2 and HTTP/1.1 that golang natively supports.

If you don't care about supporting HTTP/1.1 then you can run this code which only supports H2C prior knowledge.

server := http2.Server{}

l, err := net.Listen("tcp", "0.0.0.0:1010")
checkErr(err, "while listening")

fmt.Printf("Listening [0.0.0.0:1010]...\n")
for {
    conn, err := l.Accept()
    checkErr(err, "during accept")

    server.ServeConn(conn, &http2.ServeConnOpts{
        Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            fmt.Fprintf(w, "Hello, %v, http: %v", r.URL.Path, r.TLS == nil)
        }),
    })
}

Once you have a running server you can test your server by installing curl-openssl.

$ brew install curl-openssl

# Add curl-openssl to the front of your path
$ export PATH="/usr/local/opt/curl-openssl/bin:$PATH"

You can now use curl to test your H2C enabled server like so.

Connect via HTTP1.1 then upgrade to HTTP/2 (H2C)
curl -v --http2 http://localhost:1010
*   Trying ::1:1010...
* TCP_NODELAY set
* Connected to localhost (::1) port 1010 (#0)
> GET / HTTP/1.1
> Host: localhost:1010
> User-Agent: curl/7.65.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAARAAAAAAAIAAAAA
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 101 Switching Protocols
< Connection: Upgrade
< Upgrade: h2c
* Received 101
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< content-type: text/plain; charset=utf-8
< content-length: 20
< date: Wed, 05 Jun 2019 19:01:40 GMT
<
* Connection #0 to host localhost left intact
Hello, /, http: true
Connect via HTTP/2 (H2C)
curl -v --http2-prior-knowledge http://localhost:1010
*   Trying ::1:1010...
* TCP_NODELAY set
* Connected to localhost (::1) port 1010 (#0)
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x7fdab8007000)
> GET / HTTP/2
> Host: localhost:1010
> User-Agent: curl/7.65.0
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 250)!
< HTTP/2 200
< content-type: text/plain; charset=utf-8
< content-length: 20
< date: Wed, 05 Jun 2019 19:00:43 GMT
<
* Connection #0 to host localhost left intact
Hello, /, http: true

Now, Remember when I said that the golang standard library does not support H2C? While that is technically correct there is a workaround to get the golang standard http2 client to connect to an H2C enabled server.

To do so you have to override DialTLS and set the super secret AllowHTTP flag.

client := http.Client{
    Transport: &http2.Transport{
        // So http2.Transport doesn't complain the URL scheme isn't 'https'
        AllowHTTP: true,
        // Pretend we are dialing a TLS endpoint. (Note, we ignore the passed tls.Config)
        DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
            return net.Dial(network, addr)
        },
    },
}

resp, _ := client.Get(url)
fmt.Printf("Client Proto: %d\n", resp.ProtoMajor)

Although this all looks a little wonky it actually works really well and performs nicely in production environments.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].