{"id":15372983,"url":"https://github.com/rs/xhandler","last_synced_at":"2025-04-04T21:11:08.549Z","repository":{"id":57479682,"uuid":"44234775","full_name":"rs/xhandler","owner":"rs","description":"XHandler is a bridge between net/context and http.Handler","archived":false,"fork":false,"pushed_at":"2017-07-07T05:25:32.000Z","size":85,"stargazers_count":230,"open_issues_count":0,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-28T20:11:43.583Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rs.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}},"created_at":"2015-10-14T08:37:24.000Z","updated_at":"2025-03-04T10:39:50.000Z","dependencies_parsed_at":"2022-09-20T00:05:54.588Z","dependency_job_id":null,"html_url":"https://github.com/rs/xhandler","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rs%2Fxhandler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rs%2Fxhandler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rs%2Fxhandler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rs%2Fxhandler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rs","download_url":"https://codeload.github.com/rs/xhandler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247249532,"owners_count":20908212,"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":[],"created_at":"2024-10-01T13:53:52.388Z","updated_at":"2025-04-04T21:11:08.530Z","avatar_url":"https://github.com/rs.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# XHandler\n\n[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/xhandler) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/xhandler/master/LICENSE) [![Build Status](https://travis-ci.org/rs/xhandler.svg?branch=master)](https://travis-ci.org/rs/xhandler) [![Coverage](http://gocover.io/_badge/github.com/rs/xhandler)](http://gocover.io/github.com/rs/xhandler)\n\nXHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`.\n\nIt lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router.\n\nThanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.\n\nYou may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler.\n\nRead more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/).\n\n## Installing\n\n    go get -u github.com/rs/xhandler\n\n## Usage\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/rs/cors\"\n\t\"github.com/rs/xhandler\"\n\t\"golang.org/x/net/context\"\n)\n\ntype myMiddleware struct {\n\tnext xhandler.HandlerC\n}\n\nfunc (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {\n\tctx = context.WithValue(ctx, \"test\", \"World\")\n\th.next.ServeHTTPC(ctx, w, r)\n}\n\nfunc main() {\n\tc := xhandler.Chain{}\n\n\t// Add close notifier handler so context is cancelled when the client closes\n\t// the connection\n\tc.UseC(xhandler.CloseHandler)\n\n\t// Add timeout handler\n\tc.UseC(xhandler.TimeoutHandler(2 * time.Second))\n\n\t// Middleware putting something in the context\n\tc.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {\n\t\treturn myMiddleware{next: next}\n\t})\n\n\t// Mix it with a non-context-aware middleware handler\n\tc.Use(cors.Default().Handler)\n\n\t// Final handler (using handlerFuncC), reading from the context\n\txh := xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {\n\t\tvalue := ctx.Value(\"test\").(string)\n\t\tw.Write([]byte(\"Hello \" + value))\n\t})\n\n\t// Bridge context aware handlers with http.Handler using xhandler.Handle()\n\thttp.Handle(\"/test\", c.Handler(xh))\n\n\tif err := http.ListenAndServe(\":8080\", nil); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\n\n### Using xmux\n\nXhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter):\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"net/http\"\n\t\"time\"\n\n\t\"github.com/rs/xhandler\"\n\t\"github.com/rs/xmux\"\n\t\"golang.org/x/net/context\"\n)\n\nfunc main() {\n\tc := xhandler.Chain{}\n\n\t// Append a context-aware middleware handler\n\tc.UseC(xhandler.CloseHandler)\n\n\t// Another context-aware middleware handler\n\tc.UseC(xhandler.TimeoutHandler(2 * time.Second))\n\n\tmux := xmux.New()\n\n\t// Use c.Handler to terminate the chain with your final handler\n\tmux.GET(\"/welcome/:name\", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {\n\t\tfmt.Fprintf(w, \"Welcome %s!\", xmux.Params(ctx).Get(\"name\"))\n\t}))\n\n\tif err := http.ListenAndServe(\":8080\", c.Handler(mux)); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n```\n\nSee [xmux](https://github.com/rs/xmux) for more examples.\n\n## Context Aware Middleware\n\nHere is a list of `net/context` aware middleware handlers implementing `xhandler.HandlerC` interface.\n\nFeel free to put up a PR linking your middleware if you have built one:\n\n| Middleware | Author | Description |\n| ---------- | ------ | ----------- |\n| [xmux](https://github.com/rs/xmux) | [Olivier Poitrey](https://github.com/rs) | HTTP request muxer |\n| [xlog](https://github.com/rs/xlog) | [Olivier Poitrey](https://github.com/rs) | HTTP handler logger |\n| [xstats](https://github.com/rs/xstats) | [Olivier Poitrey](https://github.com/rs) | A generic client for service instrumentation |\n| [xaccess](https://github.com/rs/xaccess) | [Olivier Poitrey](https://github.com/rs) | HTTP handler access logger with [xlog](https://github.com/rs/xlog) and [xstats](https://github.com/rs/xstats) |\n| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support |\n\n## Licenses\n\nAll source code is licensed under the [MIT License](https://raw.github.com/rs/xhandler/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frs%2Fxhandler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frs%2Fxhandler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frs%2Fxhandler/lists"}