org.eclipse.smarthome.ui.internal.proxy.BlockingProxyServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.smarthome.ui.internal.proxy.BlockingProxyServlet.java

Source

/**
 * Copyright (c) 2014-2017 by the respective copyright holders.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.smarthome.ui.internal.proxy;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

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

import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A blocking version of the proxy servlet that complies with Servlet API 2.4.
 *
 * @author Kai Kreuzer - Initial contribution and API
 * @author Svilen Valkanov - Replaced Apache HttpClient with Jetty
 * @author John Cocula - refactored to support alternate implementation
 */
public class BlockingProxyServlet extends HttpServlet {

    private final Logger logger = LoggerFactory.getLogger(BlockingProxyServlet.class);

    private static final long serialVersionUID = -4716754591953017794L;

    private final ProxyServletService service;

    private static HttpClient httpClient = new HttpClient(new SslContextFactory());

    /** Timeout for HTTP requests in ms */
    private static final int TIMEOUT = 15000;

    BlockingProxyServlet(ProxyServletService service) {
        super();
        this.service = service;
        if (!httpClient.isStarted()) {
            try {
                httpClient.start();
            } catch (Exception e) {
                logger.warn("Cannot start HttpClient!", e);
            }
        }
    }

    @Override
    public String getServletInfo() {
        return "Proxy (blocking)";
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        URI uri = service.uriFromRequest(request);

        if (uri == null) {
            service.sendError(request, response);
        } else {
            Request httpRequest = httpClient.newRequest(uri);

            service.maybeAppendAuthHeader(uri, httpRequest);

            InputStreamResponseListener listener = new InputStreamResponseListener();

            // do the client request
            try {
                httpRequest.send(listener);
                // wait for the response headers to arrive or the timeout to expire
                Response httpResponse = listener.get(TIMEOUT, TimeUnit.MILLISECONDS);

                // get response headers
                HttpFields headers = httpResponse.getHeaders();
                Iterator<HttpField> iterator = headers.iterator();

                // copy all headers
                while (iterator.hasNext()) {
                    HttpField header = iterator.next();
                    response.setHeader(header.getName(), header.getValue());
                }
            } catch (Exception e) {
                if (e instanceof TimeoutException) {
                    logger.warn("Proxy servlet failed to stream content due to a timeout");
                    response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT);
                } else {
                    logger.warn("Proxy servlet failed to stream content: {}", e.getMessage());
                    response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
                }
                return;
            }
            // now copy/stream the body content
            try (InputStream responseContent = listener.getInputStream()) {
                IOUtils.copy(responseContent, response.getOutputStream());
            }
        }
    }
}