/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ambari.server.proxy;
import static javax.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED_TYPE;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.assertSame;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import org.apache.ambari.server.api.services.BaseServiceTest;
import org.apache.ambari.server.controller.internal.URLStreamProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.google.gson.Gson;
import com.sun.jersey.core.spi.factory.ResponseBuilderImpl;
import com.sun.jersey.core.spi.factory.ResponseImpl;
import com.sun.jersey.core.util.MultivaluedMapImpl;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ ProxyServiceTest.class, ProxyService.class, URLStreamProvider.class, Response.class,
ResponseBuilderImpl.class, URI.class })
public class ProxyServiceTest extends BaseServiceTest {
@Test
public void testProxyGetRequest() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uriMock = PowerMock.createMock(URI.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
Response responseMock = createMock(ResponseImpl.class);
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
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().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(streamProviderMock.processURL("testurl", "GET", (InputStream) null, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getInputStream()).andReturn(is);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(Response.status(200)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(is)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock, uriMock, URI.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForGetRequest = ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
assertSame(resultForGetRequest, responseMock);
}
@Test
public void testProxyPostRequest() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uriMock = PowerMock.createMock(URI.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
Response responseMock = createMock(ResponseImpl.class);
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
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().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(getHttpHeaders().getMediaType()).andReturn(APPLICATION_FORM_URLENCODED_TYPE);
expect(streamProviderMock.processURL("testurl", "POST", is, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getInputStream()).andReturn(is);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(Response.status(200)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(is)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock, uriMock, URI.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForPostRequest = ps.processPostRequestForwarding(is, getHttpHeaders(), getUriInfo());
assertSame(resultForPostRequest, responseMock);
}
@Test
public void testProxyPutRequest() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uriMock = PowerMock.createMock(URI.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
Response responseMock = createMock(ResponseImpl.class);
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
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().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(getHttpHeaders().getMediaType()).andReturn(APPLICATION_FORM_URLENCODED_TYPE);
expect(streamProviderMock.processURL("testurl", "PUT", is, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getInputStream()).andReturn(is);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(Response.status(200)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(is)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock, uriMock, URI.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForPutRequest = ps.processPutRequestForwarding(is, getHttpHeaders(), getUriInfo());
assertSame(resultForPutRequest, responseMock);
}
@Test
public void testProxyDeleteRequest() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uriMock = PowerMock.createMock(URI.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
Response responseMock = createMock(ResponseImpl.class);
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
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().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(streamProviderMock.processURL("testurl", "DELETE", (InputStream) null, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getInputStream()).andReturn(is);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(Response.status(200)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(is)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock, uriMock, URI.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForDeleteRequest = ps.processDeleteRequestForwarding(getHttpHeaders(), getUriInfo());
assertSame(resultForDeleteRequest, responseMock);
}
@Test
public void testResponseWithError() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
URI uriMock = PowerMock.createMock(URI.class);
Response responseMock = createMock(ResponseImpl.class);
InputStream es = new ByteArrayInputStream("error".getBytes());
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
userRemoteParams.add("testuser");
headerParamsToForward.put("User-Remote", userRemoteParams);
PowerMock.mockStatic(Response.class);
expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
expect(getUriInfo().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(streamProviderMock.processURL("testurl", "GET", (InputStream) null, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(400).times(2);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getErrorStream()).andReturn(es);
expect(Response.status(400)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(es)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("text/plain")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, uriMock, URI.class, Response.class, responseBuilderMock);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForErrorRequest = ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
assertSame(resultForErrorRequest, responseMock);
}
@Test
public void testProxyWithJSONResponse() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uriMock = PowerMock.createMock(URI.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
Response.ResponseBuilder responseBuilderMock = PowerMock.createMock(ResponseBuilderImpl.class);
Response responseMock = createMock(ResponseImpl.class);
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
List<String> userRemoteParams = new LinkedList<>();
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().getRequestUri()).andReturn(uriMock);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(uriMock.getQuery()).andReturn("url=testurl");
expect(streamProviderMock.processURL("testurl", "GET", (InputStream) null, headerParamsToForward)).andReturn(urlConnectionMock);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("application/json");
expect(urlConnectionMock.getInputStream()).andReturn(new ByteArrayInputStream("{ \"test\":\"test\" }".getBytes()));
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(Response.status(200)).andReturn(responseBuilderMock);
expect(responseBuilderMock.entity(map)).andReturn(responseBuilderMock);
expect(responseBuilderMock.type("application/json")).andReturn(responseBuilderMock);
expect(responseBuilderMock.build()).andReturn(responseMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class, Response.class, responseBuilderMock, uriMock, URI.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
Response resultForGetRequest = ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
assertSame(resultForGetRequest, responseMock);
}
@Test
public void testEscapedURL() throws Exception {
ProxyService ps = new ProxyService();
URLStreamProvider streamProviderMock = PowerMock.createNiceMock(URLStreamProvider.class);
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl();
MultivaluedMap<String, String> headerParams = new MultivaluedMapImpl();
HttpURLConnection urlConnectionMock = createMock(HttpURLConnection.class);
URI uri = UriBuilder.fromUri("http://dev01.hortonworks.com:8080/proxy?url=http%3a%2f%2fserver%3a8188%2fws%2fv1%2f" +
"timeline%2fHIVE_QUERY_ID%3ffields=events%2cprimaryfilters%26limit=10%26primaryFilter=user%3ahiveuser1").build();
Map<String, List<String>> headerParamsToForward = new HashMap<>();
InputStream is = new ByteArrayInputStream("test".getBytes());
List<String> userRemoteParams = new LinkedList<>();
userRemoteParams.add("testuser");
headerParams.add("AmbariProxy-User-Remote","testuser");
headerParams.add("Content-Type","testtype");
headerParamsToForward.put("User-Remote", userRemoteParams);
expect(getHttpHeaders().getRequestHeaders()).andReturn(headerParams);
expect(getHttpHeaders().getRequestHeader("AmbariProxy-User-Remote")).andReturn(userRemoteParams);
expect(getUriInfo().getRequestUri()).andReturn(uri);
expect(getUriInfo().getQueryParameters()).andReturn(queryParams);
expect(urlConnectionMock.getResponseCode()).andReturn(200);
expect(urlConnectionMock.getContentType()).andReturn("text/plain");
expect(urlConnectionMock.getInputStream()).andReturn(is);
PowerMock.expectNew(URLStreamProvider.class, 20000, 15000, null, null, null).andReturn(streamProviderMock);
expect(streamProviderMock.processURL("http://server:8188/ws/v1/timeline/HIVE_QUERY_ID?fields=events,primary" +
"filters&limit=10&primaryFilter=user:hiveuser1", "GET", (InputStream) null, headerParamsToForward)).andReturn(urlConnectionMock);
PowerMock.replay(streamProviderMock, URLStreamProvider.class);
replay(getUriInfo(), urlConnectionMock, getHttpHeaders());
ps.processGetRequestForwarding(getHttpHeaders(),getUriInfo());
}
@Override
public List<ServiceTestInvocation> getTestInvocations() throws Exception {
return Collections.emptyList();
}
}