Getting Parameters from HttpExchange

You now in Java 6 has some APIs to create lightweight HTTP server. Well, today, I had to created a lightweight HTTP server embedded in an application, but when I try to get the parameters for a request I noticed the HttpExchange class doesn’t have a method for that.

After some researches on Google, I come across a solution.

What I did was to create a Filter class which will deal with the parameters parse:

public class ParameterFilter extends Filter {

    @Override
    public String description() {
        return "Parses the requested URI for parameters";
    }

    @Override
    public void doFilter(HttpExchange exchange, Chain chain)
        throws IOException {
        parseGetParameters(exchange);
        parsePostParameters(exchange);
        chain.doFilter(exchange);
    }    

    private void parseGetParameters(HttpExchange exchange)
        throws UnsupportedEncodingException {

        Map<String, Object> parameters = new HashMap<String, Object>();
        URI requestedUri = exchange.getRequestURI();
        String query = requestedUri.getRawQuery();
        parseQuery(query, parameters);
        exchange.setAttribute("parameters", parameters);
    }

    private void parsePostParameters(HttpExchange exchange)
        throws IOException {

        if ("post".equalsIgnoreCase(exchange.getRequestMethod())) {
            @SuppressWarnings("unchecked")
            Map<String, Object> parameters =
                (Map<String, Object>)exchange.getAttribute("parameters");
            InputStreamReader isr =
                new InputStreamReader(exchange.getRequestBody(),"utf-8");
            BufferedReader br = new BufferedReader(isr);
            String query = br.readLine();
            parseQuery(query, parameters);
        }
    }

     @SuppressWarnings("unchecked")
     private void parseQuery(String query, Map<String, Object> parameters)
         throws UnsupportedEncodingException {

         if (query != null) {
             String pairs[] = query.split("[&]");

             for (String pair : pairs) {
                 String param[] = pair.split("[=]");

                 String key = null;
                 String value = null;
                 if (param.length > 0) {
                     key = URLDecoder.decode(param[0],
                         System.getProperty("file.encoding"));
                 }

                 if (param.length > 1) {
                     value = URLDecoder.decode(param[1],
                         System.getProperty("file.encoding"));
                 }

                 if (parameters.containsKey(key)) {
                     Object obj = parameters.get(key);
                     if(obj instanceof List<?>) {
                         List<String> values = (List<String>)obj;
                         values.add(value);
                     } else if(obj instanceof String) {
                         List<String> values = new ArrayList<String>();
                         values.add((String)obj);
                         values.add(value);
                         parameters.put(key, values);
                     }
                 } else {
                     parameters.put(key, value);
                 }
             }
         }
    }
}

After that you can add this filter to your HttpServer context:

HttpServer server = HttpServer.create(new InetSocketAddress(80), 0);
HttpContext context = server.createContext("/myapp", new myHttpHandler());
context.getFilters().add(new ParameterFilter());
server.start();

Then you can do something like below in your HttpHandler to get the parameters:

public class MyHttpHandler implements HttpHandler {

    @Override
    public void handle(HttpExchange exchange) throws IOException {
        Map<String, Object> params =
           (Map<String, Object>)exchange.getAttribute("parameters");

        //now you can use the params
    }
}

Well, that’s all! I hope you enjoy the tip!

11 comments so far

  1. Kalpesh on

    Thanks a ton man. You made my life easy. Keep it up

  2. Rob on

    Thanks! Very nice.

    There is one typo, however:

    Object ojb = parameters.get(key);

    should of course be

    Object obj = parameters.get(key);

    You’re welcome!

    – rob

  3. Jamshaid Ali on

    Dear i used this code but i get this , i m looking into more detial.It works for first several thousand requests.But then i get stack overflow.
    =============================================================
    Exception in thread “pool-1-thread-31” java.lang.StackOverflowError
    at sun.nio.ch.Util$BufferCache.next(Util.java:55)
    at sun.nio.ch.Util$BufferCache.get(Util.java:94)
    at sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:144)
    at sun.nio.ch.IOUtil.write(IOUtil.java:37)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:334)
    at sun.net.httpserver.Request$WriteStream.write(Request.java:392)
    at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
    at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
    at sun.net.httpserver.ExchangeImpl.sendResponseHeaders(ExchangeImpl.java:192)
    at sun.net.httpserver.HttpExchangeImpl.sendResponseHeaders(HttpExchangeImpl.java:68)
    at DWHCPAController.RequestController.sendResponseClient(RequestController.java:50)
    at DWHCPAController.BIDMController.handle(BIDMController.java:34)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
    at sun.net.httpserver.AuthFilter.doFilter(AuthFilter.java:65)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
    at sun.net.httpserver.ServerImpl$Exchange$LinkHandler.handle(ServerImpl.java:555)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:65)
    at DWHCPAController.ParameterFilter.doFilter(ParameterFilter.java:38)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)
    at DWHCPAController.ParameterFilter.doFilter(ParameterFilter.java:38)
    at com.sun.net.httpserver.Filter$Chain.doFilter(Filter.java:68)

  4. Uditha Indika Karunarante on

    Great work

  5. Martin on

    thanks, you save my life!!!

  6. Rob on

    That’s incredible. Thanks man.

  7. mark on

    The streams/readers need to be closed out in this code other than that good work around.

  8. Anshul on

    Thanx a lot ..

  9. PF on

    I think this implementation is not thread safe. I had to synchronize on the filter instance in order to get this to work. Otherwise, when the browser was making many requests in parallel, the parameters exchange attribute was getting corrupted.

    • Stefan on

      Indeed, not threadsafe!

    • sunmao on

      Could you tell me why this code isn’t thread safe?!
      I’ve tried to understand your point, but I think we are creating by every request a new “parameters” Object and we set it for the current exchange Object which is different for every request,


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: