title: Character encoding in com.sun.net.httpserver
body: <p>I'm trying to write a mock HTTP server for unit tests, I'm using the com.sun.net.httpserver classes for that.
  I'm having problem with the encoding of the URL: the query parameters are ISO-8859-1 encoded, but the URI that is passed to the handler (via HttpExchange) is not.
  As I can't change the encoding of the original server, I was wondering if there was a way to tell the HttpServer which encoding to use when decoding the URL.
  Thanks in advance.</p>
  
  <p>Here is a test program:</p>
  
  <pre><code>package test34;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.net.URL;
  import java.net.URLEncoder;
  import java.util.logging.Level;
  import java.util.logging.Logger;
  
  public class Main {
      public static void main(String[] args) {
          try {
              MockServer mock = new MockServer();
              mock.start(8642);
              URL url = new URL("http://localhost:8642/?p="
                      + URLEncoder.encode("téléphone", "ISO-8859-1"));
              System.out.println(url);
              InputStream in = url.openStream();
              while (in.read() &gt; 0) {
              }
              in.close();
              mock.stop();
              System.out.println(mock.getLastParams().get("p"));
          } catch (IOException ex) {
              Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
          }
      }    
  }
  </code></pre>
  
  <p>And here is the code of the mock server:</p>
  
  <pre><code>package test34;
  
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  import java.io.PrintWriter;
  import java.io.Writer;
  import java.net.InetSocketAddress;
  import java.net.URI;
  import java.net.URLDecoder;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.concurrent.Executors;
  
  import com.sun.net.httpserver.Headers;
  import com.sun.net.httpserver.HttpExchange;
  import com.sun.net.httpserver.HttpHandler;
  import com.sun.net.httpserver.HttpServer;
  
  public class MockServer {
  
      private HttpServer httpServer;
      private Map&lt;String, String&gt; params;
  
      public void start(int port) {
          if (httpServer == null) {
              try {
                  InetSocketAddress addr = new InetSocketAddress(port);
                  httpServer = HttpServer.create(addr, 0);
                  httpServer.createContext("/", new HttpHandler() {
                      @Override
                      public void handle(HttpExchange exchange) throws IOException {
                          try {
                              handleRoot(exchange);
                          } catch (RuntimeException e) {
                              throw e;
                          } catch (IOException e) {
                              throw e;
                          }
                      }
                  });
                  httpServer.setExecutor(Executors.newFixedThreadPool(1));
                  httpServer.start();
              } catch (IOException e) {
                  throw new RuntimeException(e.getMessage());
              }
          }
      }
  
      public void stop() {
          if (httpServer != null) {
              httpServer.stop(10);
              httpServer = null;
          }
      }
  
      public Map&lt;String, String&gt; getLastParams() {
          Map&lt;String, String&gt; result = new HashMap&lt;String, String&gt;();
          if (params != null) {
              result.putAll(params);
          }
          return result;
      }
  
      private void handleRoot(HttpExchange exchange) throws IOException {
          URI uri = exchange.getRequestURI();
          params = parseQuery(uri.getQuery());
          Headers responseHeaders = exchange.getResponseHeaders();
          responseHeaders.set("Content-Type", "text/plain;charset=ISO-8859-1");
          exchange.sendResponseHeaders(200, 0);
          OutputStream stream = exchange.getResponseBody();
          try {
              Writer writer = new OutputStreamWriter(stream, "ISO-8859-1");
              try {
                  PrintWriter out = new PrintWriter(writer);
                  try {
                      out.println("OK");
                  } finally {
                      out.close();
                  }
              } finally {
                  writer.close();
              }
          } finally {
              stream.close();
          }
      }
  
      private static Map&lt;String, String&gt; parseQuery(String qry)
              throws IOException {
          Map&lt;String, String&gt; result = new HashMap&lt;String, String&gt;();
          if (qry != null) {
              String defs[] = qry.split("[&amp;]");
              for (String def : defs) {
                  int ix = def.indexOf('=');
                  if (ix &lt; 0) {
                      result.put(def, "");
                  } else {
                      String name = def.substring(0, ix);
                      String value = URLDecoder.decode(
                              def.substring(ix + 1), "ISO-8859-1");
                      result.put(name, value);
                  }
              }
          }
          return result;
      }
  }
  </code></pre>