org.callimachusproject.client.HttpClientRedirectTest.java Source code

Java tutorial

Introduction

Here is the source code for org.callimachusproject.client.HttpClientRedirectTest.java

Source

/*
 * Copyright (c) 2013 3 Round Stones Inc., Some Rights Reserved
 *
 * Licensed 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.callimachusproject.client;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpExecutionAware;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.execchain.ClientExecChain;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.util.EntityUtils;
import org.callimachusproject.engine.model.TermFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Client protocol handling tests.
 */
public class HttpClientRedirectTest extends TestCase {
    private static final String ORIGIN = "http://example.com";
    private static final BasicStatusLine _200 = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
    private final HttpClient httpclient = HttpClientFactory.getInstance().createHttpClient(ORIGIN);
    private final Map<String, HttpRequestHandler> handlers = new HashMap<String, HttpRequestHandler>();
    private final ClientExecChain director = new ClientExecChain() {
        public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request, HttpClientContext context,
                HttpExecutionAware execAware) throws IOException, HttpException {
            HttpResponse response = new BasicHttpResponse(_200);
            String uri = request.getRequestLine().getUri();
            String path = URI.create(uri).getRawPath();
            HttpRequestHandler handler = handlers.get(path);
            if (handler == null) {
                handler = handlers.get("*");
            }
            if (handler != null) {
                handler.handle(request, response, context);
            }
            String systemId = uri;
            return new HttpUriResponse(systemId, response);
        }
    };

    private void register(String path, HttpRequestHandler handler) {
        handlers.put(path, handler);
    }

    @Before
    public void setUp() throws Exception {
        handlers.clear();
        HttpClientFactory.getInstance().setProxy(getServerHttp(), director);
    }

    @After
    public void tearDown() throws Exception {
        HttpClientFactory.getInstance().removeProxy(getServerHttp(), director);
    }

    /**
     * Obtains the address of the local test server.
     *
     * @return  the test server host, with a scheme name of "http"
     */
    protected HttpHost getServerHttp() {
        return new HttpHost("example.com", -1, "http");
    }

    private static class SimpleService implements HttpRequestHandler {

        public SimpleService() {
            super();
        }

        public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context)
                throws HttpException, IOException {
            response.setStatusCode(HttpStatus.SC_OK);
            final StringEntity entity = new StringEntity("Whatever");
            response.setEntity(entity);
        }
    }

    @Test
    public void testRedirectLocationsReset() throws Exception {
        register("*", new SimpleService());
        register("/People.htm", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", "/people.html");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        final HttpHost target = getServerHttp();

        final HttpGet httpget = new HttpGet("/People.htm");
        final HttpClientContext context = HttpClientContext.create();

        this.httpclient.execute(target, httpget, context);
        // this checks that the context was properly reset
        final HttpResponse response = this.httpclient.execute(target, httpget, context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = context.getRequest();
        Assert.assertEquals("/people.html", request.getRequestLine().getUri());

        final URI uri = new URIBuilder().setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).setPath("/people.html").build();

        final URI location = getHttpLocation(httpget, context);
        Assert.assertEquals(uri, location);
    }

    @Test
    public void testHttpFragmentReset() throws Exception {
        register("*", new SimpleService());
        register("/~tim", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_SEE_OTHER);
                response.setHeader("Location", "/People.htm#tim");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        register("/People.htm", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", "/people.html");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        final HttpHost target = getServerHttp();

        final HttpClientContext context = HttpClientContext.create();

        this.httpclient.execute(target, new HttpGet("/~tim"), context);
        // this checks that the context was properly reset
        final HttpResponse response = this.httpclient.execute(target, new HttpGet("/People.htm"), context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = context.getRequest();
        Assert.assertEquals("/people.html", request.getRequestLine().getUri());

        final URI uri = new URIBuilder().setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).setPath("/people.html").build();

        final URI location = getHttpLocation(new HttpGet("/People.htm"), context);
        Assert.assertEquals(uri, location);
    }

    @Test
    public void testRelativeRequestURIWithFragment() throws Exception {
        register("*", new SimpleService());
        final HttpHost target = getServerHttp();

        final HttpGet httpget = new HttpGet("/stuff#blahblah");
        final HttpClientContext context = HttpClientContext.create();

        final HttpResponse response = this.httpclient.execute(target, httpget, context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = context.getRequest();
        Assert.assertEquals("/stuff", request.getRequestLine().getUri());

        final URI uri = new URIBuilder(httpget.getURI()).setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).build();

        final URI location = getHttpLocation(httpget, context);
        Assert.assertEquals(uri, location);
    }

    @Test
    public void testAbsoluteRequestURIWithFragment() throws Exception {
        register("*", new SimpleService());
        final HttpHost target = getServerHttp();

        final URI uri = new URIBuilder().setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).setPath("/stuff").setFragment("blahblah").build();

        final HttpGet httpget = new HttpGet(uri);
        final HttpClientContext context = HttpClientContext.create();

        final HttpResponse response = this.httpclient.execute(httpget, context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = (HttpRequest) context.getAttribute(HttpCoreContext.HTTP_REQUEST);
        Assert.assertEquals("/stuff", request.getRequestLine().getUri());

        final URI location = getHttpLocation(httpget, context);
        Assert.assertEquals(uri, location);
    }

    @Test
    public void testRedirectFromFragment() throws Exception {
        register("*", new SimpleService());
        register("/People.htm", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", "/people.html");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        final HttpHost target = getServerHttp();

        final HttpGet httpget = new HttpGet("/People.htm#tim");
        final HttpClientContext context = HttpClientContext.create();

        final HttpResponse response = this.httpclient.execute(target, httpget, context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = context.getRequest();
        Assert.assertEquals("/people.html", request.getRequestLine().getUri());

        final URI uri = new URIBuilder().setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).setPath("/people.html").setFragment("tim").build();

        final URI location = getHttpLocation(httpget, context);
        Assert.assertEquals(uri, location);
    }

    @Test
    public void testRedirectWithFragment() throws Exception {
        register("*", new SimpleService());
        register("/~tim", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_SEE_OTHER);
                response.setHeader("Location", "/People.htm#tim");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        register("/People.htm", new HttpRequestHandler() {
            public void handle(HttpRequest request, HttpResponse response, HttpContext context)
                    throws HttpException, IOException {
                response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY);
                response.setHeader("Location", "/people.html");
                final StringEntity entity = new StringEntity("Whatever");
                response.setEntity(entity);
            }
        });
        final HttpHost target = getServerHttp();

        final HttpGet httpget = new HttpGet("/~tim");
        final HttpClientContext context = HttpClientContext.create();

        final HttpResponse response = this.httpclient.execute(target, httpget, context);
        Assert.assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
        EntityUtils.consume(response.getEntity());

        final HttpRequest request = context.getRequest();
        Assert.assertEquals("/people.html", request.getRequestLine().getUri());

        final URI uri = new URIBuilder().setHost(target.getHostName()).setPort(target.getPort())
                .setScheme(target.getSchemeName()).setPath("/people.html").setFragment("tim").build();

        final URI location = getHttpLocation(httpget, context);
        Assert.assertEquals(uri, location);
    }

    /**
     * The interpreted (absolute) URI that was used to generate the last
     * request.
     */
    private URI getHttpLocation(HttpUriRequest originalRequest, HttpClientContext ctx) {
        try {
            URI original = originalRequest.getURI();
            HttpHost target = ctx.getTargetHost();
            List<URI> redirects = ctx.getRedirectLocations();
            URI absolute = URIUtils.resolve(original, target, redirects);
            return new URI(TermFactory.newInstance(absolute.toASCIIString()).getSystemId());
        } catch (URISyntaxException e) {
            return null;
        }
    }

}