{"action":"created","comment":{"url":"https://api.github.com/repos/opentable/sous/pulls/comments/78265622","id":78265622,"diff_hunk":"@@ -0,0 +1,126 @@\n+package server\n+\n+import (\n+\t\"encoding/json\"\n+\t\"log\"\n+\t\"net/http\"\n+\t\"runtime/debug\"\n+\n+\t\"github.com/julienschmidt/httprouter\"\n+\t\"github.com/opentable/sous/graph\"\n+\t\"github.com/opentable/sous/lib\"\n+\t\"github.com/pkg/errors\"\n+)\n+\n+type (\n+\t// A Exchanger has an Exchange method - which is presumed to write to an\n+\t// injected ResponseWriter\n+\tExchanger interface {\n+\t\tExchange() (interface{}, int)\n+\t}\n+\n+\t// A PanicHandler processes panics into 500s\n+\tPanicHandler struct {\n+\t\t*sous.LogSet\n+\t\t*ResponseWriter\n+\t}\n+\n+\t// ResponseWriter wraps the the http.ResponseWriter interface\n+\t// XXX This is a workaround for Psyringe\n+\tResponseWriter struct {\n+\t\thttp.ResponseWriter\n+\t}\n+\n+\t// An ExchangeFactory builds an Exchanger -\n+\t// they're used to configure the RouteMap\n+\tExchangeFactory func() Exchanger\n+\n+\trouteEntry struct {\n+\t\tName     string\n+\t\tMethods  []string\n+\t\tPath     string\n+\t\tExchange ExchangeFactory\n+\t}\n+\n+\t// RouteMap is a list of entries for routing\n+\tRouteMap []routeEntry\n+)\n+\n+var (\n+\tdefaultMethods = []string{\"GET\", \"POST\", \"PUT\", \"DELETE\"}\n+\n+\t// SousRouteMap is the configuration of route for the application\n+\tSousRouteMap = RouteMap{\n+\t\t{\"gdm\", []string{\"GET\"}, \"/gdm\", NewGDMHandler},\n+\t}\n+)\n+\n+// BuildRouter builds a returns an http.Handler based on some constant configuration\n+func BuildRouter(rm RouteMap, grf func() *graph.SousGraph) http.Handler {\n+\tr := httprouter.New()\n+\n+\tfor _, e := range rm {\n+\t\tfor _, m := range e.Methods {\n+\t\t\tr.Handle(m, e.Path, Handling(grf, e.Exchange))\n+\t\t}\n+\t}\n+\n+\treturn r\n+}\n+\n+// PathFor constructs a URL which should route back to the named route, with\n+// supplied parameters\n+func (rm *RouteMap) PathFor(name string, params map[string]string) (string, error) {\n+\tfor _, e := range *rm {\n+\t\tif e.Name == name {\n+\t\t\t// TODO actually handle params\n+\t\t\treturn e.Path, nil\n+\t\t}\n+\t}\n+\treturn \"\", errors.Errorf(\"No route found for name %q\", name)\n+}\n+\n+func panicsAreFiveHundred(w http.ResponseWriter) {\n+\tif r := recover(); r != nil {\n+\t\tlog.Print(\"paFH\")\n+\t\tlog.Print(r)\n+\t\tw.WriteHeader(http.StatusInternalServerError)\n+\t}\n+}\n+\n+// Handle recovers from panics, returns a 500 and logs the error\n+func (ph *PanicHandler) Handle() {\n+\tif r := recover(); r != nil {\n+\t\tph.ResponseWriter.WriteHeader(http.StatusInternalServerError)\n+\t\tph.LogSet.Warn.Printf(\"%+v\", r)\n+\t\tph.LogSet.Warn.Print(string(debug.Stack()))\n+\t\tph.LogSet.Warn.Print(\"Recovered, returned 500\")\n+\t\t// XXX in a dev mode, print the panic in the response body\n+\t\t// (normal ops it might leak secure data)\n+\t}\n+}\n+\n+// Handling (sometimes) updates the local copy of the GDM and formats it\n+func Handling(graphFac func() *graph.SousGraph, factory ExchangeFactory) httprouter.Handle {\n+\treturn func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {\n+\t\tdefer panicsAreFiveHundred(w)\n+\n+\t\tg := graphFac()\n+\t\tg.Add(&ResponseWriter{ResponseWriter: w}, r, p)\n+\n+\t\tph := &PanicHandler{}\n+\t\tg.Inject(ph)\n+\t\tdefer ph.Handle()\n+\n+\t\th := factory()\n+\t\tg.Inject(h)\n+\n+\t\tdata, status := h.Exchange()","path":"server/router.go","position":118,"original_position":118,"commit_id":"204ca722c23b8406f5ad10b5cb6a1c1d03af4d6e","original_commit_id":"204ca722c23b8406f5ad10b5cb6a1c1d03af4d6e","user":{"login":"nyarly","id":127548,"avatar_url":"https://avatars.githubusercontent.com/u/127548?v=3","gravatar_id":"","url":"https://api.github.com/users/nyarly","html_url":"https://github.com/nyarly","followers_url":"https://api.github.com/users/nyarly/followers","following_url":"https://api.github.com/users/nyarly/following{/other_user}","gists_url":"https://api.github.com/users/nyarly/gists{/gist_id}","starred_url":"https://api.github.com/users/nyarly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nyarly/subscriptions","organizations_url":"https://api.github.com/users/nyarly/orgs","repos_url":"https://api.github.com/users/nyarly/repos","events_url":"https://api.github.com/users/nyarly/events{/privacy}","received_events_url":"https://api.github.com/users/nyarly/received_events","type":"User","site_admin":false},"body":"The actual injected handler for the route returns data and status code.","created_at":"2016-09-10T00:09:37Z","updated_at":"2016-09-10T00:09:37Z","html_url":"https://github.com/opentable/sous/pull/157#discussion_r78265622","pull_request_url":"https://api.github.com/repos/opentable/sous/pulls/157","_links":{"self":{"href":"https://api.github.com/repos/opentable/sous/pulls/comments/78265622"},"html":{"href":"https://github.com/opentable/sous/pull/157#discussion_r78265622"},"pull_request":{"href":"https://api.github.com/repos/opentable/sous/pulls/157"}}},"pull_request":{"url":"https://api.github.com/repos/opentable/sous/pulls/157","id":84736493,"html_url":"https://github.com/opentable/sous/pull/157","diff_url":"https://github.com/opentable/sous/pull/157.diff","patch_url":"https://github.com/opentable/sous/pull/157.patch","issue_url":"https://api.github.com/repos/opentable/sous/issues/157","number":157,"state":"open","locked":false,"title":"Baseline server, with first endpoint: a GDM lister TECHOPS-53","user":{"login":"nyarly","id":127548,"avatar_url":"https://avatars.githubusercontent.com/u/127548?v=3","gravatar_id":"","url":"https://api.github.com/users/nyarly","html_url":"https://github.com/nyarly","followers_url":"https://api.github.com/users/nyarly/followers","following_url":"https://api.github.com/users/nyarly/following{/other_user}","gists_url":"https://api.github.com/users/nyarly/gists{/gist_id}","starred_url":"https://api.github.com/users/nyarly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nyarly/subscriptions","organizations_url":"https://api.github.com/users/nyarly/orgs","repos_url":"https://api.github.com/users/nyarly/repos","events_url":"https://api.github.com/users/nyarly/events{/privacy}","received_events_url":"https://api.github.com/users/nyarly/received_events","type":"User","site_admin":false},"body":"Line comments by way of tour","created_at":"2016-09-10T00:03:59Z","updated_at":"2016-09-10T00:09:37Z","closed_at":null,"merged_at":null,"merge_commit_sha":"edb86f5782274b270f843c0f4f31fcdf7d9c4ff2","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/opentable/sous/pulls/157/commits","review_comments_url":"https://api.github.com/repos/opentable/sous/pulls/157/comments","review_comment_url":"https://api.github.com/repos/opentable/sous/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opentable/sous/issues/157/comments","statuses_url":"https://api.github.com/repos/opentable/sous/statuses/204ca722c23b8406f5ad10b5cb6a1c1d03af4d6e","head":{"label":"nyarly:server_manifest_pull","ref":"server_manifest_pull","sha":"204ca722c23b8406f5ad10b5cb6a1c1d03af4d6e","user":{"login":"nyarly","id":127548,"avatar_url":"https://avatars.githubusercontent.com/u/127548?v=3","gravatar_id":"","url":"https://api.github.com/users/nyarly","html_url":"https://github.com/nyarly","followers_url":"https://api.github.com/users/nyarly/followers","following_url":"https://api.github.com/users/nyarly/following{/other_user}","gists_url":"https://api.github.com/users/nyarly/gists{/gist_id}","starred_url":"https://api.github.com/users/nyarly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nyarly/subscriptions","organizations_url":"https://api.github.com/users/nyarly/orgs","repos_url":"https://api.github.com/users/nyarly/repos","events_url":"https://api.github.com/users/nyarly/events{/privacy}","received_events_url":"https://api.github.com/users/nyarly/received_events","type":"User","site_admin":false},"repo":{"id":55056531,"name":"sous","full_name":"nyarly/sous","owner":{"login":"nyarly","id":127548,"avatar_url":"https://avatars.githubusercontent.com/u/127548?v=3","gravatar_id":"","url":"https://api.github.com/users/nyarly","html_url":"https://github.com/nyarly","followers_url":"https://api.github.com/users/nyarly/followers","following_url":"https://api.github.com/users/nyarly/following{/other_user}","gists_url":"https://api.github.com/users/nyarly/gists{/gist_id}","starred_url":"https://api.github.com/users/nyarly/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nyarly/subscriptions","organizations_url":"https://api.github.com/users/nyarly/orgs","repos_url":"https://api.github.com/users/nyarly/repos","events_url":"https://api.github.com/users/nyarly/events{/privacy}","received_events_url":"https://api.github.com/users/nyarly/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nyarly/sous","description":"Tools for building, testing, deploying Docker containers","fork":true,"url":"https://api.github.com/repos/nyarly/sous","forks_url":"https://api.github.com/repos/nyarly/sous/forks","keys_url":"https://api.github.com/repos/nyarly/sous/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nyarly/sous/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nyarly/sous/teams","hooks_url":"https://api.github.com/repos/nyarly/sous/hooks","issue_events_url":"https://api.github.com/repos/nyarly/sous/issues/events{/number}","events_url":"https://api.github.com/repos/nyarly/sous/events","assignees_url":"https://api.github.com/repos/nyarly/sous/assignees{/user}","branches_url":"https://api.github.com/repos/nyarly/sous/branches{/branch}","tags_url":"https://api.github.com/repos/nyarly/sous/tags","blobs_url":"https://api.github.com/repos/nyarly/sous/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nyarly/sous/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nyarly/sous/git/refs{/sha}","trees_url":"https://api.github.com/repos/nyarly/sous/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nyarly/sous/statuses/{sha}","languages_url":"https://api.github.com/repos/nyarly/sous/languages","stargazers_url":"https://api.github.com/repos/nyarly/sous/stargazers","contributors_url":"https://api.github.com/repos/nyarly/sous/contributors","subscribers_url":"https://api.github.com/repos/nyarly/sous/subscribers","subscription_url":"https://api.github.com/repos/nyarly/sous/subscription","commits_url":"https://api.github.com/repos/nyarly/sous/commits{/sha}","git_commits_url":"https://api.github.com/repos/nyarly/sous/git/commits{/sha}","comments_url":"https://api.github.com/repos/nyarly/sous/comments{/number}","issue_comment_url":"https://api.github.com/repos/nyarly/sous/issues/comments{/number}","contents_url":"https://api.github.com/repos/nyarly/sous/contents/{+path}","compare_url":"https://api.github.com/repos/nyarly/sous/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nyarly/sous/merges","archive_url":"https://api.github.com/repos/nyarly/sous/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nyarly/sous/downloads","issues_url":"https://api.github.com/repos/nyarly/sous/issues{/number}","pulls_url":"https://api.github.com/repos/nyarly/sous/pulls{/number}","milestones_url":"https://api.github.com/repos/nyarly/sous/milestones{/number}","notifications_url":"https://api.github.com/repos/nyarly/sous/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nyarly/sous/labels{/name}","releases_url":"https://api.github.com/repos/nyarly/sous/releases{/id}","deployments_url":"https://api.github.com/repos/nyarly/sous/deployments","created_at":"2016-03-30T11:09:49Z","updated_at":"2016-03-30T11:09:50Z","pushed_at":"2016-09-10T00:03:07Z","git_url":"git://github.com/nyarly/sous.git","ssh_url":"git@github.com:nyarly/sous.git","clone_url":"https://github.com/nyarly/sous.git","svn_url":"https://github.com/nyarly/sous","homepage":"","size":9357,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"opentable:master","ref":"master","sha":"f207a8fce97887c1bf749591747e6b35f17adb41","user":{"login":"opentable","id":2653541,"avatar_url":"https://avatars.githubusercontent.com/u/2653541?v=3","gravatar_id":"","url":"https://api.github.com/users/opentable","html_url":"https://github.com/opentable","followers_url":"https://api.github.com/users/opentable/followers","following_url":"https://api.github.com/users/opentable/following{/other_user}","gists_url":"https://api.github.com/users/opentable/gists{/gist_id}","starred_url":"https://api.github.com/users/opentable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opentable/subscriptions","organizations_url":"https://api.github.com/users/opentable/orgs","repos_url":"https://api.github.com/users/opentable/repos","events_url":"https://api.github.com/users/opentable/events{/privacy}","received_events_url":"https://api.github.com/users/opentable/received_events","type":"Organization","site_admin":false},"repo":{"id":43084873,"name":"sous","full_name":"opentable/sous","owner":{"login":"opentable","id":2653541,"avatar_url":"https://avatars.githubusercontent.com/u/2653541?v=3","gravatar_id":"","url":"https://api.github.com/users/opentable","html_url":"https://github.com/opentable","followers_url":"https://api.github.com/users/opentable/followers","following_url":"https://api.github.com/users/opentable/following{/other_user}","gists_url":"https://api.github.com/users/opentable/gists{/gist_id}","starred_url":"https://api.github.com/users/opentable/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opentable/subscriptions","organizations_url":"https://api.github.com/users/opentable/orgs","repos_url":"https://api.github.com/users/opentable/repos","events_url":"https://api.github.com/users/opentable/events{/privacy}","received_events_url":"https://api.github.com/users/opentable/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opentable/sous","description":"Tools for building, testing, deploying Docker containers","fork":false,"url":"https://api.github.com/repos/opentable/sous","forks_url":"https://api.github.com/repos/opentable/sous/forks","keys_url":"https://api.github.com/repos/opentable/sous/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opentable/sous/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opentable/sous/teams","hooks_url":"https://api.github.com/repos/opentable/sous/hooks","issue_events_url":"https://api.github.com/repos/opentable/sous/issues/events{/number}","events_url":"https://api.github.com/repos/opentable/sous/events","assignees_url":"https://api.github.com/repos/opentable/sous/assignees{/user}","branches_url":"https://api.github.com/repos/opentable/sous/branches{/branch}","tags_url":"https://api.github.com/repos/opentable/sous/tags","blobs_url":"https://api.github.com/repos/opentable/sous/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opentable/sous/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opentable/sous/git/refs{/sha}","trees_url":"https://api.github.com/repos/opentable/sous/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opentable/sous/statuses/{sha}","languages_url":"https://api.github.com/repos/opentable/sous/languages","stargazers_url":"https://api.github.com/repos/opentable/sous/stargazers","contributors_url":"https://api.github.com/repos/opentable/sous/contributors","subscribers_url":"https://api.github.com/repos/opentable/sous/subscribers","subscription_url":"https://api.github.com/repos/opentable/sous/subscription","commits_url":"https://api.github.com/repos/opentable/sous/commits{/sha}","git_commits_url":"https://api.github.com/repos/opentable/sous/git/commits{/sha}","comments_url":"https://api.github.com/repos/opentable/sous/comments{/number}","issue_comment_url":"https://api.github.com/repos/opentable/sous/issues/comments{/number}","contents_url":"https://api.github.com/repos/opentable/sous/contents/{+path}","compare_url":"https://api.github.com/repos/opentable/sous/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opentable/sous/merges","archive_url":"https://api.github.com/repos/opentable/sous/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opentable/sous/downloads","issues_url":"https://api.github.com/repos/opentable/sous/issues{/number}","pulls_url":"https://api.github.com/repos/opentable/sous/pulls{/number}","milestones_url":"https://api.github.com/repos/opentable/sous/milestones{/number}","notifications_url":"https://api.github.com/repos/opentable/sous/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opentable/sous/labels{/name}","releases_url":"https://api.github.com/repos/opentable/sous/releases{/id}","deployments_url":"https://api.github.com/repos/opentable/sous/deployments","created_at":"2015-09-24T18:22:46Z","updated_at":"2016-08-23T21:09:16Z","pushed_at":"2016-09-10T00:03:59Z","git_url":"git://github.com/opentable/sous.git","ssh_url":"git@github.com:opentable/sous.git","clone_url":"https://github.com/opentable/sous.git","svn_url":"https://github.com/opentable/sous","homepage":"","size":9367,"stargazers_count":17,"watchers_count":17,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":1,"forks":7,"open_issues":1,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opentable/sous/pulls/157"},"html":{"href":"https://github.com/opentable/sous/pull/157"},"issue":{"href":"https://api.github.com/repos/opentable/sous/issues/157"},"comments":{"href":"https://api.github.com/repos/opentable/sous/issues/157/comments"},"review_comments":{"href":"https://api.github.com/repos/opentable/sous/pulls/157/comments"},"review_comment":{"href":"https://api.github.com/repos/opentable/sous/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opentable/sous/pulls/157/commits"},"statuses":{"href":"https://api.github.com/repos/opentable/sous/statuses/204ca722c23b8406f5ad10b5cb6a1c1d03af4d6e"}}}}
{"actor":{"display_login":"nyarly"}}