{"action":"created","comment":{"url":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments/43231287","id":43231287,"diff_hunk":"@@ -0,0 +1,556 @@\n+# encoding: utf-8\n+\n+require_relative '../../../../../lib/carto/http/client'\n+\n+module CartoDB\n+  module Datasources\n+    module Url\n+      # BoxAPI module is a replacement for Boxr, which requires Ruby >= 2.\n+      # Most of this code has been extracted from Boxr.\n+      # This should be migrated when we upgrade to Ruby 2.\n+      module BoxAPI\n+\n+        class ExpiredTokenError < StandardError; end\n+\n+        def self.oauth_url(state, options = {})\n+          host = options.fetch(:host, \"app.box.com\")\n+          response_type = options.fetch(:response_type, \"code\")\n+          scope = options[:scope]\n+          folder_id = options[:folder_id]\n+          client_id = options[:client_id]\n+\n+          template = Addressable::Template.new(\"https://{host}/api/oauth2/authorize{?query*}\")\n+\n+          query = {\"response_type\" => \"#{response_type}\", \"state\" => \"#{state}\", \"client_id\" => \"#{client_id}\"}\n+          query[\"scope\"] = \"#{scope}\" unless scope.nil?\n+          query[\"folder_id\"] = \"#{folder_id}\" unless folder_id.nil?\n+\n+          template.expand({\"host\" => \"#{host}\", \"query\" => query})\n+        end\n+\n+        def self.get_tokens(code, options = {})\n+          grant_type = options[:grant_type]\n+          assertion = options[:assertion]\n+          scope = options[:scope]\n+          username = options[:username]\n+          client_id = options[:client_id]\n+          client_secret = options[:client_secret]\n+\n+          uri = \"https://api.box.com/oauth2/token\"\n+          body = \"grant_type=#{grant_type}&client_id=#{client_id}&client_secret=#{client_secret}\"\n+          body = body + \"&code=#{code}\" unless code.nil?\n+          body = body + \"&scope=#{scope}\" unless scope.nil?\n+          body = body + \"&username=#{username}\" unless username.nil?\n+          body = body + \"&assertion=#{assertion}\" unless assertion.nil?\n+\n+          auth_post(uri, body)\n+        end\n+\n+        def self.refresh_tokens(refresh_token, options = {})\n+          client_id = options[:client_id]\n+          client_secret = options[:client_secret]\n+\n+          uri = \"https://api.box.com/oauth2/token\"\n+          body = \"grant_type=refresh_token&refresh_token=#{refresh_token}&client_id=#{client_id}&client_secret=#{client_secret}\"\n+\n+          auth_post(uri, body)\n+        end\n+\n+        def self.auth_post(uri, body, json_body = true)\n+          uri = Addressable::URI.encode(uri)\n+\n+          res = post(uri, body: body)\n+\n+          if(res.response_code == 200)\n+            json_body ? JSON.parse(res.response_body) : res.response_body\n+          else\n+            handle_error_response(res)\n+          end\n+        end\n+\n+        def self.handle_error_response(res)\n+          body_json = JSON.parse(res.response_body)\n+\n+          if body_json['error'] == 'invalid_grant'\n+            raise ExpiredTokenError.new(body_json.fetch('error_description', 'Expired token'))\n+          else\n+            raise \"Box Error status: #{res.response_code}, body: #{res.response_body}, headers: #{res.response_headers}\"\n+          end\n+        rescue => e\n+          CartoDB.notify_exception(e, self: self.inspect, response: res.inspect)\n+          raise e\n+        end\n+\n+        def self.post(uri, options = {})\n+          http_client = Carto::Http::Client.get('box',\n+            connecttimeout: 60,\n+            timeout: 600\n+            )\n+          http_client.post(uri.to_s, options)\n+        end\n+\n+        def self.get(uri, options = {})\n+          query = options[:query]\n+          header = options[:header]\n+          follow_redirect = options[:follow_redirect]\n+\n+          http_client = Carto::Http::Client.get('box',\n+            connecttimeout: 60,\n+            timeout: 600)\n+          response = http_client.get(uri.to_s, headers: header, followlocation: follow_redirect, params: query)\n+          response\n+        end\n+\n+      end\n+\n+      module BoxAPI\n+\n+        class Client\n+\n+          API_URI = \"https://api.box.com/2.0\"\n+          SEARCH_URI = \"#{API_URI}/search\"\n+          FILES_URI = \"#{API_URI}/files\"\n+\n+          def initialize(access_token, options = {})\n+            client_id = options[:client_id]\n+            client_secret = options[:client_secret]\n+\n+            @access_token = access_token\n+            raise \"Access token cannot be nil\" if @access_token.nil?\n+            @client_id = client_id\n+            @client_secret = client_secret\n+          end\n+\n+          def search(query, options = {})\n+            scope = options[:scope]\n+            file_extensions = options[:file_extensions]\n+            created_at_range = options[:created_at_range]\n+            updated_at_range = options[:updated_at_range]\n+            size_range = options[:size_range]\n+            owner_user_ids = options[:owner_user_ids]\n+            ancestor_folder_ids = options[:ancestor_folder_ids]\n+            content_types = options[:content_types]\n+            type = options[:type]\n+            limit = options.fetch(:limit, 30)\n+            offset = options.fetch(:offset, 0)\n+\n+            query = {query: query}\n+            query[:scope] = scope unless scope.nil?\n+            query[:file_extensions] = file_extensions unless file_extensions.nil?\n+            query[:created_at_range] = created_at_range unless created_at_range.nil?\n+            query[:updated_at_range] = updated_at_range unless updated_at_range.nil?\n+            query[:size_range] = size_range unless size_range.nil?\n+            query[:owner_user_ids] = owner_user_ids unless owner_user_ids.nil?\n+            query[:ancestor_folder_ids] = ancestor_folder_ids unless ancestor_folder_ids.nil?\n+            query[:content_types] = content_types unless content_types.nil?\n+            query[:type] = type unless type.nil?\n+            query[:limit] = limit unless limit.nil?\n+            query[:offset] = offset unless offset.nil?\n+\n+            results, response = get(SEARCH_URI, query: query)\n+            results['entries']\n+          end\n+\n+          def download_url(file, options = {})\n+            version = options[:version]\n+\n+            download_file(file, version: version, follow_redirect: false)\n+          end\n+\n+          def download_file(file, options = {})\n+            version = options[:version]\n+            follow_redirect = options.fetch(:follow_redirect, true)\n+\n+            file_id = ensure_id(file)\n+            begin\n+              uri = \"#{FILES_URI}/#{file_id}/content\"\n+              query = {}\n+              query[:version] = version unless version.nil?\n+\n+              # Boxr didn't have 200\n+              body_json, response = get(uri, query: query, success_codes: [302,202,200], follow_redirect: false, process_response: false)\n+\n+              if(response.response_code == 302)\n+                location = response.header['Location'][0]\n+\n+                if(follow_redirect)\n+                  file, response = get(location, process_response: false)\n+                else\n+                  return location #simply return the url\n+                end\n+              elsif(response.response_code==202)\n+                retry_after_seconds = response.header['Retry-After'][0]\n+                sleep retry_after_seconds.to_i\n+              elsif(response.response_code == 200)\n+                file = response.response_body\n+              end\n+            end until file\n+\n+            file\n+          end\n+\n+          FOLDER_AND_FILE_FIELDS = [:type,:id,:sequence_id,:etag,:name,:created_at,:modified_at,:description,","path":"services/datasources/lib/datasources/url/box.rb","position":192,"original_position":192,"commit_id":"25d3e1569111e1801522514e7aeed584aceab271","original_commit_id":"25d3e1569111e1801522514e7aeed584aceab271","user":{"login":"houndci","id":6697940,"avatar_url":"https://avatars.githubusercontent.com/u/6697940?v=3","gravatar_id":"","url":"https://api.github.com/users/houndci","html_url":"https://github.com/houndci","followers_url":"https://api.github.com/users/houndci/followers","following_url":"https://api.github.com/users/houndci/following{/other_user}","gists_url":"https://api.github.com/users/houndci/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci/subscriptions","organizations_url":"https://api.github.com/users/houndci/orgs","repos_url":"https://api.github.com/users/houndci/repos","events_url":"https://api.github.com/users/houndci/events{/privacy}","received_events_url":"https://api.github.com/users/houndci/received_events","type":"User","site_admin":false},"body":"Space missing after comma.","created_at":"2015-10-28T09:13:17Z","updated_at":"2015-10-28T09:13:17Z","html_url":"https://github.com/CartoDB/cartodb/pull/6042#discussion_r43231287","pull_request_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042","_links":{"self":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments/43231287"},"html":{"href":"https://github.com/CartoDB/cartodb/pull/6042#discussion_r43231287"},"pull_request":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042"}}},"pull_request":{"url":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042","id":48979930,"html_url":"https://github.com/CartoDB/cartodb/pull/6042","diff_url":"https://github.com/CartoDB/cartodb/pull/6042.diff","patch_url":"https://github.com/CartoDB/cartodb/pull/6042.patch","issue_url":"https://api.github.com/repos/CartoDB/cartodb/issues/6042","number":6042,"state":"open","locked":false,"title":"5975 box integration","user":{"login":"juanignaciosl","id":932968,"avatar_url":"https://avatars.githubusercontent.com/u/932968?v=3","gravatar_id":"","url":"https://api.github.com/users/juanignaciosl","html_url":"https://github.com/juanignaciosl","followers_url":"https://api.github.com/users/juanignaciosl/followers","following_url":"https://api.github.com/users/juanignaciosl/following{/other_user}","gists_url":"https://api.github.com/users/juanignaciosl/gists{/gist_id}","starred_url":"https://api.github.com/users/juanignaciosl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juanignaciosl/subscriptions","organizations_url":"https://api.github.com/users/juanignaciosl/orgs","repos_url":"https://api.github.com/users/juanignaciosl/repos","events_url":"https://api.github.com/users/juanignaciosl/events{/privacy}","received_events_url":"https://api.github.com/users/juanignaciosl/received_events","type":"User","site_admin":false},"body":"This closes #5975. Integration code is similar to GDrive and Dropbox ones. Box specifics:\r\n- Refresh token is one use only.\r\n- Search is broader.","created_at":"2015-10-28T09:13:04Z","updated_at":"2015-10-28T09:13:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"420a04ceea991881d86137c1eba739417fd69fba","assignee":{"login":"juanignaciosl","id":932968,"avatar_url":"https://avatars.githubusercontent.com/u/932968?v=3","gravatar_id":"","url":"https://api.github.com/users/juanignaciosl","html_url":"https://github.com/juanignaciosl","followers_url":"https://api.github.com/users/juanignaciosl/followers","following_url":"https://api.github.com/users/juanignaciosl/following{/other_user}","gists_url":"https://api.github.com/users/juanignaciosl/gists{/gist_id}","starred_url":"https://api.github.com/users/juanignaciosl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juanignaciosl/subscriptions","organizations_url":"https://api.github.com/users/juanignaciosl/orgs","repos_url":"https://api.github.com/users/juanignaciosl/repos","events_url":"https://api.github.com/users/juanignaciosl/events{/privacy}","received_events_url":"https://api.github.com/users/juanignaciosl/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042/commits","review_comments_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042/comments","review_comment_url":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/issues/6042/comments","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/25d3e1569111e1801522514e7aeed584aceab271","head":{"label":"CartoDB:5975-Box_integration","ref":"5975-Box_integration","sha":"25d3e1569111e1801522514e7aeed584aceab271","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":4909355,"name":"cartodb","full_name":"CartoDB/cartodb","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/cartodb","description":"Location Intelligence & Data Visualization tool","fork":false,"url":"https://api.github.com/repos/CartoDB/cartodb","forks_url":"https://api.github.com/repos/CartoDB/cartodb/forks","keys_url":"https://api.github.com/repos/CartoDB/cartodb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/cartodb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/cartodb/teams","hooks_url":"https://api.github.com/repos/CartoDB/cartodb/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/cartodb/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/cartodb/events","assignees_url":"https://api.github.com/repos/CartoDB/cartodb/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/cartodb/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/cartodb/tags","blobs_url":"https://api.github.com/repos/CartoDB/cartodb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/cartodb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/cartodb/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/cartodb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/cartodb/languages","stargazers_url":"https://api.github.com/repos/CartoDB/cartodb/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/cartodb/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/cartodb/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/cartodb/subscription","commits_url":"https://api.github.com/repos/CartoDB/cartodb/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/cartodb/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/cartodb/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/cartodb/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/cartodb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/cartodb/merges","archive_url":"https://api.github.com/repos/CartoDB/cartodb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/cartodb/downloads","issues_url":"https://api.github.com/repos/CartoDB/cartodb/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/cartodb/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/cartodb/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/cartodb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/cartodb/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/cartodb/releases{/id}","created_at":"2012-07-05T15:23:45Z","updated_at":"2015-10-28T02:47:13Z","pushed_at":"2015-10-28T09:13:05Z","git_url":"git://github.com/CartoDB/cartodb.git","ssh_url":"git@github.com:CartoDB/cartodb.git","clone_url":"https://github.com/CartoDB/cartodb.git","svn_url":"https://github.com/CartoDB/cartodb","homepage":"http://cartodb.com","size":516762,"stargazers_count":972,"watchers_count":972,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":232,"mirror_url":null,"open_issues_count":816,"forks":232,"open_issues":816,"watchers":972,"default_branch":"master"}},"base":{"label":"CartoDB:master","ref":"master","sha":"964e15f5b97cac88d8b50d65015d10ccf6b58955","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":4909355,"name":"cartodb","full_name":"CartoDB/cartodb","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars.githubusercontent.com/u/1799254?v=3","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/cartodb","description":"Location Intelligence & Data Visualization tool","fork":false,"url":"https://api.github.com/repos/CartoDB/cartodb","forks_url":"https://api.github.com/repos/CartoDB/cartodb/forks","keys_url":"https://api.github.com/repos/CartoDB/cartodb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/cartodb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/cartodb/teams","hooks_url":"https://api.github.com/repos/CartoDB/cartodb/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/cartodb/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/cartodb/events","assignees_url":"https://api.github.com/repos/CartoDB/cartodb/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/cartodb/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/cartodb/tags","blobs_url":"https://api.github.com/repos/CartoDB/cartodb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/cartodb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/cartodb/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/cartodb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/cartodb/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/cartodb/languages","stargazers_url":"https://api.github.com/repos/CartoDB/cartodb/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/cartodb/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/cartodb/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/cartodb/subscription","commits_url":"https://api.github.com/repos/CartoDB/cartodb/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/cartodb/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/cartodb/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/cartodb/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/cartodb/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/cartodb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/cartodb/merges","archive_url":"https://api.github.com/repos/CartoDB/cartodb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/cartodb/downloads","issues_url":"https://api.github.com/repos/CartoDB/cartodb/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/cartodb/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/cartodb/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/cartodb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/cartodb/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/cartodb/releases{/id}","created_at":"2012-07-05T15:23:45Z","updated_at":"2015-10-28T02:47:13Z","pushed_at":"2015-10-28T09:13:05Z","git_url":"git://github.com/CartoDB/cartodb.git","ssh_url":"git@github.com:CartoDB/cartodb.git","clone_url":"https://github.com/CartoDB/cartodb.git","svn_url":"https://github.com/CartoDB/cartodb","homepage":"http://cartodb.com","size":516762,"stargazers_count":972,"watchers_count":972,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":232,"mirror_url":null,"open_issues_count":816,"forks":232,"open_issues":816,"watchers":972,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042"},"html":{"href":"https://github.com/CartoDB/cartodb/pull/6042"},"issue":{"href":"https://api.github.com/repos/CartoDB/cartodb/issues/6042"},"comments":{"href":"https://api.github.com/repos/CartoDB/cartodb/issues/6042/comments"},"review_comments":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042/comments"},"review_comment":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CartoDB/cartodb/pulls/6042/commits"},"statuses":{"href":"https://api.github.com/repos/CartoDB/cartodb/statuses/25d3e1569111e1801522514e7aeed584aceab271"}}}}