Java API POST 特殊字符调用

Java API POST Call with special characters

我目前使用 JAVA 通过 HTTPClient 框架调用 POST,该方法不是我们的方法,我发现特殊字符有一个有趣的问题。

  1. 调用正在发送 JSON Object,未使用 URL 参数。
  2. 调用在我的代码和 postman 中运行良好,但是,如果我在混合中加入一些特殊字符,HTTPClient 会失败(但在 postman 中保持正常工作)。

我几乎完全确定我的问题是我遗漏了一些关于我的编码的 header 但我不知道我必须在我的电话中包括哪一个并且我发现关于这个的信息很少.

调用示例。 (为了数据安全,我会删除一些东西)。

这是 POSTMAN 调用的 Headers:

这是我的 HTTPClient 调用:

headers={Authorization=Bearer XXXXXXXXXXXXXXXX, Accept-Encoding=gzip, deflate, br, Content-Type=application/json}

如您所见,我确定问题出在这里,但我不知道我必须通知哪个参数,更重要的是,为什么。

PD:我之前检查过,但没有发现任何类似的问题。

感谢您的帮助

编辑许可:

当我说“在混合中加入一些特殊字符”时,我在 JSON Object 中发送的多个变量之一是一个可以包含特殊字符的字符串,更具体地说,我们发送的是名字和姓氏,实际问题是关于字符“Ñ”的。

感谢 Scary Wombat 的提问。

编辑2:

我LOG中的api调用:

2022-05-11 10:20:45,118 错误 [es.fiatc.http_client.GenericOperation.execute]- 信息:javax.net.ssl.trustStore = null 2022-05-11 10:20:45,495 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 使用 uri 执行 method:post:https://XXXXXXXXXXXXXXXXXXXXXXXXXX 2022-05-11 10:20:45,498 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 参数:空 2022-05-11 10:20:45,501 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- Headers: {Authorization=Bearer XXXXXXXXXXXXXXXXX, Content-Type=application/json} 2022-05-11 10:20:45,503 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 超时 = 30000 2022-05-11 10:20:45,506 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 用户:空 2022-05-11 10:20:45,508 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 密码:空 2022-05-11 10:20:45,511 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 字符集:UTF-8 2022-05-11 10:20:45,513 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- TrustCertificate: null 2022-05-11 10:20:45,516 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- TrustCertificatePwd: null 2022-05-11 10:20:45,519 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- FiatcClientCertificate: false 2022-05-11 10:20:45,521 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 实体 (class): java.lang.String 2022-05-11 10:20:45,524 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- EntityCharset: 空 2022-05-11 10:20:45,526 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- EntityMimeType: application/json 2022-05-11 10:20:45,529 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- Preemptive_authentication: 错误 2022-05-11 10:20:52,141 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 执行请求 POST XXXXXXXXXXXXXXXXXXXXXX HTTP/1.1 2022-05-11 10:20:53,755 信息 [es.fiatc.http_client.dao.HTTPDao.execute]- 结果 = {headers={content-type=application/json, transfer-encoding= chunked, vary=Accept-Encoding, expires=1981 年 11 月 19 日星期四 08:52:00 GMT, cache-control=no-cache, pragma=no-cache, set-cookie=语言= es; expires=2022 年 6 月 10 日,星期五 08:21:01 GMT; Max-Age=2592000;路径=/;安全,日期=2022 年 5 月 11 日星期三 08:21:01 GMT,strict-transport-security=max-age=31536000;包括子域;预加载,x-xss-protection=1;模式=块,x-content-type-选项=nosniff,连接=关闭},status_code=200,reason_phrase=确定,内容=[ B@166a7559} 2022-05-11 10:20:53,756 错误 [es.fiatc.sld_guia_medica.dao.APIDao.callAPIPost]- {headers={content-type=application/json, transfer-encoding=chunked, vary=Accept-Encoding, expires=1981 年 11 月 19 日星期四 08:52:00 GMT , cache-control=no-cache, pragma=no-cache, set-cookie=lang=es; expires=2022 年 6 月 10 日,星期五 08:21:01 GMT; Max-Age=2592000;路径=/;安全,日期=2022 年 5 月 11 日星期三 08:21:01 GMT,strict-transport-security=max-age=31536000;包括子域;预加载,x-xss-protection=1;模式=块,x-content-type-选项=nosniff,连接=关闭},status_code=200,reason_phrase=好的,内容=[B@166a7559} 2022-05-11 10:20:54,935 信息 [es.fiatc.sld_guia_medica.tuotempo.actions.TuotempoAseguradoAction.execute]-

