Harmony
  1. Harmony
  2. HARMONY-3717

[classlib][luni] java.net.HttpURLConnection.getResponseCode() anomoly

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      Windows XP SP2
      c:\java\hre50\bin\java -version
      svn = r530500, (Apr 20 2007), Windows/ia32/msvc 1310, release build
    • Estimated Complexity:
      Unknown

      Description

      I am trying to see if OpenJNLP works with Harmony. OpenJNLP is a pretty old implementation of the JNLP protocol w/o security. I hacked OpenJNLP to recognize Windows XP and then try to load a jnlp app from the the web (http://www.eclipse.org/swt/jws/controlexample.jnlp in this case). It fails with

      java.io.IOException: Bad Request
      at org.nanode.jnlp.JNLPParser$URLJNLPParser.openInputStream(JNLPParser.java:491)
      at org.nanode.jnlp.JNLPParser.parse(JNLPParser.java:119)
      at org.nanode.jnlp.JNLPParser.parseDescriptor(JNLPParser.java:292)
      at org.nanode.app.openjnlp.DefaultAppHandler.handleOpenURL(Unknown Source)
      at org.nanode.app.OpenJNLP.main(Unknown Source)
      Launching failed: http://www.eclipse.org/swt/jws/controlexample.jnlp

      [It works with the Sun JVM].

      Instrumenting the code shows that the following basic code is executed
      URLConnection uc = srcURL.openConnection();
      if (uc instanceof HttpURLConnection) {
      HttpURLConnection huc = (HttpURLConnection) uc;
      if (huc.getResponseCode() != HttpURLConnection.HTTP_OK)

      { throw new IOException(huc.getResponseMessage()); }

      }

      getResponseCode() is returning error 400 and thus the app throws the exception. I noted that if I insert a call to huc.getHeaderFields() before the if that checks the response code, I will subsequently get a response 200 (HTTP_OK) and things proceed. It appears like there is some sort of race or deferral in populating the response codes here. Note that instead of calling huc.getHeaderFields(), I tried putting a 5 sec sleep in and it did NOT fix it. It doesn't look like it is a normal race.

      Note that it works with the Sun VM without any mods at all.

      Note that I am using a proxy server via -Dproxyset=true -DproxyHost=xxx -DproxyPort=yyy at the java command line.

      1. http.java
        0.6 kB
        Chris Elford
      2. network.txt
        4 kB
        Chris Elford

        Issue Links

          Activity

          Hide
          Alexey Petrenko added a comment -

          Chris,
          have you tried to run your test on Harmony+J9?
          It looks like this issue is similar to HARMONY-4775 and Tim has reported that HARMONY-4775 is not reproducible with Harmony+J9...

          Show
          Alexey Petrenko added a comment - Chris, have you tried to run your test on Harmony+J9? It looks like this issue is similar to HARMONY-4775 and Tim has reported that HARMONY-4775 is not reproducible with Harmony+J9...
          Hide
          Chris Elford added a comment -

          No, I have only tried to run on pure Apache Harmony. I had the version of J9 capable of running with Harmony classlibs briefly on one of my systems earlier this year but removed it.

          I have also not retried with a build more recent than r530500. I can retry with M3 if you want.

          Show
          Chris Elford added a comment - No, I have only tried to run on pure Apache Harmony. I had the version of J9 capable of running with Harmony classlibs briefly on one of my systems earlier this year but removed it. I have also not retried with a build more recent than r530500. I can retry with M3 if you want.
          Hide
          Jimmy, Jing Lv added a comment -

          Hi,
          I've try a little test [1] on HttpURLConnection on my desktop (windows xp sp2, with J9 and DRLVM), however find no failures. Am I missing something?

          [1] An example test
          public class HttpTest extends TestCase {
          public void testHttp() throws Exception {
          URL srcURL = new URL("http://www.eclipse.org/swt/jws/controlexample.jnlp");
          URLConnection uc = srcURL.openConnection();
          if (uc instanceof HttpURLConnection) {
          HttpURLConnection huc = (HttpURLConnection) uc;
          if (huc.getResponseCode() != HttpURLConnection.HTTP_OK)

          { throw new IOException(huc.getResponseMessage()); }

          }
          }
          }

          Show
          Jimmy, Jing Lv added a comment - Hi, I've try a little test [1] on HttpURLConnection on my desktop (windows xp sp2, with J9 and DRLVM), however find no failures. Am I missing something? [1] An example test public class HttpTest extends TestCase { public void testHttp() throws Exception { URL srcURL = new URL("http://www.eclipse.org/swt/jws/controlexample.jnlp"); URLConnection uc = srcURL.openConnection(); if (uc instanceof HttpURLConnection) { HttpURLConnection huc = (HttpURLConnection) uc; if (huc.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new IOException(huc.getResponseMessage()); } } } }
          Hide
          Chris Elford added a comment -

          It fails for me...

          import java.io.IOException;
          import java.net.HttpURLConnection;
          import java.net.URL;
          import java.net.URLConnection;

          public class http {
          public static void main(String[] args) throws Exception {
          URL srcURL = new URL("http://www.eclipse.org/swt/jws/controlexample.jnlp");
          URLConnection uc = srcURL.openConnection();
          if (uc instanceof HttpURLConnection) {
          HttpURLConnection huc = (HttpURLConnection) uc;
          //huc.getHeaderFields();
          if (huc.getResponseCode() != HttpURLConnection.HTTP_OK)

          { throw new IOException(huc.getResponseMessage()); }


          }
          }
          }

          C:\java\workloads\http>c:\java\hre50m3\bin\java -DproxySet=true -DproxyHost=XXX -DproxyPort=YYY http
          Uncaught exception in main:
          java.io.IOException: Bad Request
          at http.main(http.java:14)

          Note if I uncomment the commented line, it starts to work. There is something weird going on with connections.

          Note on an unrelated note that some time ago when I went and looked at the HTTP code in Harmony it seemed like there was an assumption that HTTP requests were repeatable. I seem to remember some code that resubmitted the http request to get headers if headers were requested later. I forget if I filed this as a JIRA or not. Hopefully, this has been resolved. I'd hate to see that happen when the URL was posting a credit card transaction...

          Show
          Chris Elford added a comment - It fails for me... import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; public class http { public static void main(String[] args) throws Exception { URL srcURL = new URL("http://www.eclipse.org/swt/jws/controlexample.jnlp"); URLConnection uc = srcURL.openConnection(); if (uc instanceof HttpURLConnection) { HttpURLConnection huc = (HttpURLConnection) uc; //huc.getHeaderFields(); if (huc.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new IOException(huc.getResponseMessage()); } } } } C:\java\workloads\http>c:\java\hre50m3\bin\java -DproxySet=true -DproxyHost=XXX -DproxyPort=YYY http Uncaught exception in main: java.io.IOException: Bad Request at http.main(http.java:14) Note if I uncomment the commented line, it starts to work. There is something weird going on with connections. Note on an unrelated note that some time ago when I went and looked at the HTTP code in Harmony it seemed like there was an assumption that HTTP requests were repeatable. I seem to remember some code that resubmitted the http request to get headers if headers were requested later. I forget if I filed this as a JIRA or not. Hopefully, this has been resolved. I'd hate to see that happen when the URL was posting a credit card transaction...
          Hide
          Chris Elford added a comment -

          case that fails behind a proxy.

          Show
          Chris Elford added a comment - case that fails behind a proxy.
          Hide
          Chris Elford added a comment -

          Alexey notes that this seems to have similar symptoms.

          Show
          Chris Elford added a comment - Alexey notes that this seems to have similar symptoms.
          Hide
          Jimmy, Jing Lv added a comment -

          Hi Chris,

          Yes, I've tried proxy, with command line "java -DproxySet=true -DproxyHost=myproxy -DproxyPort=80 http" , it passed silently.
          BTW, my proxy is a http proxy. And one thing strange is that if I mis-type myproxy name, it passes anyway.
          I doubt it is due to real network issue, e.g, the proxy is a little slow and Harmony does not wait for its return. I'll look into code and try to find the cause.

          Show
          Jimmy, Jing Lv added a comment - Hi Chris, Yes, I've tried proxy, with command line "java -DproxySet=true -DproxyHost=myproxy -DproxyPort=80 http" , it passed silently. BTW, my proxy is a http proxy. And one thing strange is that if I mis-type myproxy name, it passes anyway. I doubt it is due to real network issue, e.g, the proxy is a little slow and Harmony does not wait for its return. I'll look into code and try to find the cause.
          Hide
          Alexey Petrenko added a comment -

          Jimmy,

          try -Dhttp.proxyHost=myproxy -Dhttp.proxyPort=80

          Show
          Alexey Petrenko added a comment - Jimmy, try -Dhttp.proxyHost=myproxy -Dhttp.proxyPort=80
          Hide
          Chris Elford added a comment -

          network sniff with Harmony M3 and Reference implementation...

          Show
          Chris Elford added a comment - network sniff with Harmony M3 and Reference implementation...
          Hide
          Chris Elford added a comment -

          It is looking like Harmony is not following section 5.1.2 of the W3C specification for HTTP which defines a request-uri.

          ftp://ftp.isi.edu/in-notes/rfc2616.txt

          "...
          The absoluteURI form is REQUIRED when the request is being made to a
          proxy. The proxy is requested to forward the request or service it
          from a valid cache, and return the response. Note that the proxy MAY
          forward the request on to another proxy or directly to the server

          Fielding, et al. Standards Track [Page 36]

          RFC 2616 HTTP/1.1 June 1999

          specified by the absoluteURI. In order to avoid request loops, a
          proxy MUST be able to recognize all of its server names, including
          any aliases, local variations, and the numeric IP address. An example
          Request-Line would be:

          GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
          "

          Harmony sends a relative URI instead of an absolute URI.

          Thx,
          Chris

          Show
          Chris Elford added a comment - It is looking like Harmony is not following section 5.1.2 of the W3C specification for HTTP which defines a request-uri. ftp://ftp.isi.edu/in-notes/rfc2616.txt "... The absoluteURI form is REQUIRED when the request is being made to a proxy. The proxy is requested to forward the request or service it from a valid cache, and return the response. Note that the proxy MAY forward the request on to another proxy or directly to the server Fielding, et al. Standards Track [Page 36] RFC 2616 HTTP/1.1 June 1999 specified by the absoluteURI. In order to avoid request loops, a proxy MUST be able to recognize all of its server names, including any aliases, local variations, and the numeric IP address. An example Request-Line would be: GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1 " Harmony sends a relative URI instead of an absolute URI. Thx, Chris
          Hide
          Tim Ellison added a comment -

          Thanks for the analysis Chris.

          The problem is that we don't go through the proxy selector when sending a request for the default response code (GET) , so the test in o.a.h.luni.internal.net.www.protocol.http.HttpURLConnection#requestString() thinks we are not using a proxy.

          The fix is to invoke connect() – but without further testing I'm not sure if we should be left connected after getResponseCode(), so may require further investigation. If not we have to invoke the selector separately. I also don't have a real proxy handy to test with.

          My suggested fix is below, but I won't commit it until a bit more testing and somebody with a proxy can verify it for me.

          Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java
          ===================================================================
          — src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (revision 597734)
          +++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (working copy)
          @@ -1081,6 +1081,7 @@
          // Response Code Sample : "HTTP/1.0 200 OK"

          // Call connect() first since getHeaderField() doesn't return exceptions
          + connect();
          doRequest();
          if (responseCode != -1) {
          return responseCode;

          Show
          Tim Ellison added a comment - Thanks for the analysis Chris. The problem is that we don't go through the proxy selector when sending a request for the default response code (GET) , so the test in o.a.h.luni.internal.net.www.protocol.http.HttpURLConnection#requestString() thinks we are not using a proxy. The fix is to invoke connect() – but without further testing I'm not sure if we should be left connected after getResponseCode(), so may require further investigation. If not we have to invoke the selector separately. I also don't have a real proxy handy to test with. My suggested fix is below, but I won't commit it until a bit more testing and somebody with a proxy can verify it for me. Index: src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java =================================================================== — src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (revision 597734) +++ src/main/java/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnection.java (working copy) @@ -1081,6 +1081,7 @@ // Response Code Sample : "HTTP/1.0 200 OK" // Call connect() first since getHeaderField() doesn't return exceptions + connect(); doRequest(); if (responseCode != -1) { return responseCode;
          Hide
          Tim Ellison added a comment -

          The suggested fix has been committed in the LUNI module at repo revision r598265.

          Please check that it resolves the issue for you.

          Show
          Tim Ellison added a comment - The suggested fix has been committed in the LUNI module at repo revision r598265. Please check that it resolves the issue for you.
          Hide
          Chris Elford added a comment -

          well, it seems closer. The simple test (attachment #1) works now. Unfortunately the more complicated test fails with

          elf respcode=503
          java.io.IOException: Service Unavailable
          at org.nanode.jnlp.JNLPParser$URLJNLPParser.openInputStream(JNLPParser.j
          ava:496)
          at org.nanode.jnlp.JNLPParser.parse(JNLPParser.java:119)
          at org.nanode.jnlp.JNLPParser.parseDescriptor(JNLPParser.java:292)
          at org.nanode.app.openjnlp.DefaultAppHandler.handleOpenURL(Unknown Sourc
          e)
          at org.nanode.app.OpenJNLP.main(Unknown Source)

          Unless you have any ideas... I'll need to schedule a bit of time to look at in more detail and maybe snag another network packet or three.

          Show
          Chris Elford added a comment - well, it seems closer. The simple test (attachment #1) works now. Unfortunately the more complicated test fails with elf respcode=503 java.io.IOException: Service Unavailable at org.nanode.jnlp.JNLPParser$URLJNLPParser.openInputStream(JNLPParser.j ava:496) at org.nanode.jnlp.JNLPParser.parse(JNLPParser.java:119) at org.nanode.jnlp.JNLPParser.parseDescriptor(JNLPParser.java:292) at org.nanode.app.openjnlp.DefaultAppHandler.handleOpenURL(Unknown Sourc e) at org.nanode.app.OpenJNLP.main(Unknown Source) Unless you have any ideas... I'll need to schedule a bit of time to look at in more detail and maybe snag another network packet or three.
          Hide
          Chris Elford added a comment -

          Scratch that last comment. I'm guessing our proxy was down when I tried it earlier. It seems to be working fine now. I just ran my more complex test successfully 8x in a row. This is looking good.

          Thx,
          Chris

          Show
          Chris Elford added a comment - Scratch that last comment. I'm guessing our proxy was down when I tried it earlier. It seems to be working fine now. I just ran my more complex test successfully 8x in a row. This is looking good. Thx, Chris
          Hide
          Chris Elford added a comment -

          Closing as resolved. Thanks guys. Glad this could help resolve the Eclipse updates issue.

          I can now run JNLP on at least 1 JNLP workload using Harmony>598265 and the no security versionof OpenJNLP with slight tweak to get OpenJNLP to work with Windows XP.

          Show
          Chris Elford added a comment - Closing as resolved. Thanks guys. Glad this could help resolve the Eclipse updates issue. I can now run JNLP on at least 1 JNLP workload using Harmony>598265 and the no security versionof OpenJNLP with slight tweak to get OpenJNLP to work with Windows XP.
          Hide
          Tim Ellison added a comment -

          wow, it really was 'service unavailable' – a working error message

          Thanks for verifying Chris.

          Show
          Tim Ellison added a comment - wow, it really was 'service unavailable' – a working error message Thanks for verifying Chris.

            People

            • Assignee:
              Tim Ellison
              Reporter:
              Chris Elford
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development