{"action":"created","comment":{"url":"https://api.github.com/repos/wikimedia/restbase/pulls/comments/43365688","id":43365688,"diff_hunk":"@@ -449,6 +442,168 @@ templates:\n             - get_from_backend:\n                 request:\n                   uri: https://wikimedia.org/api/rest_v1/metrics/pageviews/top/{+rest}\n+      /{module:graphoid}/v1/store/{format}:\n+        post:\n+          x-setup-handler:\n+            - init:\n+                uri: /{domain}/sys/post_data/graphoid.request\n+            - init:\n+                uri: /{domain}/sys/key_value/graphoid.png\n+                body:\n+                  keyType: string\n+                  valueType: blob\n+            - init:\n+                uri: /{domain}/sys/key_value/graphoid.svg\n+                body:\n+                  keyType: string\n+                  valueType: blob\n+          x-request-handler:\n+            - calculate_hash:\n+                request:\n+                  method: put\n+                  uri: /{domain}/sys/post_data/graphoid.request/hash\n+                  body: '{$.request.body}'\n+            - check_storage:\n+                request:\n+                  method: get\n+                  uri: /{domain}/sys/key_value/graphoid.{format}/{$.calculate_hash.body}\n+                  headers:\n+                    cache-control: '{cache-control}'\n+                return_if:\n+                  status: '2xx'\n+                return:\n+                  status: 200\n+                  headers: '{$.check_storage.headers}'\n+                  body: '{$.check_storage.body}'\n+                catch:\n+                  status: 404\n+            - load_data:\n+                request:\n+                  method: post\n+                  uri: /{domain}/sys/graphoid/v1/handler/{format}\n+                  headers:\n+                    cache-control: '{cache-control}'\n+                    x-resource-location: '{$.calculate_hash.body}'\n+                  body: '{$.request.body}'\n+            - store_request:\n+                request:\n+                  method: put\n+                  uri: /{domain}/sys/post_data/graphoid.request/\n+                  body: '{$.request.body}'\n+            - return_content:\n+                return:\n+                  status: 200\n+                  headers: '{$.load_data.headers}'\n+                  body: '{$.load_data.body}'\n+      /{module:graphoid}/v1/preview/{format}:\n+        post:\n+          x-request-handler:\n+            - calculate_hash:\n+                request:\n+                  method: put\n+                  uri: /{domain}/sys/post_data/graphoid.request/hash\n+                  body: '{$$.merge($.request.body, {\"x-restbase-mode\": \"preview\"})}'\n+            - handle_req:\n+                request:\n+                  method: post\n+                  uri: /{domain}/sys/graphoid/v1/handler/{$.request.params.format}\n+                  headers:\n+                    x-resource-location: '{$.calculate_hash.body}'\n+                    content-type: application/json\n+                  body: '{$.request.body}'\n+      /{module:graphoid}/v1/request/json/{hash}:\n+        get:\n+          x-request-handler:\n+            - check_request_storage:\n+                request:\n+                  method: get\n+                  uri: /{domain}/sys/post_data/graphoid.request/{hash}\n+                return:\n+                  status: 200\n+                  headers:\n+                    content-type: application/json\n+                  body: '{$.check_request_storage.body}'\n+      /{module:graphoid}/v1/request/{format}/{hash}:\n+        get:\n+          x-request-handler:\n+            - check_storage:\n+                request:\n+                  method: get\n+                  uri: /{domain}/sys/key_value/graphoid.{$.request.params.format}/{hash}\n+                  headers:\n+                    cache-control: '{cache-control}'\n+                return_if:\n+                  status: '2xx'\n+                return:\n+                  status: 200\n+                  headers: '{$.check_storage.headers}'\n+                  body: '{$.check_storage.body}'\n+                catch:\n+                  status: 404\n+            - load_request:\n+                request:\n+                  uri: /{domain}/sys/post_data/graphoid.request/{hash}\n+            - handle_req:\n+                request:\n+                  method: post\n+                  uri: /{domain}/sys/graphoid/v1/handler/{format}\n+                  headers:\n+                    cache-control: '{cache-control}'\n+                    x-resource-location: '{$.request.params.hash}'\n+                    content-type: application/json\n+                  body: '{$.load_request.body}'\n+      /{module:graphoid}/v1/service_request:\n+        post:\n+          x-request-handler:\n+            - png:\n+                request:\n+                  method: post\n+                  uri: http://graphoid-beta.wmflabs.org/www.mediawiki.org/v2/png\n+                  headers:\n+                    content-type: 'application/json'\n+                  body: '{$.request.body}'\n+              svg:\n+                request:\n+                  method: post\n+                  uri: http://graphoid-beta.wmflabs.org/www.mediawiki.org/v2/svg\n+                  headers:\n+                    content-type: 'application/json'\n+                  body: '{$.request.body}'\n+            - return_result:\n+                return:\n+                  status: 200\n+                  body:\n+                    png:\n+                      headers: '{$.png.headers}'\n+                      body: '{$.png.body}'\n+                    svg:\n+                      headers: '{$.svg.headers}'\n+                      body: '{$.svg.body}'\n+      /{module:graphoid}/v1/handler/{format}:\n+        post:\n+          x-request-handler:\n+            - graphoid:\n+                request:\n+                  method: post\n+                  uri: /{domain}/sys/graphoid/v1/service_request\n+                  body: '{$.request.body}'\n+            - store_png:\n+                request:\n+                  method: put\n+                  uri: /{domain}/sys/key_value/graphoid.png/{$.request.headers.x-resource-location}\n+                  headers: '{$$.merge($.graphoid.body.png.headers, {\"x-resource-location\": $.request.headers.x-resource-location})}'\n+                  body: '{$.graphoid.body.png.body}'\n+              store_svg:\n+                request:\n+                  method: put\n+                  uri: /{domain}/sys/key_value/graphoid.svg/{$.request.headers.x-resource-location}\n+                  headers: '{$$.merge($.graphoid.body.svg.headers, {\"x-resource-location\": $.request.headers.x-resource-location})}'\n+                  body: '{$.graphoid.body.svg.body}'\n+            - return_result:\n+                return:\n+                  status: 200\n+                  headers: '{$$.merge($.graphoid.body[$.request.params.format].headers, {\"x-resource-location\": $.request.headers.x-resource-location})}'","path":"config.example.wikimedia.yaml","position":204,"original_position":204,"commit_id":"4f60f632958a44a2ad26f90c59486f1e6806d933","original_commit_id":"4f60f632958a44a2ad26f90c59486f1e6806d933","user":{"login":"d00rman","id":10210173,"avatar_url":"https://avatars.githubusercontent.com/u/10210173?v=3","gravatar_id":"","url":"https://api.github.com/users/d00rman","html_url":"https://github.com/d00rman","followers_url":"https://api.github.com/users/d00rman/followers","following_url":"https://api.github.com/users/d00rman/following{/other_user}","gists_url":"https://api.github.com/users/d00rman/gists{/gist_id}","starred_url":"https://api.github.com/users/d00rman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/d00rman/subscriptions","organizations_url":"https://api.github.com/users/d00rman/orgs","repos_url":"https://api.github.com/users/d00rman/repos","events_url":"https://api.github.com/users/d00rman/events{/privacy}","received_events_url":"https://api.github.com/users/d00rman/received_events","type":"User","site_admin":false},"body":"Idem","created_at":"2015-10-29T09:49:25Z","updated_at":"2015-10-29T09:49:25Z","html_url":"https://github.com/wikimedia/restbase/pull/388#discussion_r43365688","pull_request_url":"https://api.github.com/repos/wikimedia/restbase/pulls/388","_links":{"self":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/comments/43365688"},"html":{"href":"https://github.com/wikimedia/restbase/pull/388#discussion_r43365688"},"pull_request":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/388"}}},"pull_request":{"url":"https://api.github.com/repos/wikimedia/restbase/pulls/388","id":48794649,"html_url":"https://github.com/wikimedia/restbase/pull/388","diff_url":"https://github.com/wikimedia/restbase/pull/388.diff","patch_url":"https://github.com/wikimedia/restbase/pull/388.patch","issue_url":"https://api.github.com/repos/wikimedia/restbase/issues/388","number":388,"state":"open","locked":false,"title":"Added graphoid endpoints","user":{"login":"Pchelolo","id":814754,"avatar_url":"https://avatars.githubusercontent.com/u/814754?v=3","gravatar_id":"","url":"https://api.github.com/users/Pchelolo","html_url":"https://github.com/Pchelolo","followers_url":"https://api.github.com/users/Pchelolo/followers","following_url":"https://api.github.com/users/Pchelolo/following{/other_user}","gists_url":"https://api.github.com/users/Pchelolo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pchelolo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pchelolo/subscriptions","organizations_url":"https://api.github.com/users/Pchelolo/orgs","repos_url":"https://api.github.com/users/Pchelolo/repos","events_url":"https://api.github.com/users/Pchelolo/events{/privacy}","received_events_url":"https://api.github.com/users/Pchelolo/received_events","type":"User","site_admin":false},"body":"This is a work-in-progress PR and some features are not implemented yet.\r\n\r\nAdding 2 public routes:\r\n- `POST /media/graph/{format}?mode={store|preview}` - only for internal IPs\r\n - In store mode:\r\n    - A request hash is calculated\r\n    - Storage checked for already rendered content\r\n    - Two requests are sent to graphoid for png and svg content. If error occurs - it's propagated back to user and nothing is stored.\r\n    - Results for png and svg are stored\r\n    - Request is stored\r\n    - Result returned with `x-resource-location` header\r\n - In preview mode:\r\n    - Requests are passed to graphoid png and svg endpoints\r\n    - Results are stored. To avoid clashing hashes with `store` mode, special `stub` field is added to the data when a hash is calculated. The stub field is not stored.\r\n    - Result is returned with `x-resource-location` header\r\n- `GET /media/graph/{format}/{hash}`\r\n -  Content buckets for a given format is checked.\r\n - If not found - original request is loaded\r\n - Original request sent to graphoid to regenerate content\r\n - Result is stored and returned.\r\n\r\nBoth endpoints support `cache-control: no-cache` header to force rerendering.\r\n\r\nWhat's left:\r\n- Title and revision are not stored for debugging purposes yet - need to make some changes in post_data to not use them is hash calculation\r\n- Monitoring should be added to endpoints\r\n- Graphoid endpoints are not deployed yet, so all graphoid tests are failing.\r\n- There's not way to set _TTL for storage yet, so right now everything is stored permanently, even `preview` content.","created_at":"2015-10-26T20:45:13Z","updated_at":"2015-10-29T09:49:25Z","closed_at":null,"merged_at":null,"merge_commit_sha":"67add111c145fe6657e2775c09583e83ce905d92","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/wikimedia/restbase/pulls/388/commits","review_comments_url":"https://api.github.com/repos/wikimedia/restbase/pulls/388/comments","review_comment_url":"https://api.github.com/repos/wikimedia/restbase/pulls/comments{/number}","comments_url":"https://api.github.com/repos/wikimedia/restbase/issues/388/comments","statuses_url":"https://api.github.com/repos/wikimedia/restbase/statuses/4f60f632958a44a2ad26f90c59486f1e6806d933","head":{"label":"Pchelolo:graphoid","ref":"graphoid","sha":"4f60f632958a44a2ad26f90c59486f1e6806d933","user":{"login":"Pchelolo","id":814754,"avatar_url":"https://avatars.githubusercontent.com/u/814754?v=3","gravatar_id":"","url":"https://api.github.com/users/Pchelolo","html_url":"https://github.com/Pchelolo","followers_url":"https://api.github.com/users/Pchelolo/followers","following_url":"https://api.github.com/users/Pchelolo/following{/other_user}","gists_url":"https://api.github.com/users/Pchelolo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pchelolo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pchelolo/subscriptions","organizations_url":"https://api.github.com/users/Pchelolo/orgs","repos_url":"https://api.github.com/users/Pchelolo/repos","events_url":"https://api.github.com/users/Pchelolo/events{/privacy}","received_events_url":"https://api.github.com/users/Pchelolo/received_events","type":"User","site_admin":false},"repo":{"id":37933525,"name":"restbase","full_name":"Pchelolo/restbase","owner":{"login":"Pchelolo","id":814754,"avatar_url":"https://avatars.githubusercontent.com/u/814754?v=3","gravatar_id":"","url":"https://api.github.com/users/Pchelolo","html_url":"https://github.com/Pchelolo","followers_url":"https://api.github.com/users/Pchelolo/followers","following_url":"https://api.github.com/users/Pchelolo/following{/other_user}","gists_url":"https://api.github.com/users/Pchelolo/gists{/gist_id}","starred_url":"https://api.github.com/users/Pchelolo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Pchelolo/subscriptions","organizations_url":"https://api.github.com/users/Pchelolo/orgs","repos_url":"https://api.github.com/users/Pchelolo/repos","events_url":"https://api.github.com/users/Pchelolo/events{/privacy}","received_events_url":"https://api.github.com/users/Pchelolo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Pchelolo/restbase","description":"Distributed storage with REST API & dispatcher for backend services","fork":true,"url":"https://api.github.com/repos/Pchelolo/restbase","forks_url":"https://api.github.com/repos/Pchelolo/restbase/forks","keys_url":"https://api.github.com/repos/Pchelolo/restbase/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Pchelolo/restbase/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Pchelolo/restbase/teams","hooks_url":"https://api.github.com/repos/Pchelolo/restbase/hooks","issue_events_url":"https://api.github.com/repos/Pchelolo/restbase/issues/events{/number}","events_url":"https://api.github.com/repos/Pchelolo/restbase/events","assignees_url":"https://api.github.com/repos/Pchelolo/restbase/assignees{/user}","branches_url":"https://api.github.com/repos/Pchelolo/restbase/branches{/branch}","tags_url":"https://api.github.com/repos/Pchelolo/restbase/tags","blobs_url":"https://api.github.com/repos/Pchelolo/restbase/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Pchelolo/restbase/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Pchelolo/restbase/git/refs{/sha}","trees_url":"https://api.github.com/repos/Pchelolo/restbase/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Pchelolo/restbase/statuses/{sha}","languages_url":"https://api.github.com/repos/Pchelolo/restbase/languages","stargazers_url":"https://api.github.com/repos/Pchelolo/restbase/stargazers","contributors_url":"https://api.github.com/repos/Pchelolo/restbase/contributors","subscribers_url":"https://api.github.com/repos/Pchelolo/restbase/subscribers","subscription_url":"https://api.github.com/repos/Pchelolo/restbase/subscription","commits_url":"https://api.github.com/repos/Pchelolo/restbase/commits{/sha}","git_commits_url":"https://api.github.com/repos/Pchelolo/restbase/git/commits{/sha}","comments_url":"https://api.github.com/repos/Pchelolo/restbase/comments{/number}","issue_comment_url":"https://api.github.com/repos/Pchelolo/restbase/issues/comments{/number}","contents_url":"https://api.github.com/repos/Pchelolo/restbase/contents/{+path}","compare_url":"https://api.github.com/repos/Pchelolo/restbase/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Pchelolo/restbase/merges","archive_url":"https://api.github.com/repos/Pchelolo/restbase/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Pchelolo/restbase/downloads","issues_url":"https://api.github.com/repos/Pchelolo/restbase/issues{/number}","pulls_url":"https://api.github.com/repos/Pchelolo/restbase/pulls{/number}","milestones_url":"https://api.github.com/repos/Pchelolo/restbase/milestones{/number}","notifications_url":"https://api.github.com/repos/Pchelolo/restbase/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Pchelolo/restbase/labels{/name}","releases_url":"https://api.github.com/repos/Pchelolo/restbase/releases{/id}","created_at":"2015-06-23T17:22:56Z","updated_at":"2015-06-23T17:22:57Z","pushed_at":"2015-10-28T16:44:48Z","git_url":"git://github.com/Pchelolo/restbase.git","ssh_url":"git@github.com:Pchelolo/restbase.git","clone_url":"https://github.com/Pchelolo/restbase.git","svn_url":"https://github.com/Pchelolo/restbase","homepage":"https://www.mediawiki.org/wiki/RESTBase","size":2691,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"wikimedia:master","ref":"master","sha":"dd67e24e60dadf2c03bd26577d135089a8036fa3","user":{"login":"wikimedia","id":56668,"avatar_url":"https://avatars.githubusercontent.com/u/56668?v=3","gravatar_id":"","url":"https://api.github.com/users/wikimedia","html_url":"https://github.com/wikimedia","followers_url":"https://api.github.com/users/wikimedia/followers","following_url":"https://api.github.com/users/wikimedia/following{/other_user}","gists_url":"https://api.github.com/users/wikimedia/gists{/gist_id}","starred_url":"https://api.github.com/users/wikimedia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wikimedia/subscriptions","organizations_url":"https://api.github.com/users/wikimedia/orgs","repos_url":"https://api.github.com/users/wikimedia/repos","events_url":"https://api.github.com/users/wikimedia/events{/privacy}","received_events_url":"https://api.github.com/users/wikimedia/received_events","type":"Organization","site_admin":false},"repo":{"id":19002414,"name":"restbase","full_name":"wikimedia/restbase","owner":{"login":"wikimedia","id":56668,"avatar_url":"https://avatars.githubusercontent.com/u/56668?v=3","gravatar_id":"","url":"https://api.github.com/users/wikimedia","html_url":"https://github.com/wikimedia","followers_url":"https://api.github.com/users/wikimedia/followers","following_url":"https://api.github.com/users/wikimedia/following{/other_user}","gists_url":"https://api.github.com/users/wikimedia/gists{/gist_id}","starred_url":"https://api.github.com/users/wikimedia/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wikimedia/subscriptions","organizations_url":"https://api.github.com/users/wikimedia/orgs","repos_url":"https://api.github.com/users/wikimedia/repos","events_url":"https://api.github.com/users/wikimedia/events{/privacy}","received_events_url":"https://api.github.com/users/wikimedia/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/wikimedia/restbase","description":"Distributed storage with REST API & dispatcher for backend services","fork":false,"url":"https://api.github.com/repos/wikimedia/restbase","forks_url":"https://api.github.com/repos/wikimedia/restbase/forks","keys_url":"https://api.github.com/repos/wikimedia/restbase/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wikimedia/restbase/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wikimedia/restbase/teams","hooks_url":"https://api.github.com/repos/wikimedia/restbase/hooks","issue_events_url":"https://api.github.com/repos/wikimedia/restbase/issues/events{/number}","events_url":"https://api.github.com/repos/wikimedia/restbase/events","assignees_url":"https://api.github.com/repos/wikimedia/restbase/assignees{/user}","branches_url":"https://api.github.com/repos/wikimedia/restbase/branches{/branch}","tags_url":"https://api.github.com/repos/wikimedia/restbase/tags","blobs_url":"https://api.github.com/repos/wikimedia/restbase/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wikimedia/restbase/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wikimedia/restbase/git/refs{/sha}","trees_url":"https://api.github.com/repos/wikimedia/restbase/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wikimedia/restbase/statuses/{sha}","languages_url":"https://api.github.com/repos/wikimedia/restbase/languages","stargazers_url":"https://api.github.com/repos/wikimedia/restbase/stargazers","contributors_url":"https://api.github.com/repos/wikimedia/restbase/contributors","subscribers_url":"https://api.github.com/repos/wikimedia/restbase/subscribers","subscription_url":"https://api.github.com/repos/wikimedia/restbase/subscription","commits_url":"https://api.github.com/repos/wikimedia/restbase/commits{/sha}","git_commits_url":"https://api.github.com/repos/wikimedia/restbase/git/commits{/sha}","comments_url":"https://api.github.com/repos/wikimedia/restbase/comments{/number}","issue_comment_url":"https://api.github.com/repos/wikimedia/restbase/issues/comments{/number}","contents_url":"https://api.github.com/repos/wikimedia/restbase/contents/{+path}","compare_url":"https://api.github.com/repos/wikimedia/restbase/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wikimedia/restbase/merges","archive_url":"https://api.github.com/repos/wikimedia/restbase/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wikimedia/restbase/downloads","issues_url":"https://api.github.com/repos/wikimedia/restbase/issues{/number}","pulls_url":"https://api.github.com/repos/wikimedia/restbase/pulls{/number}","milestones_url":"https://api.github.com/repos/wikimedia/restbase/milestones{/number}","notifications_url":"https://api.github.com/repos/wikimedia/restbase/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wikimedia/restbase/labels{/name}","releases_url":"https://api.github.com/repos/wikimedia/restbase/releases{/id}","created_at":"2014-04-21T18:35:00Z","updated_at":"2015-10-06T12:33:17Z","pushed_at":"2015-10-28T17:32:16Z","git_url":"git://github.com/wikimedia/restbase.git","ssh_url":"git@github.com:wikimedia/restbase.git","clone_url":"https://github.com/wikimedia/restbase.git","svn_url":"https://github.com/wikimedia/restbase","homepage":"https://www.mediawiki.org/wiki/RESTBase","size":5209,"stargazers_count":32,"watchers_count":32,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":28,"mirror_url":null,"open_issues_count":4,"forks":28,"open_issues":4,"watchers":32,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/388"},"html":{"href":"https://github.com/wikimedia/restbase/pull/388"},"issue":{"href":"https://api.github.com/repos/wikimedia/restbase/issues/388"},"comments":{"href":"https://api.github.com/repos/wikimedia/restbase/issues/388/comments"},"review_comments":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/388/comments"},"review_comment":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/wikimedia/restbase/pulls/388/commits"},"statuses":{"href":"https://api.github.com/repos/wikimedia/restbase/statuses/4f60f632958a44a2ad26f90c59486f1e6806d933"}}}}