{"result":"ERROR","message":"需要一个有效的 Userid","sessionid":null,"execution_time":506,"net_execution_time":506}

我发送的 JSONObject 示例:

{"email":"","userlid":"008368790204","idnumber":"XXXXXXX","idtype":"1","mobile_number":"666666666"," privacy":"1","fname":"MARIA DEL CARMEN","lname":"OSUNA","gender":"F","date_of_birth":"1969-07-02"," lname2":"NUÑEZ","language":"es"}

如果 lname2 中的特殊字符消失,api 调用工作正常。

编辑 3:

虽然我不能 post 我的所有 java 调用这些是编码相关部分:

public static Map execute(String method, String url, Map<String, String> params, Map<String, String> headers, 
            String user, String pwd, String trustCertificate, String trustCertificateClave, String charset, 
            Integer timeout, Object entityRequest, String entityCharset, String entityMimeType, 
            boolean preemtiveAuth, boolean fiatcCertificate) throws Exception   {
        // Default values
        if (charset == null) charset = "UTF-8";
        if (timeout == null) timeout = 30000;

        // URI
        URI uri = new URI(url);
        

    // Creamos get o post
    if (StringUtils.equals(StringUtils.trim(method), "post"))
    {
        // Creamos post
        HttpPost httpPost = new HttpPost(url);

        // Insertamos params en post
        if (formparams != null)
        {
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, charset);
            httpPost.setEntity(entity);                
        }
        
        // Insertamos entity en post (también multiparts,...)
        insertEntity(httpPost, null, entityRequest, entityMimeType, entityCharset);

        // Ponemos en uriRequest
        httpPost.setConfig(requestConfig);            
        uriRequest = httpPost;
    }

  private static void insertEntity(HttpPost httpPost, HttpPut httpPut, Object entityRequest, String entityMimeType, String entityCharset) throws UnsupportedEncodingException
    {
        // Miramos si existe entidad
        if (entityRequest == null) return;
        
        // Creamos contentType
        ContentType contentType = null;
        if (entityMimeType != null)
        {
            if (entityCharset == null)  contentType = ContentType.create(entityMimeType);
            else                        contentType = ContentType.create(entityMimeType, entityCharset);
        }

post人呼叫:

再次抱歉,我提出问题的方式有任何格式错误

终于解决了

问题在我们的框架中很深,但一旦发现就很容易解决:

当您将实体作为 Post 调用发送并且它具有特殊字符时,您通常会对它进行编码。正如 ewramner 建议我检查并确认我们已经对实体进行了良好编码,但此时将实体发送到 API,我们丢失了字符集配置(不是全局配置,而是实体配置)

解决方案是在实体类型中添加实体的特定字符集,如下所示:

data.put("entity", paramsCrear.toString());
data.put("entity_mime_type", "application/json");
data.put("entity_charset", "UTF-8");

似乎 postman 会自动将这个 entity_charset 添加到你创建的每个 form-data 中,这就是为什么我在寻找这个特定点时遇到问题。

非常感谢@ewramner 和@Scary_wombat

每个人,请记住,如果您在 java 中对实体使用 post 调用,您可能需要指定对实体进行编码的字符集(事件如果它是也放入 headers。