com.subgraph.vega.internal.http.proxy.VegaHttpRequestParser.java Source code

Java tutorial

Introduction

Here is the source code for com.subgraph.vega.internal.http.proxy.VegaHttpRequestParser.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Subgraph.
 * 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
 * 
 * Contributors:
 *     Subgraph - initial API and implementation
 ******************************************************************************/
package com.subgraph.vega.internal.http.proxy;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.ConnectionClosedException;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpMessage;
import org.apache.http.HttpRequestFactory;
import org.apache.http.ParseException;
import org.apache.http.ProtocolException;
import org.apache.http.RequestLine;
import org.apache.http.impl.io.AbstractMessageParser;
import org.apache.http.io.HttpMessageParser;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.BasicRequestLine;
import org.apache.http.message.LineParser;
import org.apache.http.message.ParserCursor;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.CharArrayBuffer;

/**
 * HTTP request parser based on HttpRequestParser and AbstractMessageParser. Attaches scheme and host information to a 
 * request line URI when the connection is performing SSL MITM so the request still contains an absoluteURI as it would
 * for an ordinary proxy request.
 */
public class VegaHttpRequestParser implements HttpMessageParser {
    private final VegaHttpServerConnection conn;
    private final SessionInputBuffer sessionBuffer;
    private final HttpRequestFactory requestFactory;
    private final CharArrayBuffer lineBuf;
    private final LineParser lineParser;
    private final int maxHeaderCount;
    private final int maxLineLen;

    public VegaHttpRequestParser(final VegaHttpServerConnection conn, final SessionInputBuffer buffer,
            final LineParser parser, final HttpRequestFactory requestFactory, final HttpParams params) {
        if (requestFactory == null) {
            throw new IllegalArgumentException("Request factory may not be null");
        }
        this.conn = conn;
        this.sessionBuffer = buffer;
        this.lineParser = parser;
        this.requestFactory = requestFactory;
        this.lineBuf = new CharArrayBuffer(128);
        this.maxHeaderCount = params.getIntParameter(CoreConnectionPNames.MAX_HEADER_COUNT, -1);
        this.maxLineLen = params.getIntParameter(CoreConnectionPNames.MAX_LINE_LENGTH, -1);
    }

    private RequestLine parseRequestLine(final SessionInputBuffer sessionBuffer)
            throws IOException, HttpException, ParseException {
        lineBuf.clear();
        int i = sessionBuffer.readLine(lineBuf);
        if (i == -1) {
            throw new ConnectionClosedException("Client closed connection");
        }
        ParserCursor cursor = new ParserCursor(0, lineBuf.length());
        return lineParser.parseRequestLine(lineBuf, cursor);
    }

    @Override
    public HttpMessage parse() throws IOException, HttpException {
        RequestLine requestLine;
        try {
            requestLine = parseRequestLine(sessionBuffer);
        } catch (ParseException px) {
            throw new ProtocolException(px.getMessage(), px);
        }

        List<CharArrayBuffer> headerLines = new ArrayList<CharArrayBuffer>();
        Header[] headers = AbstractMessageParser.parseHeaders(sessionBuffer, maxHeaderCount, maxLineLen, lineParser,
                headerLines);

        if (conn.isSslConnection()) {
            URI uri;
            try {
                uri = new URI(requestLine.getUri());
            } catch (URISyntaxException e) {
                throw new ProtocolException("Invalid URI: " + requestLine.getUri(), e);
            }
            if (uri.getScheme() == null) {
                final Header hostHeader = getFirstHeader(headers, HTTP.TARGET_HOST);
                final StringBuilder buf = new StringBuilder();
                if (hostHeader != null) {
                    // REVISIT: does using the Host header value instead of the SSL host risk opening another connection?
                    buf.append("https://");
                    buf.append(hostHeader.getValue());
                } else {
                    buf.append(conn.getSslHost().toURI());
                }
                buf.append(uri.getRawPath());
                if (uri.getRawQuery() != null) {
                    buf.append("?");
                    buf.append(uri.getRawQuery());
                }

                requestLine = new BasicRequestLine(requestLine.getMethod(), buf.toString(),
                        requestLine.getProtocolVersion());
            }
        }

        HttpMessage message = requestFactory.newHttpRequest(requestLine);
        message.setHeaders(headers);
        return message;
    }

    private Header getFirstHeader(Header[] headers, String name) {
        for (int i = 0; i < headers.length; i++) {
            if (headers[i].getName().equalsIgnoreCase(name)) {
                return headers[i];
            }
        }
        return null;
    }

}