com.sun.net.httpserver 中的字符编码

Character encoding in com.sun.net.httpserver

我正在尝试为单元测试编写一个模拟 HTTP 服务器,为此我使用 com.sun.net.httpserver 类。 URL 的编码有问题:查询参数是 ISO-8859-1 编码的,但传递给处理程序(通过 HttpExchange)的 URI 不是。 由于我无法更改原始服务器的编码,我想知道是否有办法告诉 HttpServer 在解码 URL 时使用哪种编码。 提前致谢。

这是一个测试程序:

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() > 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);
        }
    }    
}

这里是模拟服务器的代码:

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<String, String> 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<String, String> getLastParams() {
        Map<String, String> result = new HashMap<String, String>();
        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<String, String> parseQuery(String qry)
            throws IOException {
        Map<String, String> result = new HashMap<String, String>();
        if (qry != null) {
            String defs[] = qry.split("[&]");
            for (String def : defs) {
                int ix = def.indexOf('=');
                if (ix < 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;
    }
}

HttpExchange.getQueryString() 的 javadoc 说 returns "undecoded query string of request URI, or null if the request URI doesn't have one."

如果它没有被解码,并且由于 http headers 必须是 7 位 ASCII (ietf.org/rfc/rfc2616.txt) ,那么您可以稍后使用 URLDecoder.decode(. .. "ISO-8859-1");