You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by vb...@apache.org on 2014/02/12 16:18:38 UTC

git commit: AMBARI-4628. Provide ability to forward request headers for Pass Through API.(vbrodetskyi)

Updated Branches:
  refs/heads/trunk 8b90b39bf -> 9d6e78168


AMBARI-4628. Provide ability to forward request headers for Pass Through API.(vbrodetskyi)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/9d6e7816
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/9d6e7816
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/9d6e7816

Branch: refs/heads/trunk
Commit: 9d6e78168fe4d3c2e873a9390cd4d61166ed4e8e
Parents: 8b90b39
Author: Vitaly Brodetskyi <vb...@hortonworks.com>
Authored: Wed Feb 12 17:17:58 2014 +0200
Committer: Vitaly Brodetskyi <vb...@hortonworks.com>
Committed: Wed Feb 12 17:17:58 2014 +0200

----------------------------------------------------------------------
 .../controller/internal/URLStreamProvider.java  | 19 ++++-
 .../ambari/server/proxy/ProxyService.java       | 26 +++++--
 .../ambari/server/proxy/ProxyServiceTest.java   | 78 +++++++++++++++++---
 3 files changed, 101 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/9d6e7816/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/URLStreamProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/URLStreamProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/URLStreamProvider.java
index 6b5681c..be95221 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/URLStreamProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/URLStreamProvider.java
@@ -28,6 +28,8 @@ import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLConnection;
 import java.security.KeyStore;
+import java.util.List;
+import java.util.Map;
 import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
 import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED;
 
