javaurlhttpconnection

java.lang.IllegalArgumentException in URL's path in Java


I have a java code that sends a web service request to the interfaces. Now for one of the interface I a getting the following error

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)

I guess this is because of the "-" in the URL but not sure. Can someone please let me know how to encode the path of a URL or is there some other way to handle this. This is how my java code looks like now

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

Also, the same code works fine in another server with the same URL. The only difference is of java 1.7 and 1.8 between the two servers. So is this a new functionality in java 1.8?


Solution

  • HTTP 1.1 is defined in RFC 2616. Headers are defined in section 4.2, which refers to RFC 822, which defines them is section 3.2, which itself defines header field names as

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

    That means that you can't use a colon (:) in an header's name.

    When you do httpconn.setRequestProperty(smsService, smsService); you're setting a field name containing a : (the one in http://...) which is fine for the value, but not for the name.

    That header doesn't seem to make sense anyway so you should be able to safely delete that whole line from your code.

    EDIT:

    I just noticed you're not using the class I thought you were using. You're using sun.net.www.protocol.http.HttpURLConnection instead of java.net.HttpURLConnection.

    That would explain why it works in Java 7, because if you look at the source code for the checkMessageHeader method in that class it doesn't check whether it contains :

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

    While, for example the current version of openjdk does.

    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 ...
    

    I'm not sure what version of java 8 you're running this on, since in the available source code for OpenJDK 8 the row numbers don't correspond with your exception, and OpenJDK 8 doesn't seem to have that check either.