• Stars
    star
    129
  • Rank 279,262 (Top 6 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 6 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

HTTP2 client-server full-duplex connection

h2conn

h2conn provides HTTP2 client-server full-duplex communication connection.

Build Status codecov GoDoc Go Report Card

Motivation

Go has a wonderful HTTP2 support that is integrated seamlessly into the HTTP1.1 implementation. There is a nice demo on https://http2.golang.org in which you can see it in action. The code for the demo is available here.

I became interested how HTTP2 can work with full-duplex communication, and saw the echo handler implementation, and a suggested client side implementation for this handler in this Github issue.

This library provides a simpler API for the same sort of "advanced usage" / "low level" / "hard core" implementation.

Examples

Check out the example directory.

Server

On the server side, in an implementation of http.Handler, the h2conn.Accept function can be used to get a full-duplex connection to the client.

type handler struct{}

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	conn, err := h2conn.Accept(w, r)
	if err != nil {
		log.Printf("Failed creating connection from %s: %s", r.RemoteAddr, err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	defer conn.Close() 
	
	// [ Use conn ... ]
	// The connection will be left open until this function will return.
	// If there is a need to wait to the client to close the connection,
	// we can wait on the request context: `<-r.Context().Done()`.
}

Client

On the client side, the h2conn.Connect function can be used in order to connect to an HTTP2 server with full-duplex communication.

func main() {
    conn, resp, err := h2conn.Connect(ctx, url, nil)
	if err != nil {
		log.Fatalf("Initiate conn: %s", err)
	}
	defer conn.Close()

	// Check server status code
	if resp.StatusCode != http.StatusOK {
		log.Fatalf("Bad status code: %d", resp.StatusCode)
	}

	// [ Use conn ... ]
}

Using the Connection

The server and the client need to decide on message format. Here are few examples that demonstrate how the client and server can communicate over the created pipe.

1. JSON

Sending and receiving JSON format is a very common thing to do.

import "encoding/json"

func main() {
	// [ Create a connection ... ]
	
	// Create an encoder and decoder from the connection
	var in, out = json.NewDecoder(conn), json.NewEncoder(conn)
	
	// Sending data into the connection using the out encoder.	
	// Any type can be sent - the important thing is that the other side will read with a
	// variable of the same type.
	// In this case, we just use a simple string.
	err = out.Encode("hello")
	// [ handle err ... ]
	
	// Receiving data from the connection using the in decoder and a variable.
	// Any type can be received - the important thing is that the other side will write data
	// to the connection of the same type.
	// In this case we assume that the other side sent us a string.
	var resp string
	err = in.Decode(&resp)	
	// [ handle err, use resp ... ]
}

2. GOB

GOB is more efficient message format, but requires both client and server to be written in Go. The example is exactly the same as in the json encoding, just switch json with gob.

import "encoding/gob"

func main() {
	// [ Create a connection ... ]
	
	var in, out = gob.NewDecoder(conn), gob.NewEncoder(conn)
	
	// Sending data into the connection using the out encoder.	
	// Any type can be sent - the important thing is that the other side will read with a
	// variable of the same type.
	// In this case, we just use a simple string.
	err = out.Encode("hello")
	// [ handle err ... ]
	
	// Receiving data from the connection using the in decoder and a variable.
	// Any type can be received - the important thing is that the other side will write data
	// to the connection of the same type.
	// In this case we assume that the other side sent us a string.
	var resp string
	err = in.Decode(&resp)	
	// [ handle err, use resp ... ]
}

3. Constant Buffer Size

// Create constant size buffer
const bufSize = 10

func main () {
	// [ Create a connection ... ]
	
	buf := make([]byte, bufSize)

	// Write to the connection:
	// [ Write something to buf... ]
	_, err = conn.Write(buf)

	// Read from the connection:
	_, err = conn.Read(buf)
	// [ Use buf... ]
}

More Repositories

1

complete

bash completion written in go + bash completion for go command
Go
925
star
2

goreadme

Generate readme file from Go doc. Now available as a Github action!
Go
213
star
3

goaction

Write Github actions in Go
Go
210
star
4

gitfs

A complete solution for static files in Go code
Go
127
star
5

wstest

go websocket client for unit testing of a websocket handler
Go
101
star
6

sharedsecret

Implementation of Shamir's Secret Sharing algorithm.
Go
69
star
7

tarfs

An implementation of the FileSystem interface for tar files.
Go
58
star
8

cmd

The standard library flag package with its missing features
Go
41
star
9

ctxutil

utils for Go context
Go
25
star
10

client-timing

An HTTP client for go-server-timing middleware. Enables automatic timing propagation through HTTP calls between servers.
Go
24
star
11

order

More readable and easier ordering and comparison tasks
Go
21
star
12

mock-import

A helper mocking function to mask ImportErrors
Python
17
star
13

orm

Go Typed ORM
Go
16
star
14

context

A proof of concept implementation of scoped context
Go
16
star
15

h2demo

Code examples for blog post
Go
15
star
16

script

Easily write scripts with Go. Improvements for https://github.com/bitfield/script.
Go
14
star
17

fuzzing

Easy fuzzing with go-fuzz
Go
14
star
18

eztables

iptables in web browser
Go
11
star
19

fcontext

Go Context with (pseudo) constant access-time
Go
10
star
20

auth

Painless OAuth authentication middleware
Go
8
star
21

dont

A towel, is about the most massively useful thing an interstellar hitchhiker can have
Go
6
star
22

tiler

A Go port of https://github.com/nuno-faria/tiler.
Go
6
star
23

goaction-example

Simplest goaction example
Go
5
star
24

flag

Like the flag package, but with bash completion support!
Go
5
star
25

goreadme-server

Github App for goreadme package
Go
4
star
26

formatter

A library for formatting text - indenting and line wrapping
Go
3
star
27

wsbeam

WebSocket HTTP handler that can be used to beam (broadcast) data to all connections
Go
3
star
28

contexttest

Test package for context implementations
Go
3
star
29

chrome-github-godoc

Chrome extension that replaces Github view of git commit messages with useful godoc.org synopsis
JavaScript
3
star
30

tmplt

A small wrapper around Go templates for handling simple templates
Go
2
star
31

learn

Go
2
star
32

goaction-issues-example

Goaction example for using Github APIs
Go
2
star
33

meetups

An archive of my meetup lectures
Go
1
star
34

grpcgw

Convenience comes with grpc-ecosystem/grpc-gateway
Go
1
star
35

go

Go
1
star
36

fsutil

Go
1
star
37

state-logger

A logging tool to log on state changes
Go
1
star
38

ps1

A lightweight script that sets a nice shell prompt
Shell
1
star
39

githubapp

oauth2 Github app authentication client
Go
1
star
40

autogen

Automatically generate files
Go
1
star