{"action":"created","comment":{"url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/comments/203421892","pull_request_review_id":138307353,"id":203421892,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMzQyMTg5Mg==","diff_hunk":"@@ -0,0 +1,256 @@\n+package com.mapbox.mapboxsdk.http;\n+\n+import android.content.Context;\n+import android.content.pm.PackageInfo;\n+import android.os.Build;\n+import android.support.annotation.NonNull;\n+import android.support.v4.util.LongSparseArray;\n+import android.text.TextUtils;\n+import android.util.Log;\n+import com.mapbox.android.telemetry.TelemetryUtils;\n+import com.mapbox.mapboxsdk.BuildConfig;\n+import com.mapbox.mapboxsdk.Mapbox;\n+import com.mapbox.mapboxsdk.constants.MapboxConstants;\n+import okhttp3.Call;\n+import okhttp3.Callback;\n+import okhttp3.Dispatcher;\n+import okhttp3.HttpUrl;\n+import okhttp3.OkHttpClient;\n+import okhttp3.Request;\n+import okhttp3.Response;\n+import okhttp3.ResponseBody;\n+import timber.log.Timber;\n+\n+import javax.net.ssl.SSLException;\n+import java.io.IOException;\n+import java.io.InterruptedIOException;\n+import java.net.NoRouteToHostException;\n+import java.net.ProtocolException;\n+import java.net.SocketException;\n+import java.net.UnknownHostException;\n+\n+public class OkHttpRequest extends HttpRequest {\n+\n+  // maintain ongoing calls\n+  private static final LongSparseArray<Call> calls = new LongSparseArray<>();\n+\n+  // configuration\n+  private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();\n+  private static boolean logEnabled = true;\n+  private static boolean logRequestUrl = false;\n+  private static String userAgentString;\n+\n+  @Override\n+  public void executeRequest(NativeHttpRequest httpRequest, long nativePtr, String resourceUrl,\n+                             String etag, String modified) {\n+    Call call = null;\n+    OkHttpCallback callback = new OkHttpCallback(httpRequest);\n+    try {\n+      HttpUrl httpUrl = HttpUrl.parse(resourceUrl);\n+      if (httpUrl == null) {\n+        log(Log.ERROR, String.format(\"[HTTP] Unable to parse resourceUrl %s\", resourceUrl));\n+      }\n+\n+      final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);\n+      // Don't try a request to remote server if we aren't connected\n+      if (!Mapbox.isConnected() && !host.equals(\"127.0.0.1\") && !host.equals(\"localhost\")) {\n+        throw new NoRouteToHostException(\"No Internet connection available.\");\n+      }\n+\n+      if (host.equals(\"mapbox.com\") || host.endsWith(\".mapbox.com\") || host.equals(\"mapbox.cn\")\n+        || host.endsWith(\".mapbox.cn\")) {\n+        if (httpUrl.querySize() == 0) {\n+          resourceUrl = resourceUrl + \"?\";\n+        } else {\n+          resourceUrl = resourceUrl + \"&\";\n+        }\n+        resourceUrl = resourceUrl + \"events=true\";\n+      }\n+\n+      Request.Builder builder = new Request.Builder()\n+        .url(resourceUrl)\n+        .tag(resourceUrl.toLowerCase(MapboxConstants.MAPBOX_LOCALE))\n+        .addHeader(\"User-Agent\", getUserAgent());\n+      if (etag.length() > 0) {\n+        builder = builder.addHeader(\"If-None-Match\", etag);\n+      } else if (modified.length() > 0) {\n+        builder = builder.addHeader(\"If-Modified-Since\", modified);\n+      }\n+      Request request = builder.build();\n+      call = client.newCall(request);\n+\n+      synchronized (calls) {\n+        calls.put(nativePtr, call);\n+      }\n+\n+      call.enqueue(callback);\n+      Timber.e(\"Requesting resource with size %s for %s\", calls.size(), call.hashCode());\n+    } catch (Exception exception) {\n+      callback.handleFailure(call, exception);\n+    }\n+  }\n+\n+  @Override\n+  public void cancelRequest(long nativePtr) {\n+    synchronized (calls) {\n+      Call call = calls.get(nativePtr);\n+      // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).\n+      if (call != null) {\n+        call.cancel();\n+        calls.delete(nativePtr);\n+      }\n+    }\n+  }\n+\n+  public static void enablePrintRequestUrlOnFailure(boolean enabled) {\n+    logRequestUrl = enabled;\n+  }\n+\n+  public static void enableLog(boolean enabled) {\n+    logEnabled = enabled;\n+  }\n+\n+  public static void setOkHttpClient(OkHttpClient okHttpClient) {\n+    OkHttpRequest.client = okHttpClient;\n+  }\n+\n+  private static class OkHttpCallback implements Callback {\n+\n+    private NativeHttpRequest httpRequest;\n+\n+    OkHttpCallback(NativeHttpRequest httpRequest) {\n+      this.httpRequest = httpRequest;\n+    }\n+\n+    @Override\n+    public void onFailure(@NonNull Call call, @NonNull IOException e) {\n+      handleFailure(call, e);\n+    }\n+\n+    @Override\n+    public void onResponse(@NonNull Call call, @NonNull Response response) {\n+      if (response.isSuccessful()) {\n+        log(Log.VERBOSE, String.format(\"[HTTP] Request was successful (code = %s).\", response.code()));\n+      } else {\n+        // We don't want to call this unsuccessful because a 304 isn't really an error\n+        String message = !TextUtils.isEmpty(response.message()) ? response.message() : \"No additional information\";\n+        log(Log.DEBUG, String.format(\"[HTTP] Request with response code = %s: %s\", response.code(), message));\n+      }\n+\n+      removeCall(call);\n+\n+      ResponseBody responseBody = response.body();\n+      if (responseBody == null) {\n+        log(Log.ERROR, \"[HTTP] Received empty response body\");\n+        return;\n+      }\n+\n+      byte[] body;\n+      try {\n+        body = responseBody.bytes();\n+      } catch (IOException ioException) {\n+        onFailure(call, ioException);\n+        // throw ioException;\n+        return;\n+      } finally {\n+        response.close();\n+      }\n+\n+      httpRequest.onResponse(response.code(),\n+        response.header(\"ETag\"),\n+        response.header(\"Last-Modified\"),\n+        response.header(\"Cache-Control\"),\n+        response.header(\"Expires\"),\n+        response.header(\"Retry-After\"),\n+        response.header(\"x-rate-limit-reset\"),\n+        body);\n+    }\n+\n+    private void handleFailure(Call call, Exception e) {\n+      String errorMessage = e.getMessage() != null ? e.getMessage() : \"Error processing the request\";\n+      int type = getFailureType(e);\n+\n+      if (logEnabled && call != null && call.request() != null) {\n+        String requestUrl = call.request().url().toString();\n+        logFailure(type, errorMessage, requestUrl);\n+      }\n+\n+      removeCall(call);\n+      Timber.e(\"Handle Failure with size %s for %s\", calls.size(), call.hashCode());\n+      httpRequest.handleFailure(type, errorMessage);\n+    }\n+\n+    private void logFailure(int type, String errorMessage, String requestUrl) {\n+      log(type == TEMPORARY_ERROR ? Log.DEBUG : type == CONNECTION_ERROR ? Log.INFO : Log.WARN,\n+        String.format(\n+          \"Request failed due to a %s error: %s %s\",\n+          type == TEMPORARY_ERROR ? \"temporary\" : type == CONNECTION_ERROR ? \"connection\" : \"permanent\",\n+          errorMessage,\n+          logRequestUrl ? requestUrl : \"\"\n+        )\n+      );\n+    }\n+\n+    private int getFailureType(Exception e) {\n+      if ((e instanceof NoRouteToHostException) || (e instanceof UnknownHostException) || (e instanceof SocketException)\n+        || (e instanceof ProtocolException) || (e instanceof SSLException)) {\n+        return CONNECTION_ERROR;\n+      } else if ((e instanceof InterruptedIOException)) {\n+        return TEMPORARY_ERROR;\n+      }\n+      return PERMANENT_ERROR;\n+    }\n+\n+    private void removeCall(Call call) {\n+      synchronized (calls) {\n+        Call currentCall;\n+        for (int i = 0; i < calls.size(); i++) {\n+          long key = calls.keyAt(i);\n+          currentCall = calls.get(key);\n+          if (call.equals(currentCall)) {\n+            calls.delete(key);\n+          }","path":"platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/OkHttpRequest.java","position":212,"original_position":212,"commit_id":"599f37b92d6ffc57d93ba7211295936329a6ea02","original_commit_id":"599f37b92d6ffc57d93ba7211295936329a6ea02","user":{"login":"LukasPaczos","id":16925074,"node_id":"MDQ6VXNlcjE2OTI1MDc0","avatar_url":"https://avatars0.githubusercontent.com/u/16925074?v=4","gravatar_id":"","url":"https://api.github.com/users/LukasPaczos","html_url":"https://github.com/LukasPaczos","followers_url":"https://api.github.com/users/LukasPaczos/followers","following_url":"https://api.github.com/users/LukasPaczos/following{/other_user}","gists_url":"https://api.github.com/users/LukasPaczos/gists{/gist_id}","starred_url":"https://api.github.com/users/LukasPaczos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LukasPaczos/subscriptions","organizations_url":"https://api.github.com/users/LukasPaczos/orgs","repos_url":"https://api.github.com/users/LukasPaczos/repos","events_url":"https://api.github.com/users/LukasPaczos/events{/privacy}","received_events_url":"https://api.github.com/users/LukasPaczos/received_events","type":"User","site_admin":false},"body":"I believe we can safely return here.","created_at":"2018-07-18T15:20:55Z","updated_at":"2018-07-18T15:56:49Z","html_url":"https://github.com/mapbox/mapbox-gl-native/pull/12423#discussion_r203421892","pull_request_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/comments/203421892"},"html":{"href":"https://github.com/mapbox/mapbox-gl-native/pull/12423#discussion_r203421892"},"pull_request":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423"}}},"pull_request":{"url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423","id":202259553,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAyMjU5NTUz","html_url":"https://github.com/mapbox/mapbox-gl-native/pull/12423","diff_url":"https://github.com/mapbox/mapbox-gl-native/pull/12423.diff","patch_url":"https://github.com/mapbox/mapbox-gl-native/pull/12423.patch","issue_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/12423","number":12423,"state":"open","locked":false,"title":"HttpClient configuration","user":{"login":"tobrun","id":2151639,"node_id":"MDQ6VXNlcjIxNTE2Mzk=","avatar_url":"https://avatars0.githubusercontent.com/u/2151639?v=4","gravatar_id":"","url":"https://api.github.com/users/tobrun","html_url":"https://github.com/tobrun","followers_url":"https://api.github.com/users/tobrun/followers","following_url":"https://api.github.com/users/tobrun/following{/other_user}","gists_url":"https://api.github.com/users/tobrun/gists{/gist_id}","starred_url":"https://api.github.com/users/tobrun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tobrun/subscriptions","organizations_url":"https://api.github.com/users/tobrun/orgs","repos_url":"https://api.github.com/users/tobrun/repos","events_url":"https://api.github.com/users/tobrun/events{/privacy}","received_events_url":"https://api.github.com/users/tobrun/received_events","type":"User","site_admin":false},"body":"WIP:\r\n\r\nThis PR allows to exclude the [`okhttp`](http://square.github.io/okhttp/) dependency from our SDK and replace the http client integration with another. In the test app I'm now showcasing this with using [`ion`](https://github.com/koush/ion) instead of `okhttp`.\r\n\r\nNotes:\r\n - I had to disable telemetry completely as I was hitting `NoClassDefFoundError`, stripping out okhttp also removes it from telemetry. We need an additional configuration handling this. \r\n - I had to introduce a collection to manage ongoing requests, with the old system this wasn't necessary but with this static approach we need additional bookkeeping.\r\n\r\nTodo:\r\n  - [ ] revisit naming\r\n  - [ ] add javadoc\r\n  - [ ] fix telemetry integration\r\n  - [ ] remove ion sample integration from testapp\r\n  - [ ] run large scale tests on AWS device farm to detect regressions","created_at":"2018-07-18T13:48:45Z","updated_at":"2018-07-18T15:56:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"aa23ef3953dbf9a0a4ab66bf99ac223fdd77b438","assignee":{"login":"tobrun","id":2151639,"node_id":"MDQ6VXNlcjIxNTE2Mzk=","avatar_url":"https://avatars0.githubusercontent.com/u/2151639?v=4","gravatar_id":"","url":"https://api.github.com/users/tobrun","html_url":"https://github.com/tobrun","followers_url":"https://api.github.com/users/tobrun/followers","following_url":"https://api.github.com/users/tobrun/following{/other_user}","gists_url":"https://api.github.com/users/tobrun/gists{/gist_id}","starred_url":"https://api.github.com/users/tobrun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tobrun/subscriptions","organizations_url":"https://api.github.com/users/tobrun/orgs","repos_url":"https://api.github.com/users/tobrun/repos","events_url":"https://api.github.com/users/tobrun/events{/privacy}","received_events_url":"https://api.github.com/users/tobrun/received_events","type":"User","site_admin":false},"assignees":[{"login":"tobrun","id":2151639,"node_id":"MDQ6VXNlcjIxNTE2Mzk=","avatar_url":"https://avatars0.githubusercontent.com/u/2151639?v=4","gravatar_id":"","url":"https://api.github.com/users/tobrun","html_url":"https://github.com/tobrun","followers_url":"https://api.github.com/users/tobrun/followers","following_url":"https://api.github.com/users/tobrun/following{/other_user}","gists_url":"https://api.github.com/users/tobrun/gists{/gist_id}","starred_url":"https://api.github.com/users/tobrun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tobrun/subscriptions","organizations_url":"https://api.github.com/users/tobrun/orgs","repos_url":"https://api.github.com/users/tobrun/repos","events_url":"https://api.github.com/users/tobrun/events{/privacy}","received_events_url":"https://api.github.com/users/tobrun/received_events","type":"User","site_admin":false}],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":143173729,"node_id":"MDU6TGFiZWwxNDMxNzM3Mjk=","url":"https://api.github.com/repos/mapbox/mapbox-gl-native/labels/Android","name":"Android","color":"000000","default":false}],"milestone":{"url":"https://api.github.com/repos/mapbox/mapbox-gl-native/milestones/119","html_url":"https://github.com/mapbox/mapbox-gl-native/milestone/119","labels_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/milestones/119/labels","id":3483095,"node_id":"MDk6TWlsZXN0b25lMzQ4MzA5NQ==","number":119,"title":"android-v6.4.0","description":null,"creator":{"login":"LukasPaczos","id":16925074,"node_id":"MDQ6VXNlcjE2OTI1MDc0","avatar_url":"https://avatars0.githubusercontent.com/u/16925074?v=4","gravatar_id":"","url":"https://api.github.com/users/LukasPaczos","html_url":"https://github.com/LukasPaczos","followers_url":"https://api.github.com/users/LukasPaczos/followers","following_url":"https://api.github.com/users/LukasPaczos/following{/other_user}","gists_url":"https://api.github.com/users/LukasPaczos/gists{/gist_id}","starred_url":"https://api.github.com/users/LukasPaczos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/LukasPaczos/subscriptions","organizations_url":"https://api.github.com/users/LukasPaczos/orgs","repos_url":"https://api.github.com/users/LukasPaczos/repos","events_url":"https://api.github.com/users/LukasPaczos/events{/privacy}","received_events_url":"https://api.github.com/users/LukasPaczos/received_events","type":"User","site_admin":false},"open_issues":9,"closed_issues":7,"state":"open","created_at":"2018-07-09T14:35:13Z","updated_at":"2018-07-18T13:48:45Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423/commits","review_comments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423/comments","review_comment_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/12423/comments","statuses_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/statuses/599f37b92d6ffc57d93ba7211295936329a6ea02","head":{"label":"mapbox:tvn-configurable-httpclient","ref":"tvn-configurable-httpclient","sha":"599f37b92d6ffc57d93ba7211295936329a6ea02","user":{"login":"mapbox","id":600935,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==","avatar_url":"https://avatars1.githubusercontent.com/u/600935?v=4","gravatar_id":"","url":"https://api.github.com/users/mapbox","html_url":"https://github.com/mapbox","followers_url":"https://api.github.com/users/mapbox/followers","following_url":"https://api.github.com/users/mapbox/following{/other_user}","gists_url":"https://api.github.com/users/mapbox/gists{/gist_id}","starred_url":"https://api.github.com/users/mapbox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapbox/subscriptions","organizations_url":"https://api.github.com/users/mapbox/orgs","repos_url":"https://api.github.com/users/mapbox/repos","events_url":"https://api.github.com/users/mapbox/events{/privacy}","received_events_url":"https://api.github.com/users/mapbox/received_events","type":"Organization","site_admin":false},"repo":{"id":16286131,"node_id":"MDEwOlJlcG9zaXRvcnkxNjI4NjEzMQ==","name":"mapbox-gl-native","full_name":"mapbox/mapbox-gl-native","owner":{"login":"mapbox","id":600935,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==","avatar_url":"https://avatars1.githubusercontent.com/u/600935?v=4","gravatar_id":"","url":"https://api.github.com/users/mapbox","html_url":"https://github.com/mapbox","followers_url":"https://api.github.com/users/mapbox/followers","following_url":"https://api.github.com/users/mapbox/following{/other_user}","gists_url":"https://api.github.com/users/mapbox/gists{/gist_id}","starred_url":"https://api.github.com/users/mapbox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapbox/subscriptions","organizations_url":"https://api.github.com/users/mapbox/orgs","repos_url":"https://api.github.com/users/mapbox/repos","events_url":"https://api.github.com/users/mapbox/events{/privacy}","received_events_url":"https://api.github.com/users/mapbox/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mapbox/mapbox-gl-native","description":"Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL","fork":false,"url":"https://api.github.com/repos/mapbox/mapbox-gl-native","forks_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/forks","keys_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/teams","hooks_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/hooks","issue_events_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/events{/number}","events_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/events","assignees_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/assignees{/user}","branches_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/branches{/branch}","tags_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/tags","blobs_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/refs{/sha}","trees_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/statuses/{sha}","languages_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/languages","stargazers_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/stargazers","contributors_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/contributors","subscribers_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/subscribers","subscription_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/subscription","commits_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/commits{/sha}","git_commits_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/commits{/sha}","comments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/comments{/number}","issue_comment_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/comments{/number}","contents_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/contents/{+path}","compare_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/merges","archive_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/downloads","issues_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues{/number}","pulls_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls{/number}","milestones_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/milestones{/number}","notifications_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/labels{/name}","releases_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/releases{/id}","deployments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/deployments","created_at":"2014-01-27T17:14:48Z","updated_at":"2018-07-18T15:35:33Z","pushed_at":"2018-07-18T15:45:44Z","git_url":"git://github.com/mapbox/mapbox-gl-native.git","ssh_url":"git@github.com:mapbox/mapbox-gl-native.git","clone_url":"https://github.com/mapbox/mapbox-gl-native.git","svn_url":"https://github.com/mapbox/mapbox-gl-native","homepage":"https://mapbox.com/mobile","size":207258,"stargazers_count":2701,"watchers_count":2701,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":855,"mirror_url":null,"archived":false,"open_issues_count":748,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":855,"open_issues":748,"watchers":2701,"default_branch":"master"}},"base":{"label":"mapbox:master","ref":"master","sha":"c29740e73fafaeeac880b4dc451256ab4be78013","user":{"login":"mapbox","id":600935,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==","avatar_url":"https://avatars1.githubusercontent.com/u/600935?v=4","gravatar_id":"","url":"https://api.github.com/users/mapbox","html_url":"https://github.com/mapbox","followers_url":"https://api.github.com/users/mapbox/followers","following_url":"https://api.github.com/users/mapbox/following{/other_user}","gists_url":"https://api.github.com/users/mapbox/gists{/gist_id}","starred_url":"https://api.github.com/users/mapbox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapbox/subscriptions","organizations_url":"https://api.github.com/users/mapbox/orgs","repos_url":"https://api.github.com/users/mapbox/repos","events_url":"https://api.github.com/users/mapbox/events{/privacy}","received_events_url":"https://api.github.com/users/mapbox/received_events","type":"Organization","site_admin":false},"repo":{"id":16286131,"node_id":"MDEwOlJlcG9zaXRvcnkxNjI4NjEzMQ==","name":"mapbox-gl-native","full_name":"mapbox/mapbox-gl-native","owner":{"login":"mapbox","id":600935,"node_id":"MDEyOk9yZ2FuaXphdGlvbjYwMDkzNQ==","avatar_url":"https://avatars1.githubusercontent.com/u/600935?v=4","gravatar_id":"","url":"https://api.github.com/users/mapbox","html_url":"https://github.com/mapbox","followers_url":"https://api.github.com/users/mapbox/followers","following_url":"https://api.github.com/users/mapbox/following{/other_user}","gists_url":"https://api.github.com/users/mapbox/gists{/gist_id}","starred_url":"https://api.github.com/users/mapbox/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mapbox/subscriptions","organizations_url":"https://api.github.com/users/mapbox/orgs","repos_url":"https://api.github.com/users/mapbox/repos","events_url":"https://api.github.com/users/mapbox/events{/privacy}","received_events_url":"https://api.github.com/users/mapbox/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mapbox/mapbox-gl-native","description":"Interactive, thoroughly customizable maps in native Android, iOS, macOS, Node.js, and Qt applications, powered by vector tiles and OpenGL","fork":false,"url":"https://api.github.com/repos/mapbox/mapbox-gl-native","forks_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/forks","keys_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/teams","hooks_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/hooks","issue_events_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/events{/number}","events_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/events","assignees_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/assignees{/user}","branches_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/branches{/branch}","tags_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/tags","blobs_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/refs{/sha}","trees_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/statuses/{sha}","languages_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/languages","stargazers_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/stargazers","contributors_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/contributors","subscribers_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/subscribers","subscription_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/subscription","commits_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/commits{/sha}","git_commits_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/git/commits{/sha}","comments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/comments{/number}","issue_comment_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/comments{/number}","contents_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/contents/{+path}","compare_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/merges","archive_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/downloads","issues_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues{/number}","pulls_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls{/number}","milestones_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/milestones{/number}","notifications_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/labels{/name}","releases_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/releases{/id}","deployments_url":"https://api.github.com/repos/mapbox/mapbox-gl-native/deployments","created_at":"2014-01-27T17:14:48Z","updated_at":"2018-07-18T15:35:33Z","pushed_at":"2018-07-18T15:45:44Z","git_url":"git://github.com/mapbox/mapbox-gl-native.git","ssh_url":"git@github.com:mapbox/mapbox-gl-native.git","clone_url":"https://github.com/mapbox/mapbox-gl-native.git","svn_url":"https://github.com/mapbox/mapbox-gl-native","homepage":"https://mapbox.com/mobile","size":207258,"stargazers_count":2701,"watchers_count":2701,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":855,"mirror_url":null,"archived":false,"open_issues_count":748,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":855,"open_issues":748,"watchers":2701,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423"},"html":{"href":"https://github.com/mapbox/mapbox-gl-native/pull/12423"},"issue":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/12423"},"comments":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/issues/12423/comments"},"review_comments":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423/comments"},"review_comment":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/pulls/12423/commits"},"statuses":{"href":"https://api.github.com/repos/mapbox/mapbox-gl-native/statuses/599f37b92d6ffc57d93ba7211295936329a6ea02"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"LukasPaczos"}}