@@ -49,6 +51,7 @@ public class URLStreamProvider implements StreamProvider {
   private static final String COOKIE = "Cookie";
   private static final String WWW_AUTHENTICATE = "WWW-Authenticate";
   private static final String NEGOTIATE = "Negotiate";
+  private static final String CONTENT_TYPE_HEADER_PARAMETER = "Content-Type";
   private static Log LOG = LogFactory.getLog(URLStreamProvider.class);
 
   private final int connTimeout;
@@ -81,10 +84,11 @@ public class URLStreamProvider implements StreamProvider {
   
   @Override
   public InputStream readFrom(String spec, String requestMethod, String params) throws IOException {
-    return processURL(spec, requestMethod, params, APPLICATION_FORM_URLENCODED).getInputStream();
+    return processURL(spec, requestMethod, params, null).getInputStream();
   }
 
-  public HttpURLConnection processURL(String spec, String requestMethod, Object params, String mediaType) throws IOException {
+  public HttpURLConnection processURL(String spec, String requestMethod, Object params, Map<String, List<String>> headers)
+          throws IOException {
     if (LOG.isDebugEnabled()) {
       LOG.debug("readFrom spec:" + spec);
     }
@@ -102,11 +106,18 @@ public class URLStreamProvider implements StreamProvider {
     connection.setReadTimeout(readTimeout);
     connection.setDoOutput(true);
     connection.setRequestMethod(requestMethod);
-    connection.setRequestProperty("Content-Type", mediaType);
+
+    if (headers != null) {
+      for (Map.Entry<String, List<String>> entry: headers.entrySet()) {
+        String paramValue = entry.getValue().toString();
+        connection.setRequestProperty(entry.getKey(), paramValue.substring(1, paramValue.length() - 1));
+      }
+    }
 
     if (params != null) {
       String strParams;
-      if (mediaType.equals(APPLICATION_JSON)) {
+      if (headers != null && headers.containsKey(CONTENT_TYPE_HEADER_PARAMETER) &&
+              headers.get(CONTENT_TYPE_HEADER_PARAMETER).toString().indexOf(APPLICATION_JSON) != -1) {
         strParams = new Gson().toJson(params);
       } else {
         strParams = (String)params;

http://git-wip-us.apache.org/repos/asf/ambari/blob/9d6e7816/ambari-server/src/main/java/org/apache/ambari/server/proxy/ProxyService.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/proxy/ProxyService.java b/ambari-server/src/main/java/org/apache/ambari/server/proxy/ProxyService.java
index 9f7f108..3ed0b8c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/proxy/ProxyService.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/proxy/ProxyService.java
@@ -39,8 +39,9 @@ import javax.ws.rs.core.UriInfo;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
-import java.util.List;
 import java.util.Map;
+import java.util.List;
+import java.util.HashMap;
 
 @Path("/")
 public class ProxyService {
@@ -54,38 +55,39 @@ public class ProxyService {
   private static final String REQUEST_TYPE_PUT = "PUT";
   private static final String REQUEST_TYPE_DELETE = "DELETE";
   private static final String QUERY_PARAMETER_URL = "url";
+  private static final String AMBARI_PROXY_PREFIX = "AmbariProxy-";
   private static final String ERROR_PROCESSING_URL = "Error occurred during processing URL ";
 
   private final static Logger LOG = LoggerFactory.getLogger(ProxyService.class);
 
   @GET
   public Response processGetRequestForwarding(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(REQUEST_TYPE_GET, ui, null, APPLICATION_FORM_URLENCODED);
+    return handleRequest(REQUEST_TYPE_GET, ui, null, headers);
   }
 
   @POST
   public Response processPostRequestForwarding(Object body, @Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(REQUEST_TYPE_POST, ui, body, headers.getMediaType().toString());
+    return handleRequest(REQUEST_TYPE_POST, ui, body, headers);
   }
 
   @PUT
   public Response processPutRequestForwarding(Object body, @Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(REQUEST_TYPE_PUT, ui, body, headers.getMediaType().toString());
+    return handleRequest(REQUEST_TYPE_PUT, ui, body, headers);
   }
 
   @DELETE
   public Response processDeleteRequestForwarding(@Context HttpHeaders headers, @Context UriInfo ui) {
-    return handleRequest(REQUEST_TYPE_DELETE, ui, null, APPLICATION_FORM_URLENCODED);
+    return handleRequest(REQUEST_TYPE_DELETE, ui, null, headers);
   }
 
-  private Response handleRequest(String requestType, UriInfo ui, Object body, String mediaType) {
+  private Response handleRequest(String requestType, UriInfo ui, Object body, HttpHeaders headers) {
     URLStreamProvider urlStreamProvider = new URLStreamProvider(REPO_URL_CONNECT_TIMEOUT,
                                                 REPO_URL_READ_TIMEOUT, null, null, null);
     List<String> urlsToForward = ui.getQueryParameters().get(QUERY_PARAMETER_URL);
     if (!urlsToForward.isEmpty()) {
       String url = urlsToForward.get(0);
       try {
-        HttpURLConnection connection = urlStreamProvider.processURL(url, requestType, body, mediaType);
+        HttpURLConnection connection = urlStreamProvider.processURL(url, requestType, body, getHeaderParamsToForward(headers));
         int responseCode = connection.getResponseCode();
         if (responseCode >= HTTP_ERROR_RANGE_START) {
           throw new WebApplicationException(connection.getResponseCode());
@@ -105,4 +107,14 @@ public class ProxyService {
     return null;
   }
 
+  private Map<String, List<String>> getHeaderParamsToForward(HttpHeaders headers) {
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
+    for (String paramName: headers.getRequestHeaders().keySet()) {
+      if (paramName.startsWith(AMBARI_PROXY_PREFIX)) {
+        headerParamsToForward.put(paramName.replaceAll(AMBARI_PROXY_PREFIX,""), headers.getRequestHeader(paramName));
+      }
+    }
+    return headerParamsToForward;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/9d6e7816/ambari-server/src/test/java/org/apache/ambari/server/proxy/ProxyServiceTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/proxy/ProxyServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/proxy/ProxyServiceTest.java
index 80c5c7d..1a9a176 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/proxy/ProxyServiceTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/proxy/ProxyServiceTest.java
@@ -43,8 +43,10 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.HttpURLConnection;
 import java.util.Map;
-import java.util.List;
+import java.util.LinkedList;
+import java.util.HashMap;
 import java.util.Collections;
+import java.util.List;
 
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.expect;
@@ -60,13 +62,22 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
     Response responseMock = createMock(ResponseImpl.class);
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
     InputStream is = new ByteArrayInputStream("test".getBytes());
     PowerMock.mockStatic(Response.class);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
-    expect(streamProviderMock.processURL("testurl", "GET", null, APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "GET", null, headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(200);
     expect(urlConnectionMock.getContentType()).andReturn("text/plain");
     expect(urlConnectionMock.getInputStream()).andReturn(is);
@@ -76,7 +87,7 @@ class ProxyServiceTest extends BaseServiceTest {
     expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
     expect(responseBuilderMock.build()).andReturn(responseMock);
     PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock);
-    replay(getUriInfo(), urlConnectionMock);
+    replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
     Response resultForGetRequest = ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
     assertSame(resultForGetRequest, responseMock);
   }
@@ -87,14 +98,23 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
     Response responseMock = createMock(ResponseImpl.class);
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
     InputStream is = new ByteArrayInputStream("test".getBytes());
     PowerMock.mockStatic(Response.class);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
     expect(getHttpHeaders().getMediaType()).andReturn(APPLICATION_FORM_URLENCODED_TYPE);
-    expect(streamProviderMock.processURL("testurl", "POST", "testbody", APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "POST", "testbody", headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(200);
     expect(urlConnectionMock.getContentType()).andReturn("text/plain");
     expect(urlConnectionMock.getInputStream()).andReturn(is);
@@ -115,14 +135,23 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
     Response responseMock = createMock(ResponseImpl.class);
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
     InputStream is = new ByteArrayInputStream("test".getBytes());
     PowerMock.mockStatic(Response.class);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
     expect(getHttpHeaders().getMediaType()).andReturn(APPLICATION_FORM_URLENCODED_TYPE);
-    expect(streamProviderMock.processURL("testurl", "PUT", "testbody", APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "PUT", "testbody", headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(200);
     expect(urlConnectionMock.getContentType()).andReturn("text/plain");
     expect(urlConnectionMock.getInputStream()).andReturn(is);
@@ -143,13 +172,22 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
     Response responseMock = createMock(ResponseImpl.class);
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
     InputStream is = new ByteArrayInputStream("test".getBytes());
     PowerMock.mockStatic(Response.class);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
-    expect(streamProviderMock.processURL("testurl", "DELETE", null, APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "DELETE", null, headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(200);
     expect(urlConnectionMock.getContentType()).andReturn("text/plain");
     expect(urlConnectionMock.getInputStream()).andReturn(is);
@@ -159,7 +197,7 @@ class ProxyServiceTest extends BaseServiceTest {
     expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
     expect(responseBuilderMock.build()).andReturn(responseMock);
     PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock);
-    replay(getUriInfo(), urlConnectionMock);
+    replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
     Response resultForDeleteRequest = ps.processDeleteRequestForwarding(getHttpHeaders(), getUriInfo());
     assertSame(resultForDeleteRequest, responseMock);
   }
@@ -170,13 +208,22 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
-    expect(streamProviderMock.processURL("testurl", "GET", null, APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "GET", null, headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(405).times(2);
     PowerMock.expectNew(URLStreamProvider.class, 3000, 1000, null, null, null).andReturn(streamProviderMock);
     PowerMock.replay(streamProviderMock, URLStreamProvider.class);
-    replay(getUriInfo(), urlConnectionMock);
+    replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
     ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
   }
 
@@ -186,13 +233,22 @@ class ProxyServiceTest extends BaseServiceTest {
     URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
     HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
     MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
+    MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
+    Map<String, List<String>> headerParamsToForward = new HashMap<String, List<String>>();
     Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
     Response responseMock = createMock(ResponseImpl.class);
     queryParams.add("url","testurl");
+    headerParams.add("AmbariProxy-User-Remote","testuser");
+    headerParams.add("Content-Type","testtype");
+    List<String> userRemoteParams = new LinkedList<String>();
+    userRemoteParams.add("testuser");
+    headerParamsToForward.put("User-Remote", userRemoteParams);
     Map map = new Gson().fromJson(new InputStreamReader(new ByteArrayInputStream("{ \"test\":\"test\" }".getBytes())), Map.class);
     PowerMock.mockStatic(Response.class);
+    expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
+    expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
     expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
-    expect(streamProviderMock.processURL("testurl", "GET", null, APPLICATION_FORM_URLENCODED)).andReturn(urlConnectionMock);
+    expect(streamProviderMock.processURL("testurl", "GET", null, headerParamsToForward)).andReturn(urlConnectionMock);
     expect(urlConnectionMock.getResponseCode()).andReturn(200);
     expect(urlConnectionMock.getContentType()).andReturn("application/json");
     expect(urlConnectionMock.getInputStream()).andReturn(new ByteArrayInputStream("{ \"test\":\"test\" }".getBytes()));
@@ -202,7 +258,7 @@ class ProxyServiceTest extends BaseServiceTest {
     expect(responseBuilderMock.type("application/json")).andReturn(responseBuilderMock);
     expect(responseBuilderMock.build()).andReturn(responseMock);
     PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock);
-    replay(getUriInfo(), urlConnectionMock);
+    replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
     Response resultForGetRequest = ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
     assertSame(resultForGetRequest, responseMock);
   }