FULL PRODUCT VERSION :
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 5.2.3790]
and also
Microsoft Windows [Version 6.1.7600]
A DESCRIPTION OF THE PROBLEM :
The HttpURLConnection class doesn't correctly handle URLs that have empty path components. For example:
http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
NOTE: that the path is empty, there is no '/' after the domain and before the '?'
According to http://www.rfc-editor.org/rfc/std/std66.txt section 3.3. It is valid for the path component to be empty. However according to http://www.rfc-editor.org/rfc/rfc2616.txt section 3.2.2 If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource.
Many HTTP libraries and browsers will handle this by automatically adding the missing '/' character. However the JDK does not do this.
The problem is complicated when the above URL is the target of a redirect. For example: http://g.live.com/xHlysk_sk/144 is redirected to http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
When java requests either of the above URLs it will fail with an HTTP response code of 400 (Bad Request).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
According to http://www.rfc-editor.org/rfc/rfc2616.txt section 3.2.2 If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource.
When generating the HTTP request Java should automatically insert a root path or '/' if the URL contained an empty path component.
The expected response would then be 200 OK assuming that everything else was OK with the target server.
ACTUAL -
Response Code was 400
java.io.IOException: Server returned HTTP response code: 400 for URL: http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1496)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1490)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1144)
at com.infor.test.TestUrls.main(TestUrls.java:18)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at com.infor.test.TestUrls.main(TestUrls.java:16)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package com.infor.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class TestUrls {
public static void main(String[] args) {
URL url = null;
try {
// url = new URL("http://g.live.com/xHlysk_sk/144");
url = new URL("http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
int code = conn.getResponseCode();
System.out.println("Response Code was " + code);
InputStream is = conn.getInputStream();
/* read data from input stream */
is.close();
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
To work around this bug I must fix the URL. I do this will the following code:
public String autoCorrectUrl(String url) throws URISyntaxException {
URI u = new URI(url);
if (u.getPath().isEmpty()) {
URI u2 = new URI(u.getScheme(),
u.getUserInfo(),
u.getHost(), u.getPort(),
"/", u.getQuery(),
u.getFragment());
return u2.toString();
} else {
return url;
}
}
However as mentioned if the target URL is the result of a redirect then you must first disable the following of redirects. Then you must process the redirects in application code while potentially fixing any redirected URLs.
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 5.2.3790]
and also
Microsoft Windows [Version 6.1.7600]
A DESCRIPTION OF THE PROBLEM :
The HttpURLConnection class doesn't correctly handle URLs that have empty path components. For example:
http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
NOTE: that the path is empty, there is no '/' after the domain and before the '?'
According to http://www.rfc-editor.org/rfc/std/std66.txt section 3.3. It is valid for the path component to be empty. However according to http://www.rfc-editor.org/rfc/rfc2616.txt section 3.2.2 If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource.
Many HTTP libraries and browsers will handle this by automatically adding the missing '/' character. However the JDK does not do this.
The problem is complicated when the above URL is the target of a redirect. For example: http://g.live.com/xHlysk_sk/144 is redirected to http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
When java requests either of the above URLs it will fail with an HTTP response code of 400 (Bad Request).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
According to http://www.rfc-editor.org/rfc/rfc2616.txt section 3.2.2 If the abs_path is not present in the URL, it MUST be given as "/" when used as a Request-URI for a resource.
When generating the HTTP request Java should automatically insert a root path or '/' if the URL contained an empty path component.
The expected response would then be 200 OK assuming that everything else was OK with the target server.
ACTUAL -
Response Code was 400
java.io.IOException: Server returned HTTP response code: 400 for URL: http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at sun.net.www.protocol.http.HttpURLConnection$6.run(HttpURLConnection.java:1496)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1490)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1144)
at com.infor.test.TestUrls.main(TestUrls.java:18)
Caused by: java.io.IOException: Server returned HTTP response code: 400 for URL: http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at com.infor.test.TestUrls.main(TestUrls.java:16)
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package com.infor.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class TestUrls {
public static void main(String[] args) {
URL url = null;
try {
// url = new URL("http://g.live.com/xHlysk_sk/144");
url = new URL("http://photos.live.com?form=MWGRAE&publ=WLPROMAIL&crea=EML_CIMS015006_Windows+Live_SK-SK_0x0_148");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
int code = conn.getResponseCode();
System.out.println("Response Code was " + code);
InputStream is = conn.getInputStream();
/* read data from input stream */
is.close();
conn.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
To work around this bug I must fix the URL. I do this will the following code:
public String autoCorrectUrl(String url) throws URISyntaxException {
URI u = new URI(url);
if (u.getPath().isEmpty()) {
URI u2 = new URI(u.getScheme(),
u.getUserInfo(),
u.getHost(), u.getPort(),
"/", u.getQuery(),
u.getFragment());
return u2.toString();
} else {
return url;
}
}
However as mentioned if the target URL is the result of a redirect then you must first disable the following of redirects. Then you must process the redirects in application code while potentially fixing any redirected URLs.