com.web.server.ProxyServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.web.server.ProxyServlet.java

Source

package com.web.server;

/**
 *    Copyright 2010 Kenneth Jorgensen (kennethjorgensen.com) (modifications)
 *    - original code can be found at http://www.siafoo.net/snippet/258
 *    Copyright 2009 Stou Sandalski (Siafoo.net)
 *    Copyright 1999-2008 The Apache Software Foundation
 *
 *  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.
 * 
 */

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.StatusLine;

/**
* This servlet provides a proxy to other servers for use in development with GWT devmode.
* It is not meant, in any way shape or form, to be used in production.
*/
public class ProxyServlet extends HttpServlet {

    private static final String targetServer = "http://localhost:9000/";

    @Override
    @SuppressWarnings("unchecked")
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // Create new client to perform the proxied request
        HttpClient httpclient = new DefaultHttpClient();

        // Determine final URL
        StringBuffer uri = new StringBuffer();
        uri.append(targetServer);
        uri.append(req.getRequestURI());

        // Add any supplied query strings
        String queryString = req.getQueryString();
        if (queryString != null) {
            uri.append("?" + queryString);
        }

        // Get HTTP method
        final String method = req.getMethod();
        // Create new HTTP request container
        HttpRequestBase request = null;

        // Get content length
        int contentLength = req.getContentLength();
        // Unknown content length ...
        //       if (contentLength == -1)
        //          throw new ServletException("Cannot handle unknown content length");
        // If we don't have an entity body, things are quite simple
        if (contentLength < 1) {
            request = new HttpRequestBase() {
                public String getMethod() {
                    return method;
                }
            };
        } else {
            // Prepare request
            HttpEntityEnclosingRequestBase tmpRequest = new HttpEntityEnclosingRequestBase() {
                public String getMethod() {
                    return method;
                }
            };

            // Transfer entity body from the received request to the new request
            InputStreamEntity entity = new InputStreamEntity(req.getInputStream(), contentLength);
            tmpRequest.setEntity(entity);

            request = tmpRequest;
        }

        // Set URI
        try {
            request.setURI(new URI(uri.toString()));
        } catch (URISyntaxException e) {
            throw new ServletException("URISyntaxException: " + e.getMessage());
        }

        // Copy headers from old request to new request
        // @todo not sure how this handles multiple headers with the same name
        Enumeration<String> headers = req.getHeaderNames();
        while (headers.hasMoreElements()) {
            String headerName = headers.nextElement();
            String headerValue = req.getHeader(headerName);
            // Skip Content-Length and Host
            String lowerHeader = headerName.toLowerCase();
            if (lowerHeader.equals("content-length") == false && lowerHeader.equals("host") == false) {
                //             System.out.println(headerName.toLowerCase() + ": " + headerValue);
                request.addHeader(headerName, headerValue);
            }
        }

        // Execute the request
        HttpResponse response = httpclient.execute(request);

        // Transfer status code to the response
        StatusLine status = response.getStatusLine();
        resp.setStatus(status.getStatusCode());
        // resp.setStatus(status.getStatusCode(), status.getReasonPhrase()); // This seems to be deprecated. Yes status message is "ambigous", but I don't approve

        // Transfer headers to the response
        Header[] responseHeaders = response.getAllHeaders();
        for (int i = 0; i < responseHeaders.length; i++) {
            Header header = responseHeaders[i];
            resp.addHeader(header.getName(), header.getValue());
        }

        // Transfer proxy response entity to the servlet response
        HttpEntity entity = response.getEntity();
        InputStream input = entity.getContent();
        OutputStream output = resp.getOutputStream();
        int b = input.read();
        while (b != -1) {
            output.write(b);
            b = input.read();
        }

        // Clean up
        input.close();
        output.close();
        httpclient.getConnectionManager().shutdown();
    }
}