Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a string to an Apache HttpComponents HttpRequest

I have a String that contains an HTTP header. I want to turn this into an Apache HttpComponents HttpRequest object. Is there a way to do this without picking apart the string myself?

This tutorial: http://hc.apache.org/httpcomponents-core-dev/tutorial/html/fundamentals.html#d5e56 and the javadoc does not indicate as much.

like image 295
Jason Thompson Avatar asked Mar 26 '12 21:03

Jason Thompson


1 Answers

A class to convert a string to apache request:

import org.apache.http.*;
import org.apache.http.impl.DefaultHttpRequestFactory;
import org.apache.http.impl.entity.EntityDeserializer;
import org.apache.http.impl.entity.LaxContentLengthStrategy;
import org.apache.http.impl.io.AbstractSessionInputBuffer;
import org.apache.http.impl.io.HttpRequestParser;
import org.apache.http.io.HttpMessageParser;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.message.BasicLineParser;
import org.apache.http.params.BasicHttpParams;

import java.io.ByteArrayInputStream;
import java.io.IOException;

/**
 *
 */
public class ApacheRequestFactory {
    public static HttpRequest create(final String requestAsString) {
        try {
            SessionInputBuffer inputBuffer = new AbstractSessionInputBuffer() {
                {
                    init(new ByteArrayInputStream(requestAsString.getBytes()), 10, new BasicHttpParams());
                }

                @Override
                public boolean isDataAvailable(int timeout) throws IOException {
                    throw new RuntimeException("have to override but probably not even called");
                }
            };
            HttpMessageParser parser = new HttpRequestParser(inputBuffer, new BasicLineParser(new ProtocolVersion("HTTP", 1, 1)), new DefaultHttpRequestFactory(), new BasicHttpParams());
            HttpMessage message = parser.parse();
            if (message instanceof BasicHttpEntityEnclosingRequest) {
                BasicHttpEntityEnclosingRequest request = (BasicHttpEntityEnclosingRequest) message;
                EntityDeserializer entityDeserializer = new EntityDeserializer(new LaxContentLengthStrategy());
                HttpEntity entity = entityDeserializer.deserialize(inputBuffer, message);
                request.setEntity(entity);
            }
            return (HttpRequest) message;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (HttpException e) {
            throw new RuntimeException(e);
        }
    }
}

and a test class showing how to use it:

import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.junit.Test;

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

import static org.junit.Assert.*;

/**
 *
 */
public class ApacheRequestFactoryTest {
    @Test
    public void testGet() {
        String requestString = "GET /?one=aone&two=atwo HTTP/1.1\n" +
                "Host: localhost:7788\n" +
                "Connection: Keep-Alive\n" +
                "User-Agent: Apache-HttpClient/4.0.1 (java 1.5)";

        HttpRequest request = ApacheRequestFactory.create(requestString);
        assertEquals("GET", request.getRequestLine().getMethod());
        List<NameValuePair> pairs = URLEncodedUtils.parse(URI.create(request.getRequestLine().getUri()), "ISO-8859-1");
        checkPairs(pairs);
    }

    @Test
    public void testPost() throws IOException {
        String requestString = "POST / HTTP/1.1\n" +
                "Content-Length: 17\n" +
                "Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1\n" +
                "Host: localhost:7788\n" +
                "Connection: Keep-Alive\n" +
                "User-Agent: Apache-HttpClient/4.0.1 (java 1.5)\n" +
                "\n" +
                "one=aone&two=atwo";

        HttpRequest request = ApacheRequestFactory.create(requestString);
        assertEquals("POST", request.getRequestLine().getMethod());
        List<NameValuePair> pairs = URLEncodedUtils.parse(((BasicHttpEntityEnclosingRequest)request).getEntity());
        checkPairs(pairs);
    }

    private void checkPairs(List<NameValuePair> pairs) {
        for (NameValuePair pair : pairs) {
            if (pair.getName().equals("one")) assertEquals("aone", pair.getValue());
            else if (pair.getName().equals("two")) assertEquals("atwo", pair.getValue());
            else assertTrue("got more parameters than expected:"+pair.getName(), false);
        }
    }
}

And a small rant:

WHAT ARE THE APACHE HTTP TEAM THINKING ? The api is incredibly awkward to use. Developers around the world are wasting time writing wrapper and conversion classes for what should be run of the mill every day usage (like this example the simple act of converting a string to an apache http request, and the bizarre way you need to extract the form parameters (also having to do it in two different ways depending on what type of request was made)). The global time wasted because of this is huge. When you write an API from the bottom up, starting with the specs, you MUST then start a layer from the top down (top being an interface where you can get typical work done without having to understand or look at the way the code is implemented), making every day usage of the library CONVENIENT and intuitive. Apache http libraries are anything but. It's almost a miracle that its the standard library for this type of task.

like image 113
user467257 Avatar answered Sep 28 '22 07:09

user467257