{"id":13841078,"url":"https://github.com/posener/h2conn","last_synced_at":"2025-03-17T14:12:16.896Z","repository":{"id":55528154,"uuid":"140945788","full_name":"posener/h2conn","owner":"posener","description":"HTTP2 client-server full-duplex connection","archived":false,"fork":false,"pushed_at":"2023-12-04T02:54:07.000Z","size":62,"stargazers_count":134,"open_issues_count":3,"forks_count":22,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-26T01:21:06.290Z","etag":null,"topics":["go","golang","http2"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/posener.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-14T12:49:30.000Z","updated_at":"2025-02-13T08:06:23.000Z","dependencies_parsed_at":"2023-12-04T03:36:43.992Z","dependency_job_id":null,"html_url":"https://github.com/posener/h2conn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Fh2conn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Fh2conn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Fh2conn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/posener%2Fh2conn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/posener","download_url":"https://codeload.github.com/posener/h2conn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241960880,"owners_count":20049343,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","http2"],"created_at":"2024-08-04T17:01:02.410Z","updated_at":"2025-03-05T04:14:32.032Z","avatar_url":"https://github.com/posener.png","language":"Go","funding_links":[],"categories":["Go (531)","Go"],"sub_categories":[],"readme":"# h2conn\n\n`h2conn` provides HTTP2 client-server full-duplex communication connection.\n\n[![Build Status](https://travis-ci.org/posener/h2conn.svg?branch=master)](https://travis-ci.org/posener/h2conn)\n[![codecov](https://codecov.io/gh/posener/h2conn/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/h2conn)\n[![GoDoc](https://godoc.org/github.com/posener/h2conn?status.svg)](http://godoc.org/github.com/posener/h2conn)\n[![Go Report Card](https://goreportcard.com/badge/github.com/posener/h2conn)](https://goreportcard.com/report/github.com/posener/h2conn)\n\n## Motivation\n\nGo has a wonderful HTTP2 support that is integrated seamlessly into the HTTP1.1 implementation.\nThere is a nice demo on [https://http2.golang.org](https://http2.golang.org) in which you can see it in action.\nThe code for the demo is available [here](https://github.com/golang/net/tree/master/http2/h2demo).\n\nI became interested how HTTP2 can work with full-duplex communication, \nand saw the [echo handler implementation](https://github.com/golang/net/blob/a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1/http2/h2demo/h2demo.go#L136-L164),\nand a suggested client side implementation for this handler in this\n[Github issue](https://github.com/golang/go/issues/13444#issuecomment-161115822).\n\nThis library provides a simpler API for the same sort of \"advanced usage\" / \"low level\" / \"hard core\" implementation.\n\n## Examples\n\nCheck out the [example](https://github.com/posener/h2conn/tree/master/example) directory.\n\n### Server\n\nOn the server side, in an implementation of `http.Handler`, the `h2conn.Accept` function\ncan be used to get a full-duplex connection to the client.\n\n\n```go\ntype handler struct{}\n\nfunc (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {\n\tconn, err := h2conn.Accept(w, r)\n\tif err != nil {\n\t\tlog.Printf(\"Failed creating connection from %s: %s\", r.RemoteAddr, err)\n\t\thttp.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)\n\t\treturn\n\t}\n\tdefer conn.Close() \n\t\n\t// [ Use conn ... ]\n\t// The connection will be left open until this function will return.\n\t// If there is a need to wait to the client to close the connection,\n\t// we can wait on the request context: `\u003c-r.Context().Done()`.\n}\n```\n\n### Client\n\nOn the client side, the `h2conn.Connect` function can be used in order to connect to an HTTP2 server\nwith full-duplex communication.\n\n```go\nfunc main() {\n    conn, resp, err := h2conn.Connect(ctx, url, nil)\n\tif err != nil {\n\t\tlog.Fatalf(\"Initiate conn: %s\", err)\n\t}\n\tdefer conn.Close()\n\n\t// Check server status code\n\tif resp.StatusCode != http.StatusOK {\n\t\tlog.Fatalf(\"Bad status code: %d\", resp.StatusCode)\n\t}\n\n\t// [ Use conn ... ]\n}\n```\n\n### Using the Connection\n\nThe server and the client need to decide on message format.\nHere are few examples that demonstrate how the client and server can communicate over the created pipe.\n\n#### 1. JSON\n\nSending and receiving JSON format is a very common thing to do.\n\n```go\nimport \"encoding/json\"\n\nfunc main() {\n\t// [ Create a connection ... ]\n\t\n\t// Create an encoder and decoder from the connection\n\tvar in, out = json.NewDecoder(conn), json.NewEncoder(conn)\n\t\n\t// Sending data into the connection using the out encoder.\t\n\t// Any type can be sent - the important thing is that the other side will read with a\n\t// variable of the same type.\n\t// In this case, we just use a simple string.\n\terr = out.Encode(\"hello\")\n\t// [ handle err ... ]\n\t\n\t// Receiving data from the connection using the in decoder and a variable.\n\t// Any type can be received - the important thing is that the other side will write data\n\t// to the connection of the same type.\n\t// In this case we assume that the other side sent us a string.\n\tvar resp string\n\terr = in.Decode(\u0026resp)\t\n\t// [ handle err, use resp ... ]\n}\n```\n\n#### 2. GOB \n\nGOB is more efficient message format, but requires both client and server to be written in Go.\nThe example is exactly the same as in the json encoding, just switch `json` with `gob`.\n\n```go\nimport \"encoding/gob\"\n\nfunc main() {\n\t// [ Create a connection ... ]\n\t\n\tvar in, out = gob.NewDecoder(conn), gob.NewEncoder(conn)\n\t\n\t// Sending data into the connection using the out encoder.\t\n\t// Any type can be sent - the important thing is that the other side will read with a\n\t// variable of the same type.\n\t// In this case, we just use a simple string.\n\terr = out.Encode(\"hello\")\n\t// [ handle err ... ]\n\t\n\t// Receiving data from the connection using the in decoder and a variable.\n\t// Any type can be received - the important thing is that the other side will write data\n\t// to the connection of the same type.\n\t// In this case we assume that the other side sent us a string.\n\tvar resp string\n\terr = in.Decode(\u0026resp)\t\n\t// [ handle err, use resp ... ]\n}\n```\n\n#### 3. Constant Buffer Size\n\n```go\n// Create constant size buffer\nconst bufSize = 10\n\nfunc main () {\n\t// [ Create a connection ... ]\n\t\n\tbuf := make([]byte, bufSize)\n\n\t// Write to the connection:\n\t// [ Write something to buf... ]\n\t_, err = conn.Write(buf)\n\n\t// Read from the connection:\n\t_, err = conn.Read(buf)\n\t// [ Use buf... ]\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposener%2Fh2conn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fposener%2Fh2conn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fposener%2Fh2conn/lists"}