Java 中 URL 路径中的 java.lang.IllegalArgumentException

问题描述

我有一个向接口发送 Web 服务请求的 Java 代码。现在对于其中一个界面,我收到以下错误

java.lang.IllegalArgumentException: Illegal character(s) in message header field: http://10.11.22.33:8088/platform-core/smsGateMgw
    at sun.net.www.protocol.http.HttpURLConnection.checkMessageHeader(HttpURLConnection.java:522)
    at sun.net.www.protocol.http.HttpURLConnection.isExternalMessageHeaderAllowed(HttpURLConnection.java:492)
    at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3057)
    at com.in.ci.fIoUtbound.custom.SmsSender.sendSms(SmsSender1.java:255)
    at com.in.ci.fIoUtbound.custom.SmsSender.executeOutboundRequest(SmsSender1.java:104)

我猜这是因为 URL 中的“-”,但不确定。 有人可以让我知道如何对 URL 的路径进行编码,或者是否有其他方法可以处理此问题。 这就是我的 java 代码现在的样子

URL smsServiceUrl = new URL(smsService);
URLConnection conn = smsServiceUrl.openConnection();
HttpURLConnection httpconn = (HttpURLConnection)conn;
ByteArrayOutputStream bout = new ByteArrayOutputStream();

byte[] buffer = new byte[reqXml.length()];
buffer = reqXml.getBytes();
bout.write(buffer);
byte[] b = bout.toByteArray();

httpconn.setRequestProperty("Content-Length",String.valueOf(b.length));
httpconn.setRequestProperty("Content-Type","text/xml;charset=utf-8");
httpconn.setRequestProperty(smsService,smsService);
httpconn.setRequestMethod("POST");

httpconn.setDoOutput(true);
httpconn.setDoOutput(true);

OutputStream out = httpconn.getoutputStream();
out.write(b);
InputStreamReader isr = new InputStreamReader(httpconn.getInputStream());
  
BufferedReader in = new BufferedReader(isr);
while ((responseString = in.readLine()) != null) {
    outputString = outputString + responseString;
}

此外,相同的代码在具有相同 URL 的另一台服务器中也能正常工作。唯一的区别是两台服务器之间的 java 1.7 和 1.8。那么这是 Java 1.8 中的新功能吗?

解决方法

HTTP 1.1 在 RFC 2616 中定义。 headers在4.2节定义,引用RFC 822,定义它们的是3.2节,它本身定义header字段名称为

field-name  =  1*<any CHAR,excluding CTLs,SPACE,and ":">

这意味着您不能在标题的名称中使用冒号 (:)。

当您执行 httpconn.setRequestProperty(smsService,smsService); 时,您正在设置一个包含 :http://... 中的那个)的字段名称,该名称适用于值,但不适用于名称。

>

无论如何,该标题似乎没有意义,因此您应该能够从代码中安全地删除整行。

编辑:

我刚刚注意到您没有使用我认为您正在使用的课程。您使用的是 sun.net.www.protocol.http.HttpURLConnection 而不是 java.net.HttpURLConnection

这可以解释为什么它在 Java 7 中有效,因为如果您查看该类中 checkMessageHeader 方法的 source code,它不会检查它是否包含 :>

private void checkMessageHeader(String key,String value) {
        char LF = '\n';
        int index = key.indexOf(LF);
        if (index != -1) {
            throw new IllegalArgumentException(
                "Illegal character(s) in message header field: " + key);
        }

        else {
            if (value == null) {
                return;
            }

            index = value.indexOf(LF);
            while (index != -1) {
                index++;
                if (index < value.length()) {
                    char c = value.charAt(index);
                    if ((c==' ') || (c=='\t')) {
                        // ok,check the next occurrence
                        index = value.indexOf(LF,index);
                        continue;

                    }
                }

                throw new IllegalArgumentException(
                    "Illegal character(s) in message header value: " + value);

            }
        }
    }

虽然,例如 current version of openjdk 确实如此。

private void checkMessageHeader(String key,String value) {
    char LF = '\n';
    int index = key.indexOf(LF);
    int index1 = key.indexOf(':');
    if (index != -1 || index1 != -1) {
        throw new IllegalArgumentException(
            "Illegal character(s) in message header field: " + key);
    }
    // ... rest of the method ...

我不确定您运行的是什么版本的 java 8,因为在 OpenJDK 8 的 available source code 中,行号与您的异常不对应,而 OpenJDK 8 似乎没有也可以检查一下。