{"action":"created","comment":{"url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/comments/82003706","pull_request_review_id":2941444,"id":82003706,"diff_hunk":"@@ -0,0 +1,301 @@\n+/** *\n+  * Copyright 2014 Rackspace US, Inc.\n+  *\n+  * Licensed under the Apache License, Version 2.0 (the \"License\");\n+  * you may not use this file except in compliance with the License.\n+  * You may obtain a copy of the License at\n+  *\n+  * http://www.apache.org/licenses/LICENSE-2.0\n+  *\n+  * Unless required by applicable law or agreed to in writing, software\n+  * distributed under the License is distributed on an \"AS IS\" BASIS,\n+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+  * See the License for the specific language governing permissions and\n+  * limitations under the License.\n+  */\n+package com.rackspace.com.papi.components.checker\n+\n+import java.io.File\n+import javax.servlet.FilterChain\n+import javax.servlet.http.HttpServletResponse\n+\n+import com.rackspace.cloud.api.wadl.Converters._\n+import org.mockito.Mockito._\n+import org.scalatest.FlatSpec\n+\n+abstract class GivenAWadlWithAuthenticatedByBase extends FlatSpec {\n+\n+  import GivenAWadlWithAuthenticatedByBase._\n+\n+  val wadl =\n+    <application xmlns=\"http://wadl.dev.java.net/2009/02\"\n+                 xmlns:rax=\"http://docs.rackspace.com/api\"\n+                 xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n+      <resources base=\"https://test.api.openstack.com\">\n+        <resource path=\"/noAuthenticatedBy\">\n+          <method name=\"GET\">{ DefaultRequest }</method>\n+          <method name=\"POST\">{ DefaultRequest }</method>\n+          <method name=\"PUT\">{ DefaultRequest }</method>\n+          <method name=\"DELETE\">{ DefaultRequest }</method>\n+        </resource>\n+        <resource path=\"/resourceLevel\" rax:authenticatedBy=\"APIKEY\">\n+          <method name=\"GET\">{ DefaultRequest }</method>\n+          <method name=\"POST\">{ DefaultRequest }</method>\n+          <method name=\"PUT\">{ DefaultRequest }</method>\n+          <method name=\"DELETE\">{ DefaultRequest }</method>\n+        </resource>\n+        <resource path=\"/methodLevel\">\n+          <method name=\"GET\" rax:authenticatedBy=\"PASSCODE\">{ DefaultRequest }</method>\n+          <method name=\"POST\" rax:authenticatedBy=\"APIKEY\">{ DefaultRequest }</method>\n+          <method name=\"PUT\" rax:authenticatedBy=\"PASSWORD\">{ DefaultRequest }</method>\n+          <method name=\"DELETE\" rax:authenticatedBy=\"FEDERATED\">{ DefaultRequest }</method>\n+        </resource>\n+        <resource path=\"/multipleValues\" rax:authenticatedBy=\"APIKEY PASSWORD OTPPASSCODE\">\n+          <method name=\"GET\">{ DefaultRequest }</method>\n+          <method name=\"POST\">{ DefaultRequest }</method>\n+          <method name=\"PUT\">{ DefaultRequest }</method>\n+          <method name=\"DELETE\">{ DefaultRequest }</method>\n+        </resource>\n+        <resource path=\"/multipleLevels\" rax:authenticatedBy=\"RSAKEY\">\n+          <method name=\"GET\" rax:authenticatedBy=\"RSAKEY\">{ DefaultRequest }</method>\n+          <method name=\"POST\" rax:authenticatedBy=\"APIKEY\">{ DefaultRequest }</method>\n+          <method name=\"PUT\" rax:authenticatedBy=\"PASSWORD\">{ DefaultRequest }</method>\n+          <method name=\"DELETE\" rax:authenticatedBy=\"FEDERATED\">{ DefaultRequest }</method>\n+        </resource>\n+        <resource path=\"/parentResourceLevel\" rax:authenticatedBy=\"PASSCODE\">\n+          <resource path=\"/noAdditionalAuthBy\">\n+            <method name=\"GET\">{ DefaultRequest }</method>\n+            <method name=\"POST\">{ DefaultRequest }</method>\n+            <method name=\"PUT\">{ DefaultRequest }</method>\n+            <method name=\"DELETE\">{ DefaultRequest }</method>\n+          </resource>\n+          <resource path=\"/allAuthByAllowed\" rax:authenticatedBy=\"#all\">\n+            <method name=\"GET\">{ DefaultRequest }</method>\n+            <method name=\"POST\">{ DefaultRequest }</method>\n+            <method name=\"PUT\">{ DefaultRequest }</method>\n+            <method name=\"DELETE\">{ DefaultRequest }</method>\n+          </resource>\n+        </resource>\n+        <resource path=\"/resourceWithHeaderPresent\" rax:authenticatedBy=\"RSAKEY\">\n+          <method name=\"GET\">\n+            <request>\n+              <param name={ AuthByHeader } style=\"header\" required=\"true\" fixed=\"PASSWORD\"/>\n+              <representation mediaType={ DefaultMediaType }/>\n+            </request>\n+          </method>\n+        </resource>\n+        <resource path=\"/methodWithHeaderPresent\">\n+          <method name=\"GET\" rax:authenticatedBy=\"RSAKEY\">\n+            <request>\n+              <param name={ AuthByHeader } style=\"header\" required=\"true\" fixed=\"PASSWORD\"/>\n+              <representation mediaType={ DefaultMediaType }/>\n+            </request>\n+          </method>\n+        </resource>\n+        <resource path=\"/methodId\" rax:authenticatedBy=\"RSAKEY\">\n+          <method href=\"#getOnMethodId\" rax:authenticatedBy=\"APIKEY\"/>\n+          <resource path=\"/more\" rax:authenticatedBy=\"PASSWORD\">\n+            <method href=\"#getOnMore\" rax:authenticatedBy=\"PASSCODE\"/>\n+            <method href=\"#postOnMore\"/>\n+            <method href=\"#putOnMore\" rax:authenticatedBy=\"IMPERSONATION\"/>\n+          </resource>\n+        </resource>\n+      </resources>\n+      <method id=\"getOnMethodId\" name=\"GET\">{ DefaultRequest }</method>\n+      <method id=\"getOnMore\" name=\"GET\">{ DefaultRequest }</method>\n+      <method id=\"postOnMore\" name=\"POST\" rax:authenticatedBy=\"FEDERATED\">{ DefaultRequest }</method>\n+      <method id=\"putOnMore\" name=\"PUT\" rax:authenticatedBy=\"OTPPASSCODE\">{ DefaultRequest }</method>\n+    </application>\n+\n+  val requestBody = base.goodXML_XSD2\n+\n+  def createTests(useSaxon: Boolean): Unit = {\n+    val config = createConfig(useSaxon)\n+    val validator = Validator((localWADLURI, wadl), config)\n+    val authByCombinations = getAllCombinations(ValidAuthenticatedByValues)\n+    var desc: String = \"\"\n+\n+    def accessIsAllowed(method: String, path: String, authBy: List[String], desc: String): Unit = {\n+      it should s\"succeed when $method on $path with $AuthByHeader values $authBy for a $desc\" in {\n+        validator.validate(createRequest(method, path, authBy), response, chain)\n+      }\n+    }\n+\n+    def accessIsNotAllowed(method: String, path: String, authBy: List[String], desc: String): Unit = {\n+      it should s\"fail with a 403 when $method on $path with $AuthByHeader values $authBy for a $desc\" in {\n+        base.assertResultFailed(validator.validate(\n+          createRequest(method, path, authBy), response, chain),\n+          HttpCodeForbidden,\n+          \"You are forbidden to perform the operation\")\n+      }\n+    }\n+\n+    // everything should be allowed when no rax:authenticatedBy is configured on the resource or method\n+    desc = \"resource and method with no rax:authenticatedBy\"\n+    for {\n+      authBy <- authByCombinations\n+      method <- WadlMethods\n+    } {\n+      it should behave like accessIsAllowed(method, \"/noAuthenticatedBy\", authBy, desc)\n+    }\n+\n+    // rax:authenticatedBy set at resource level applies to all of the resource's methods\n+    desc = \"resource with rax:authenticatedBy of APIKEY\"\n+    WadlMethods.foreach { method =>\n+      it should behave like accessIsAllowed(method, \"/resourceLevel\", List(\"APIKEY\"), desc)\n+      it should behave like accessIsAllowed(method, \"/resourceLevel\", List(\"APIKEY\", \"PASSCODE\", \"RSAKEY\"), desc)\n+\n+      authByCombinations.filterNot(_.contains(\"APIKEY\")).foreach { authBy =>\n+        it should behave like accessIsNotAllowed(method, \"/resourceLevel\", authBy, desc)\n+      }\n+    }\n+\n+    // rax:authenticatedBy set at the method level applies to only that method\n+    desc = \"method with rax:authenticatedBy of\"\n+    WadlMethods.zip(List(\"PASSCODE\", \"APIKEY\", \"PASSWORD\", \"FEDERATED\")).foreach { case (method, authBy) =>\n+      it should behave like accessIsAllowed(method, \"/methodLevel\", List(authBy), s\"$desc $authBy\")\n+      it should behave like accessIsAllowed(method, \"/methodLevel\", List(authBy, \"BACON\"), s\"$desc $authBy\")\n+      it should behave like accessIsNotAllowed(method, \"/methodLevel\", InvalidAuthBy, s\"$desc $authBy\")\n+      it should behave like accessIsNotAllowed(method, \"/methodLevel\", NoAuthBy, s\"$desc $authBy\")\n+    }\n+\n+    // rax:authenticatedBy set at resource level with multiple values\n+    desc = \"resource with rax:authenticatedBy of APIKEY PASSWORD OTPPASSCODE\"\n+    val multipleAuthByCombos = getAllCombinations(Set(\"APIKEY\", \"PASSWORD\", \"OTPPASSCODE\")).filterNot(_.isEmpty)\n+    WadlMethods.foreach { method =>\n+      multipleAuthByCombos.foreach { authBy =>\n+        it should behave like accessIsAllowed(method, \"/multipleValues\", authBy, desc)\n+      }\n+      it should behave like accessIsNotAllowed(method, \"/multipleValues\", InvalidAuthBy, desc)\n+      it should behave like accessIsNotAllowed(method, \"/multipleValues\", NoAuthBy, desc)\n+    }\n+\n+    // rax:authenticatedBy set at both resource and method level, values should be OR'd\n+    desc = \"resource with rax:authenticatedBy of RSAKEY and method with \"\n+    WadlMethods.zip(List(\"RSAKEY\", \"APIKEY\", \"PASSWORD\", \"FEDERATED\")).foreach { case (method, authBy) =>\n+      it should behave like accessIsAllowed(method, \"/multipleLevels\", List(authBy), s\"$desc $authBy\")\n+      it should behave like accessIsAllowed(method, \"/multipleLevels\", List(\"RSAKEY\", \"BACON\"), s\"$desc $authBy\")\n+      it should behave like accessIsNotAllowed(method, \"/multipleLevels\", InvalidAuthBy, s\"$desc $authBy\")\n+      it should behave like accessIsNotAllowed(method, \"/multipleLevels\", NoAuthBy, s\"$desc $authBy\")\n+    }\n+\n+    // rax:authenticatedBy set at parent resource level should apply to all of the methods\n+    desc = \"parent resource with rax:authenticatedBy of PASSCODE\"\n+    WadlMethods.foreach { method =>\n+      it should behave like accessIsAllowed(method, \"/parentResourceLevel/noAdditionalAuthBy\", List(\"PASSCODE\"), desc)\n+      it should behave like accessIsNotAllowed(method, \"/parentResourceLevel/noAdditionalAuthBy\", InvalidAuthBy, desc)\n+      it should behave like accessIsNotAllowed(method, \"/parentResourceLevel/noAdditionalAuthBy\", NoAuthBy, desc)\n+    }\n+\n+    // rax:authenticatedBy set at resource level to #all should allow everything\n+    desc = \"resource with rax:authenticatedBy of #all and parent resource with PASSCODE\"\n+    for {\n+      authBy <- authByCombinations\n+      method <- WadlMethods\n+    } {\n+      it should behave like accessIsAllowed(method, \"/parentResourceLevel/allAuthByAllowed\", authBy, desc)\n+    }\n+\n+    // rax:authenticatedBy set at resource level and an X-Authenticated-By header that should be ignored\n+    desc = \"resource with rax:authenticatedBy of RSAKEY and header param set to PASSWORD\"\n+    it should behave like accessIsAllowed(\"GET\", \"/resourceWithHeaderPresent\", List(\"RSAKEY\"), desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/resourceWithHeaderPresent\", List(\"PASSWORD\"), desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/resourceWithHeaderPresent\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/resourceWithHeaderPresent\", NoAuthBy, desc)\n+\n+    // rax:authenticatedBy set at method level and an X-Authenticated-By header that should be ignored\n+    desc = \"method with rax:authenticatedBy of RSAKEY and header param set to PASSWORD\"\n+    it should behave like accessIsAllowed(\"GET\", \"/methodWithHeaderPresent\", List(\"RSAKEY\"), desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodWithHeaderPresent\", List(\"PASSWORD\"), desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodWithHeaderPresent\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodWithHeaderPresent\", NoAuthBy, desc)\n+\n+    // reference a method with rax:authenticatedBy on resource and referencing method\n+    desc = \"method with a rax:authenticatedBy and referencing another method, resource rax:authenticatedBy\"\n+    Set(\"RSAKEY\", \"APIKEY\").foreach { authBy =>\n+      it should behave like accessIsAllowed(\"GET\", \"/methodId\", List(authBy), desc)\n+    }\n+    Set(\"PASSWORD\", \"PASSCODE\", \"OTPPASSCODE\", \"IMPERSONATION\", \"FEDERATED\").foreach { authBy =>\n+      it should behave like accessIsNotAllowed(\"GET\", \"/methodId\", List(authBy), desc)\n+    }\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodId\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodId\", NoAuthBy, desc)\n+\n+    // reference a method with rax:authenticatedBy on parent+child resource and referencing method\n+    desc = \"method with a rax:authenticatedBy and referencing another method, parent+child resource rax:authenticatedBy\"\n+    Set(\"RSAKEY\", \"PASSWORD\", \"PASSCODE\").foreach { authBy =>\n+      it should behave like accessIsAllowed(\"GET\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    Set(\"APIKEY\", \"OTPPASSCODE\", \"IMPERSONATION\", \"FEDERATED\").foreach { authBy =>\n+      it should behave like accessIsNotAllowed(\"GET\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodId/more\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"GET\", \"/methodId/more\", NoAuthBy, desc)\n+\n+    // reference a method with rax:authenticatedBy on parent+child resource and referenced method\n+    desc = \"method and referencing another method with a rax:authenticatedBy, parent+child resource rax:authenticatedBy\"\n+    Set(\"RSAKEY\", \"PASSWORD\", \"FEDERATED\").foreach { authBy =>\n+      it should behave like accessIsAllowed(\"POST\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    Set(\"APIKEY\", \"PASSCODE\", \"OTPPASSCODE\", \"IMPERSONATION\").foreach { authBy =>\n+      it should behave like accessIsNotAllowed(\"POST\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    it should behave like accessIsNotAllowed(\"POST\", \"/methodId/more\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"POST\", \"/methodId/more\", NoAuthBy, desc)\n+\n+    // reference a method with rax:authenticatedBy on parent+child resource and referencing+referenced method\n+    desc = \"method and referencing another method, both with a rax:authenticatedBy, and parent+child resource rax:authenticatedBy\"\n+    Set(\"RSAKEY\", \"PASSWORD\", \"IMPERSONATION\").foreach { authBy =>\n+      it should behave like accessIsAllowed(\"PUT\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    Set(\"APIKEY\", \"PASSCODE\", \"FEDERATED\", \"OTPPASSCODE\").foreach { authBy =>\n+      it should behave like accessIsNotAllowed(\"PUT\", \"/methodId/more\", List(authBy), desc)\n+    }\n+    it should behave like accessIsNotAllowed(\"PUT\", \"/methodId/more\", InvalidAuthBy, desc)\n+    it should behave like accessIsNotAllowed(\"PUT\", \"/methodId/more\", NoAuthBy, desc)\n+  }\n+\n+  def createRequest(method: String, path: String, authBy: List[String]) =\n+    base.request(method, path, DefaultMediaType, requestBody, parseContent = false, Map(AuthByHeader -> authBy))\n+\n+  def createConfig(useSaxon: Boolean): Config = {\n+    val config = new Config\n+\n+    if (useSaxon) {\n+      config.xsdEngine                    = \"SaxonEE\"\n+    }\n+    config.removeDups                     = true    // -d Wadl2Checker default is different from Config default.","path":"core/src/test/scala/com/rackspace/com/papi/components/checker/GivenAWadlWithAuthenticatedByBase.scala","position":267,"original_position":267,"commit_id":"a078cc1cbd9abecbabefa0c175d57742cc0839be","original_commit_id":"a078cc1cbd9abecbabefa0c175d57742cc0839be","user":{"login":"RackerWilliams","id":348314,"avatar_url":"https://avatars.githubusercontent.com/u/348314?v=3","gravatar_id":"","url":"https://api.github.com/users/RackerWilliams","html_url":"https://github.com/RackerWilliams","followers_url":"https://api.github.com/users/RackerWilliams/followers","following_url":"https://api.github.com/users/RackerWilliams/following{/other_user}","gists_url":"https://api.github.com/users/RackerWilliams/gists{/gist_id}","starred_url":"https://api.github.com/users/RackerWilliams/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RackerWilliams/subscriptions","organizations_url":"https://api.github.com/users/RackerWilliams/orgs","repos_url":"https://api.github.com/users/RackerWilliams/repos","events_url":"https://api.github.com/users/RackerWilliams/events{/privacy}","received_events_url":"https://api.github.com/users/RackerWilliams/received_events","type":"User","site_admin":false},"body":"See other tests,  you typically want to iterate over these possible options.  Also you need to check that enableAuthenticatedByExtension also enables checkHeaders, etc.","created_at":"2016-10-05T15:41:40Z","updated_at":"2016-10-05T15:41:40Z","html_url":"https://github.com/rackerlabs/api-checker/pull/317#discussion_r82003706","pull_request_url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317","_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/comments/82003706"},"html":{"href":"https://github.com/rackerlabs/api-checker/pull/317#discussion_r82003706"},"pull_request":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317"}}},"pull_request":{"url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317","id":88075933,"html_url":"https://github.com/rackerlabs/api-checker/pull/317","diff_url":"https://github.com/rackerlabs/api-checker/pull/317.diff","patch_url":"https://github.com/rackerlabs/api-checker/pull/317.patch","issue_url":"https://api.github.com/repos/rackerlabs/api-checker/issues/317","number":317,"state":"open","locked":false,"title":"REP-4446 Add authenticated-by extension","user":{"login":"Mario-Lopez","id":6766560,"avatar_url":"https://avatars.githubusercontent.com/u/6766560?v=3","gravatar_id":"","url":"https://api.github.com/users/Mario-Lopez","html_url":"https://github.com/Mario-Lopez","followers_url":"https://api.github.com/users/Mario-Lopez/followers","following_url":"https://api.github.com/users/Mario-Lopez/following{/other_user}","gists_url":"https://api.github.com/users/Mario-Lopez/gists{/gist_id}","starred_url":"https://api.github.com/users/Mario-Lopez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mario-Lopez/subscriptions","organizations_url":"https://api.github.com/users/Mario-Lopez/orgs","repos_url":"https://api.github.com/users/Mario-Lopez/repos","events_url":"https://api.github.com/users/Mario-Lopez/events{/privacy}","received_events_url":"https://api.github.com/users/Mario-Lopez/received_events","type":"User","site_admin":false},"body":"I added a new extension similar to rax:roles but checking the X-Authenticated-By header instead.  Like rax:roles, the extension rax:authenticatedBy can be added to resources and methods, will apply to descendent resources, and can have a value of \"#all\" to allow all values (including no value).  When the rax:authenticatedBy extension is not specified on a resource, method, nor any parent resource, the check will not be performed for that resource and method.\r\n\r\nThe extension can be enabled using the `-u` or `--authenticated-by` option.\r\n\r\nAlso like rax:roles, when a resource method specifies a param for the X-Authenticated-By header, the param will be dropped.  While testing the removal of this behavior, I discovered that if the param header name wasn't exactly X-AUTHENTICATED-BY (in all caps), the check was skipped entirely for that resource method (i.e. the rax:authenticatedBy and param values were both ignored).  For now I left the restriction in to avoid the dangerous behavior.","created_at":"2016-10-05T13:19:05Z","updated_at":"2016-10-05T15:41:40Z","closed_at":null,"merged_at":null,"merge_commit_sha":"460a06e2f7abb018d9736703296558c2ff97a2f3","assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/rackerlabs/api-checker/milestones/35","html_url":"https://github.com/rackerlabs/api-checker/milestones/2.0.2","labels_url":"https://api.github.com/repos/rackerlabs/api-checker/milestones/35/labels","id":1926594,"number":35,"title":"2.0.2","description":"","creator":{"login":"RackerWilliams","id":348314,"avatar_url":"https://avatars.githubusercontent.com/u/348314?v=3","gravatar_id":"","url":"https://api.github.com/users/RackerWilliams","html_url":"https://github.com/RackerWilliams","followers_url":"https://api.github.com/users/RackerWilliams/followers","following_url":"https://api.github.com/users/RackerWilliams/following{/other_user}","gists_url":"https://api.github.com/users/RackerWilliams/gists{/gist_id}","starred_url":"https://api.github.com/users/RackerWilliams/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RackerWilliams/subscriptions","organizations_url":"https://api.github.com/users/RackerWilliams/orgs","repos_url":"https://api.github.com/users/RackerWilliams/repos","events_url":"https://api.github.com/users/RackerWilliams/events{/privacy}","received_events_url":"https://api.github.com/users/RackerWilliams/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":5,"state":"open","created_at":"2016-08-06T05:34:15Z","updated_at":"2016-10-05T15:26:54Z","due_on":"2016-09-30T05:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317/commits","review_comments_url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317/comments","review_comment_url":"https://api.github.com/repos/rackerlabs/api-checker/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rackerlabs/api-checker/issues/317/comments","statuses_url":"https://api.github.com/repos/rackerlabs/api-checker/statuses/a078cc1cbd9abecbabefa0c175d57742cc0839be","head":{"label":"Mario-Lopez:REP-4446_AuthenticatedByExtension","ref":"REP-4446_AuthenticatedByExtension","sha":"a078cc1cbd9abecbabefa0c175d57742cc0839be","user":{"login":"Mario-Lopez","id":6766560,"avatar_url":"https://avatars.githubusercontent.com/u/6766560?v=3","gravatar_id":"","url":"https://api.github.com/users/Mario-Lopez","html_url":"https://github.com/Mario-Lopez","followers_url":"https://api.github.com/users/Mario-Lopez/followers","following_url":"https://api.github.com/users/Mario-Lopez/following{/other_user}","gists_url":"https://api.github.com/users/Mario-Lopez/gists{/gist_id}","starred_url":"https://api.github.com/users/Mario-Lopez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mario-Lopez/subscriptions","organizations_url":"https://api.github.com/users/Mario-Lopez/orgs","repos_url":"https://api.github.com/users/Mario-Lopez/repos","events_url":"https://api.github.com/users/Mario-Lopez/events{/privacy}","received_events_url":"https://api.github.com/users/Mario-Lopez/received_events","type":"User","site_admin":false},"repo":{"id":69608182,"name":"api-checker","full_name":"Mario-Lopez/api-checker","owner":{"login":"Mario-Lopez","id":6766560,"avatar_url":"https://avatars.githubusercontent.com/u/6766560?v=3","gravatar_id":"","url":"https://api.github.com/users/Mario-Lopez","html_url":"https://github.com/Mario-Lopez","followers_url":"https://api.github.com/users/Mario-Lopez/followers","following_url":"https://api.github.com/users/Mario-Lopez/following{/other_user}","gists_url":"https://api.github.com/users/Mario-Lopez/gists{/gist_id}","starred_url":"https://api.github.com/users/Mario-Lopez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Mario-Lopez/subscriptions","organizations_url":"https://api.github.com/users/Mario-Lopez/orgs","repos_url":"https://api.github.com/users/Mario-Lopez/repos","events_url":"https://api.github.com/users/Mario-Lopez/events{/privacy}","received_events_url":"https://api.github.com/users/Mario-Lopez/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Mario-Lopez/api-checker","description":"The API Checker library allows checking a rest servlet against a contract written in WADL","fork":true,"url":"https://api.github.com/repos/Mario-Lopez/api-checker","forks_url":"https://api.github.com/repos/Mario-Lopez/api-checker/forks","keys_url":"https://api.github.com/repos/Mario-Lopez/api-checker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Mario-Lopez/api-checker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Mario-Lopez/api-checker/teams","hooks_url":"https://api.github.com/repos/Mario-Lopez/api-checker/hooks","issue_events_url":"https://api.github.com/repos/Mario-Lopez/api-checker/issues/events{/number}","events_url":"https://api.github.com/repos/Mario-Lopez/api-checker/events","assignees_url":"https://api.github.com/repos/Mario-Lopez/api-checker/assignees{/user}","branches_url":"https://api.github.com/repos/Mario-Lopez/api-checker/branches{/branch}","tags_url":"https://api.github.com/repos/Mario-Lopez/api-checker/tags","blobs_url":"https://api.github.com/repos/Mario-Lopez/api-checker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Mario-Lopez/api-checker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Mario-Lopez/api-checker/git/refs{/sha}","trees_url":"https://api.github.com/repos/Mario-Lopez/api-checker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Mario-Lopez/api-checker/statuses/{sha}","languages_url":"https://api.github.com/repos/Mario-Lopez/api-checker/languages","stargazers_url":"https://api.github.com/repos/Mario-Lopez/api-checker/stargazers","contributors_url":"https://api.github.com/repos/Mario-Lopez/api-checker/contributors","subscribers_url":"https://api.github.com/repos/Mario-Lopez/api-checker/subscribers","subscription_url":"https://api.github.com/repos/Mario-Lopez/api-checker/subscription","commits_url":"https://api.github.com/repos/Mario-Lopez/api-checker/commits{/sha}","git_commits_url":"https://api.github.com/repos/Mario-Lopez/api-checker/git/commits{/sha}","comments_url":"https://api.github.com/repos/Mario-Lopez/api-checker/comments{/number}","issue_comment_url":"https://api.github.com/repos/Mario-Lopez/api-checker/issues/comments{/number}","contents_url":"https://api.github.com/repos/Mario-Lopez/api-checker/contents/{+path}","compare_url":"https://api.github.com/repos/Mario-Lopez/api-checker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Mario-Lopez/api-checker/merges","archive_url":"https://api.github.com/repos/Mario-Lopez/api-checker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Mario-Lopez/api-checker/downloads","issues_url":"https://api.github.com/repos/Mario-Lopez/api-checker/issues{/number}","pulls_url":"https://api.github.com/repos/Mario-Lopez/api-checker/pulls{/number}","milestones_url":"https://api.github.com/repos/Mario-Lopez/api-checker/milestones{/number}","notifications_url":"https://api.github.com/repos/Mario-Lopez/api-checker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Mario-Lopez/api-checker/labels{/name}","releases_url":"https://api.github.com/repos/Mario-Lopez/api-checker/releases{/id}","deployments_url":"https://api.github.com/repos/Mario-Lopez/api-checker/deployments","created_at":"2016-09-29T21:10:50Z","updated_at":"2016-09-29T21:10:51Z","pushed_at":"2016-10-05T12:54:09Z","git_url":"git://github.com/Mario-Lopez/api-checker.git","ssh_url":"git@github.com:Mario-Lopez/api-checker.git","clone_url":"https://github.com/Mario-Lopez/api-checker.git","svn_url":"https://github.com/Mario-Lopez/api-checker","homepage":"www.openrepose.org","size":4127,"stargazers_count":0,"watchers_count":0,"language":"Scala","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":"rackerlabs:master","ref":"master","sha":"b90531ae019a7f2b8d2c30ccd01589ba34dcc724","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":3188519,"name":"api-checker","full_name":"rackerlabs/api-checker","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/api-checker","description":"The API Checker library allows checking a rest servlet against a contract written in WADL","fork":false,"url":"https://api.github.com/repos/rackerlabs/api-checker","forks_url":"https://api.github.com/repos/rackerlabs/api-checker/forks","keys_url":"https://api.github.com/repos/rackerlabs/api-checker/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/api-checker/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/api-checker/teams","hooks_url":"https://api.github.com/repos/rackerlabs/api-checker/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/api-checker/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/api-checker/events","assignees_url":"https://api.github.com/repos/rackerlabs/api-checker/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/api-checker/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/api-checker/tags","blobs_url":"https://api.github.com/repos/rackerlabs/api-checker/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/api-checker/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/api-checker/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/api-checker/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/api-checker/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/api-checker/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/api-checker/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/api-checker/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/api-checker/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/api-checker/subscription","commits_url":"https://api.github.com/repos/rackerlabs/api-checker/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/api-checker/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/api-checker/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/api-checker/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/api-checker/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/api-checker/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/api-checker/merges","archive_url":"https://api.github.com/repos/rackerlabs/api-checker/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/api-checker/downloads","issues_url":"https://api.github.com/repos/rackerlabs/api-checker/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/api-checker/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/api-checker/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/api-checker/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/api-checker/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/api-checker/releases{/id}","deployments_url":"https://api.github.com/repos/rackerlabs/api-checker/deployments","created_at":"2012-01-16T06:39:01Z","updated_at":"2016-09-19T13:25:14Z","pushed_at":"2016-10-05T14:11:04Z","git_url":"git://github.com/rackerlabs/api-checker.git","ssh_url":"git@github.com:rackerlabs/api-checker.git","clone_url":"https://github.com/rackerlabs/api-checker.git","svn_url":"https://github.com/rackerlabs/api-checker","homepage":"www.openrepose.org","size":4861,"stargazers_count":8,"watchers_count":8,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":15,"mirror_url":null,"open_issues_count":32,"forks":15,"open_issues":32,"watchers":8,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317"},"html":{"href":"https://github.com/rackerlabs/api-checker/pull/317"},"issue":{"href":"https://api.github.com/repos/rackerlabs/api-checker/issues/317"},"comments":{"href":"https://api.github.com/repos/rackerlabs/api-checker/issues/317/comments"},"review_comments":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317/comments"},"review_comment":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rackerlabs/api-checker/pulls/317/commits"},"statuses":{"href":"https://api.github.com/repos/rackerlabs/api-checker/statuses/a078cc1cbd9abecbabefa0c175d57742cc0839be"}}}}
{"actor":{"display_login":"RackerWilliams"}}