/*
* 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.shindig.gadgets.servlet;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.StringUtils;
import org.apache.shindig.common.uri.Uri;
import org.apache.shindig.config.AbstractContainerConfig;
import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.gadgets.http.HttpRequest;
import org.apache.shindig.gadgets.http.HttpResponse;
import org.apache.shindig.gadgets.http.HttpResponseBuilder;
import org.apache.shindig.gadgets.rewrite.CaptureRewriter;
import org.apache.shindig.gadgets.rewrite.DefaultResponseRewriterRegistry;
import org.apache.shindig.gadgets.rewrite.ResponseRewriter;
import org.apache.shindig.gadgets.uri.AccelUriManager;
import org.apache.shindig.gadgets.uri.DefaultAccelUriManager;
import org.apache.shindig.gadgets.uri.DefaultProxyUriManager;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.Before;
import org.junit.Test;
import javax.servlet.ServletInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Vector;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.expect;
public class HtmlAccelServletTest extends ServletTestFixture {
private static class FakeContainerConfig extends AbstractContainerConfig {
protected final Map<String, Object> data = ImmutableMap.<String, Object>builder()
.put(AccelUriManager.PROXY_HOST_PARAM, "apache.org")
.put(AccelUriManager.PROXY_PATH_PARAM, "/gadgets/accel")
.build();
@Override
public Object getProperty(String container, String name) {
return data.get(name);
}
}
private static class FakeCaptureRewriter extends CaptureRewriter {
String contentToRewrite;
public void setContentToRewrite(String s) {
contentToRewrite = s;
}
@Override
public void rewrite(HttpRequest request, HttpResponseBuilder original) {
super.rewrite(request, original);
if (!StringUtils.isEmpty(contentToRewrite)) {
original.setResponse(contentToRewrite.getBytes());
}
}
}
private static final String REWRITE_CONTENT = "working rewrite";
private static final String SERVLET = "/gadgets/accel";
private HtmlAccelServlet servlet;
@Before
public void setUp() throws Exception {
ContainerConfig config = new FakeContainerConfig();
AccelUriManager accelUriManager = new DefaultAccelUriManager(
config, new DefaultProxyUriManager(config, null));
rewriter = new FakeCaptureRewriter();
rewriterRegistry = new DefaultResponseRewriterRegistry(
Arrays.<ResponseRewriter>asList(rewriter), null);
servlet = new HtmlAccelServlet();
servlet.setHandler(new AccelHandler(pipeline, rewriterRegistry,
accelUriManager, true));
}
private void expectRequest(String extraPath, String url) {
expect(request.getMethod()).andReturn("GET").anyTimes();
expect(request.getServletPath()).andReturn(SERVLET).anyTimes();
expect(request.getScheme()).andReturn("http").anyTimes();
expect(request.getServerName()).andReturn("apache.org").anyTimes();
expect(request.getServerPort()).andReturn(-1).anyTimes();
expect(request.getRequestURI()).andReturn(SERVLET + extraPath).anyTimes();
expect(request.getRequestURL())
.andReturn(new StringBuffer("apache.org" + SERVLET + extraPath))
.anyTimes();
String queryParams = (url == null ? "" : "url=" + url + "&container=accel"
+ "&gadget=test");
expect(request.getQueryString()).andReturn(queryParams).anyTimes();
Vector<String> headerNames = new Vector<String>();
expect(request.getHeaderNames()).andReturn(headerNames.elements());
}
private void expectPostRequest(String extraPath, String url,
final String data)
throws IOException {
expect(request.getMethod()).andReturn("POST").anyTimes();
expect(request.getServletPath()).andReturn(SERVLET).anyTimes();
expect(request.getScheme()).andReturn("http").anyTimes();
expect(request.getServerName()).andReturn("apache.org").anyTimes();
expect(request.getServerPort()).andReturn(-1).anyTimes();
expect(request.getRequestURI()).andReturn(SERVLET + extraPath).anyTimes();
expect(request.getRequestURL())
.andReturn(new StringBuffer("apache.org" + SERVLET + extraPath))
.anyTimes();
String queryParams = (url == null ? "" : "url=" + url + "&container=accel"
+ "&gadget=test");
expect(request.getQueryString()).andReturn(queryParams).anyTimes();
ServletInputStream inputStream = mock(ServletInputStream.class);
expect(request.getInputStream()).andReturn(inputStream);
expect(inputStream.read((byte[]) EasyMock.anyObject()))
.andAnswer(new IAnswer<Integer>() {
public Integer answer() throws Throwable {
byte[] byteArray = (byte[]) EasyMock.getCurrentArguments()[0];
System.arraycopy(data.getBytes(), 0, byteArray, 0, data.length());
return data.length();
}
});
expect(inputStream.read((byte[]) EasyMock.anyObject()))
.andReturn(-1);
Vector<String> headerNames = new Vector<String>();
expect(request.getHeaderNames()).andReturn(headerNames.elements());
}
@Test
public void testHtmlAccelNoData() throws Exception {
String url = "http://example.org/data.html";
HttpRequest req = new HttpRequest(Uri.parse(url));
expect(pipeline.execute(req)).andReturn(null).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(AccelHandler.ERROR_FETCHING_DATA,
recorder.getResponseAsString());
assertEquals(404, recorder.getHttpStatusCode());
}
@Test
public void testHtmlAccelRewriteSimple() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>Hello World</body></html>";
((FakeCaptureRewriter) rewriter).setContentToRewrite(REWRITE_CONTENT);
HttpRequest req = new HttpRequest(Uri.parse(url));
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.setHttpStatusCode(200)
.create();
expect(pipeline.execute(req)).andReturn(resp).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(REWRITE_CONTENT, recorder.getResponseAsString());
assertEquals(200, recorder.getHttpStatusCode());
assertTrue(rewriter.responseWasRewritten());
}
@Test
public void testHtmlAccelRewriteDoesNotFollowRedirects() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>Moved to new page</body></html>";
String redirectLocation = "http://example-redirected.org/data.html";
((FakeCaptureRewriter) rewriter).setContentToRewrite(data);
HttpRequest req = new HttpRequest(Uri.parse(url));
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.setHeader("Location", redirectLocation)
.setHttpStatusCode(302)
.create();
expect(pipeline.execute(req)).andReturn(resp).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(data, recorder.getResponseAsString());
assertEquals(redirectLocation, recorder.getHeader("Location"));
assertEquals(302, recorder.getHttpStatusCode());
assertTrue(rewriter.responseWasRewritten());
}
@Test
public void testHtmlAccelReturnsOriginal404MessageAndCode() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>This is error page</body></html>";
((FakeCaptureRewriter) rewriter).setContentToRewrite(REWRITE_CONTENT);
HttpRequest req = new HttpRequest(Uri.parse(url));
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.setHttpStatusCode(404)
.create();
expect(pipeline.execute(req)).andReturn(resp).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(data, recorder.getResponseAsString());
assertEquals(404, recorder.getHttpStatusCode());
assertFalse(rewriter.responseWasRewritten());
}
@Test
public void testHtmlAccelRewriteInternalError() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>This is error page</body></html>";
((FakeCaptureRewriter) rewriter).setContentToRewrite(data);
HttpRequest req = new HttpRequest(Uri.parse(url));
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.setHttpStatusCode(500)
.create();
expect(pipeline.execute(req)).andReturn(resp).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(data, recorder.getResponseAsString());
assertEquals(502, recorder.getHttpStatusCode());
assertFalse(rewriter.responseWasRewritten());
}
@Test
public void testHtmlAccelHandlesPost() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>This is error page</body></html>";
((FakeCaptureRewriter) rewriter).setContentToRewrite(data);
Capture<HttpRequest> req = new Capture<HttpRequest>();
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.create();
expect(pipeline.execute(capture(req))).andReturn(resp).once();
expectPostRequest("", url, "hello=world");
replay();
servlet.doPost(request, recorder);
verify();
assertEquals(data, recorder.getResponseAsString());
assertEquals(200, recorder.getHttpStatusCode());
assertTrue(rewriter.responseWasRewritten());
assertEquals("POST", req.getValue().getMethod());
assertEquals("hello=world", req.getValue().getPostBodyAsString());
}
@Test
public void testHtmlAccelReturnsSameStatusCodeAndMessageWhenError() throws Exception {
String url = "http://example.org/data.html";
String data = "<html><body>This is error page</body></html>";
((FakeCaptureRewriter) rewriter).setContentToRewrite(data);
HttpRequest req = new HttpRequest(Uri.parse(url));
HttpResponse resp = new HttpResponseBuilder()
.setResponse(data.getBytes())
.setHeader("Content-Type", "text/html")
.setHttpStatusCode(5001)
.create();
expect(pipeline.execute(req)).andReturn(resp).once();
expectRequest("", url);
replay();
servlet.doGet(request, recorder);
verify();
assertEquals(data, recorder.getResponseAsString());
assertEquals(5001, recorder.getHttpStatusCode());
assertFalse(rewriter.responseWasRewritten());
}
}