Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain the query string in a GET with Java HttpServer/HttpExchange?

I am trying to create a simple HttpServer in Java to handle GET requests, but when I try to get the GET parameters for a request I noticed the HttpExchange class does not have a method for that.

Does anybody know an easy way to read the GET parameters (query string)?

This is how my handler looks like:

public class TestHandler{
  @Override
  public void handle(HttpExchange exc) throws IOxception {
    String response = "This is the reponse";
    exc.sendResponseHeaders(200, response.length());

    // need GET params here

    OutputStream os = exc.getResponseBody();
    os.write(response.getBytes());
    os.close();
  } 
}

.. and the main method:

public static void main(String[] args) throws Exception{
  // create server on port 8000
  InetSocketAddress address = new InetSocketAddress(8000);
  HttpServer server = new HttpServer.create(address, 0);

  // bind handler
  server.createContext("/highscore", new TestHandler());
  server.setExecutor(null);
  server.start();
}
like image 758
Tibor Avatar asked Jul 24 '12 22:07

Tibor


4 Answers

The following: httpExchange.getRequestURI().getQuery()

will return string in format similar to this: "field1=value1&field2=value2&field3=value3..."

so you could simply parse string yourself, this is how function for parsing could look like:

public Map<String, String> queryToMap(String query) {     if(query == null) {         return null;     }     Map<String, String> result = new HashMap<>();     for (String param : query.split("&")) {         String[] entry = param.split("=");         if (entry.length > 1) {             result.put(entry[0], entry[1]);         }else{             result.put(entry[0], "");         }     }     return result; } 

And this is how you could use it:

Map<String, String> params = queryToMap(httpExchange.getRequestURI().getQuery());  System.out.println("param A=" + params.get("A")); 
like image 199
anon01 Avatar answered Sep 23 '22 20:09

anon01


This answer, contrary to annon01's, properly decodes the keys and values. It does not use String.split, but scans the string using indexOf, which is faster.

public static Map<String, String> parseQueryString(String qs) {     Map<String, String> result = new HashMap<>();     if (qs == null)         return result;      int last = 0, next, l = qs.length();     while (last < l) {         next = qs.indexOf('&', last);         if (next == -1)             next = l;          if (next > last) {             int eqPos = qs.indexOf('=', last);             try {                 if (eqPos < 0 || eqPos > next)                     result.put(URLDecoder.decode(qs.substring(last, next), "utf-8"), "");                 else                     result.put(URLDecoder.decode(qs.substring(last, eqPos), "utf-8"), URLDecoder.decode(qs.substring(eqPos + 1, next), "utf-8"));             } catch (UnsupportedEncodingException e) {                 throw new RuntimeException(e); // will never happen, utf-8 support is mandatory for java             }         }         last = next + 1;     }     return result; } 
like image 20
Oliv Avatar answered Sep 23 '22 20:09

Oliv


Building on the answer by @anon01, this is how to do it in Groovy:

Map<String,String> getQueryParameters( HttpExchange httpExchange )
{
    def query = httpExchange.getRequestURI().getQuery()
    return query.split( '&' )
            .collectEntries {
        String[] pair = it.split( '=' )
        if (pair.length > 1)
        {
            return [(pair[0]): pair[1]]
        }
        else
        {
            return [(pair[0]): ""]
        }
    }
}

And this is how to use it:

def queryParameters = getQueryParameters( httpExchange )
def parameterA = queryParameters['A']
like image 45
Wim Deblauwe Avatar answered Sep 25 '22 20:09

Wim Deblauwe


Stumbled across this, and figured I'd toss a Java 8 / Streams implementation out here, whilst adding a few extra bits (not in previous answers).

Extra 1: I've added a filter to avoid processing any empty params. Something that should not happen, but it allows a cleaner implementation vs. not handling the issue (and sending an empty response). An example of this would look like ?param1=value1&param2=

Extra 2: I've leveraged String.split(String regex, int limit) for the second split operation. This allows a query parameter such as ?param1=it_has=in-it&other=something to be passed.

public static Map<String, String> getParamMap(String query) {
    // query is null if not provided (e.g. localhost/path )
    // query is empty if '?' is supplied (e.g. localhost/path? )
    if (query == null || query.isEmpty()) return Collections.emptyMap();

    return Stream.of(query.split("&"))
            .filter(s -> !s.isEmpty())
            .map(kv -> kv.split("=", 2)) 
            .collect(Collectors.toMap(x -> x[0], x-> x[1]));

}

Imports

import java.util.Map;
import java.util.Collections;
import java.util.stream.Stream;
import java.util.stream.Collectors;
like image 25
Brian Avatar answered Sep 22 '22 20:09

Brian