Avoid OAuth with REST and RPC calls and static resources

When Gerrit UX is making REST API calls to the backend
by providing both an GerritAccount cookie and
a X-GERRIT-AUTH HTTP Header, the call can be safely
propagate to Gerrit for validation without having to
necessarily re-create a new GerritOAuth cookie.

Gerrit UX is unable anyway to complete the GitHub
OAuth handshake, there is no value then in getting
the calls redirected to GitHub as it would just break
the user interface.

Change-Id: Ie1566364be6eb647609971b88e2a30c78e012afe
diff --git a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
index 3d91df5..adc5e58 100644
--- a/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
+++ b/github-oauth/src/main/java/com/googlesource/gerrit/plugins/github/oauth/OAuthFilter.java
@@ -14,6 +14,8 @@
 package com.googlesource.gerrit.plugins.github.oauth;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 import javax.servlet.Filter;
@@ -24,9 +26,12 @@
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.commons.lang.StringUtils;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.Sets;
 import com.google.gerrit.httpd.GitOverHttpServlet;
+import com.google.gerrit.httpd.XGerritAuth;
 import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.Singleton;
@@ -37,13 +42,16 @@
       .getLogger(OAuthFilter.class);
   private static Pattern GIT_HTTP_REQUEST_PATTERN = Pattern
       .compile(GitOverHttpServlet.URL_REGEX);
+  private static final Set<String> GERRIT_STATIC_RESOURCES_EXTS = Sets
+      .newHashSet(Arrays.asList("css", "png", "jpg", "gif", "woff", "otf",
+          "ttf", "map", "js", "swf", "txt"));
 
   private final GitHubOAuthConfig config;
   private final OAuthGitFilter gitFilter;
   private final OAuthWebFilter webFilter;
 
   @Inject
-  public OAuthFilter(GitHubOAuthConfig config, 
+  public OAuthFilter(GitHubOAuthConfig config,
       OAuthWebFilter webFilter, Injector injector) {
     this.config = config;
     this.webFilter = webFilter;
@@ -60,13 +68,15 @@
   @Override
   public void doFilter(ServletRequest request, ServletResponse response,
       FilterChain chain) throws IOException, ServletException {
+    HttpServletRequest httpRequest = (HttpServletRequest) request;
 
-    if (!config.enabled) {
+    if (!config.enabled || isStaticResource(httpRequest)
+        || isRpcCall(httpRequest) || isAuthenticatedRestCall(httpRequest)) {
       chain.doFilter(request, response);
       return;
     }
 
-    String requestUrl = ((HttpServletRequest) request).getRequestURI();
+    String requestUrl = httpRequest.getRequestURI();
     if (GIT_HTTP_REQUEST_PATTERN.matcher(requestUrl).matches()) {
       gitFilter.doFilter(request, response, chain);
     } else {
@@ -74,6 +84,25 @@
     }
   }
 
+  private boolean isAuthenticatedRestCall(HttpServletRequest httpRequest) {
+    return !StringUtils.isEmpty(httpRequest
+        .getHeader(XGerritAuth.X_GERRIT_AUTH));
+  }
+
+  private boolean isStaticResource(HttpServletRequest httpRequest) {
+    String pathExt =
+        StringUtils.substringAfterLast(httpRequest.getRequestURI(), ".");
+    if (StringUtils.isEmpty(pathExt)) {
+      return false;
+    }
+
+    return GERRIT_STATIC_RESOURCES_EXTS.contains(pathExt.toLowerCase());
+  }
+
+  private boolean isRpcCall(HttpServletRequest httpRequest) {
+    return httpRequest.getRequestURI().indexOf("/rpc/") >= 0;
+  }
+
   @Override
   public void destroy() {
     log.info("Destroy");