Chinese encoding of HttpClient request parameters

  • Catalog

problem

First, let's see how we normally use HttpClient to handle POST requests

public static String doHttpPost(String url, JSONObject params)
            throws IOException {
    CloseableHttpClient httpclient = HttpClients.createDefault();
    try {
        HttpPost httpPost = new HttpPost(url);

        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        params.forEach((key, value) -> {
            if (value != null) {
                nvps.add(new BasicNameValuePair(key, String.valueOf(value)));
            } else {
                nvps.add(new BasicNameValuePair(key, ""));
            }
        });

        HttpEntity reqEntity = EntityBuilder
                .create()
                .setContentEncoding('UTF-8")
                .setParameters(nvps).build();
        httpPost.setEntity(reqEntity);
        CloseableHttpResponse response = httpclient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        String result = null;
        if (entity != null) {
            result = EntityUtils.toString(entity, "UTF-8");
        }
        EntityUtils.consume(entity);
        response.close();
        return result;
    } finally {
        httpclient.close();
    }
}

At first glance, there is no problem. Usually, we can't see the problem when we use it (because the programmer will instinctively avoid the Chinese content in the request parameters when making a request), but once the parameter passing params contains Chinese, we will see in the received request??? This kind of thing that makes the program climax in minutes! Because setContentEncoding('UTF-8 ') doesn't work at all

problem analysis

The processing of request parameters is mainly concentrated in the following part

HttpEntity reqEntity = EntityBuilder.create().setContentEncoding('UTF-8").setParameters(nvps).build();

It can be seen that this is a typical decorator mode. Through Maven, check the build() function in the source code of EntityBuilder as follows:

public HttpEntity build() {
    final AbstractHttpEntity e;
    //... slightly ...
    else if (this.parameters != null) {
        e = new UrlEncodedFormEntity(this.parameters,
                this.contentType != null ? this.contentType.getCharset() : null);
    }
    //... slightly ...
    e.setContentEncoding(this.contentEncoding);
    //... slightly ...
    return e;
}

As you can see, this setContentEncoding is not to set the request parameter encoding. The parameter encoding is set to e = new urlencodedformentity (this. Parameters, this. ContentType! = null? This. ContentType. Getcharset(): null). This sentence is completed, so the parameter encoding needs to be set with setContentType(). Let's look at the source code of ContentType

public static final ContentType APPLICATION_ATOM_XML = create(
            "application/atom+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_FORM_URLENCODED = create(
        "application/x-www-form-urlencoded", Consts.ISO_8859_1);
public static final ContentType APPLICATION_JSON = create(
        "application/json", Consts.UTF_8);
public static final ContentType APPLICATION_OCTET_STREAM = create(
        "application/octet-stream", (Charset) null);
public static final ContentType APPLICATION_SVG_XML = create(
        "application/svg+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_XHTML_XML = create(
        "application/xhtml+xml", Consts.ISO_8859_1);
public static final ContentType APPLICATION_XML = create(
        "application/xml", Consts.ISO_8859_1);
public static final ContentType MULTIPART_FORM_DATA = create(
        "multipart/form-data", Consts.ISO_8859_1);
public static final ContentType TEXT_HTML = create(
        "text/html", Consts.ISO_8859_1);
public static final ContentType TEXT_PLAIN = create(
        "text/plain", Consts.ISO_8859_1);
public static final ContentType TEXT_XML = create(
        "text/xml", Consts.ISO_8859_1);
public static final ContentType WILDCARD = create(
        "*/*", (Charset) null);

Nima, the inherent is all ISO ⊛ 1. To speak Chinese, fortunately, ContentType.create(mimeType, charset) can be used, so the final code is as follows:

public static String doHttpPost(String url, JSONObject params)
            throws IOException {
    CloseableHttpClient httpclient = HttpClients.createDefault();
    try {
        HttpPost httpPost = new HttpPost(url);

        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        params.forEach((key, value) -> {
            if (value != null) {
                nvps.add(new BasicNameValuePair(key, String.valueOf(value)));
            } else {
                nvps.add(new BasicNameValuePair(key, ""));
            }
        });

        HttpEntity reqEntity = EntityBuilder
                .create()
                .setContentType(
                        ContentType.create(
                                "application/x-www-form-urlencoded",
                                Consts.UTF_8)).setParameters(nvps).build();
        httpPost.setEntity(reqEntity);
        CloseableHttpResponse response = httpclient.execute(httpPost);
        HttpEntity entity = response.getEntity();
        String result = null;
        if (entity != null) {
            result = EntityUtils.toString(entity, "UTF-8");
        }
        EntityUtils.consume(entity);
        response.close();
        return result;
    } finally {
        httpclient.close();
    }
}

Tags: xml encoding Maven JSON

Posted on Tue, 05 May 2020 01:08:04 -0400 by dbillings