1

I am able to send the following request using browser and receive the correct response, but when I send it using following code the server return an error.

I suspect the problem is that Java puts the xml attributes in "request version" part of HTTP request.

String QueryString = "http://xml.example.com/service?"
            + "<List>"
            + "<Credentials username=\"example\" password=\"example1\" remoteIp=\"X.X.X.X\"/>"
            + "<Id>10202</Id>"
            + "</List>";

    try {
        URL page = new URL(QueryString);

        StringBuffer text = new StringBuffer();

        HttpURLConnection conn = (HttpURLConnection) page.openConnection();
        conn.connect();

        InputStreamReader in = new InputStreamReader(
                (InputStream) conn.getContent());

I had a look at the request being sent using WireShark.

GET /service?<List><Credentials username="example" password="example1" remoteIp="X.X.X.X"/<Id>10202</Id></List>
....
Request URI: /service?<List><Credentials
Request Version: username="example" password="example1" remoteIp="X.X.X.X"/<Id>10202</Id></List> HTTP/1.1

Server's result is

  XML document structures must start and end within the same entity.
  • This is very (let me stress that *VERY*) ugly, sending data in a query string like that. Use body of POST request instead. – Pavel Horal Nov 30 '13 at 12:05
  • Also to your question - the problem might be URI encoding. Browsers are doing encoding automatically (without user noticing it). In Java code, you need to do it manually or construct URL object semantically. – Pavel Horal Nov 30 '13 at 12:07
  • 1
    It even looks like you are trying to do authentication like this. URL gets dumped in access logs, so you will expose user credentials in these files. – Pavel Horal Nov 30 '13 at 12:11
  • @PavelHoral would you help me to put it in the body please –  Nov 30 '13 at 12:20
  • Sending POST via JRE components might be a bit annoying (http://www.mkyong.com/java/how-to-send-http-request-getpost-in-java/). Check Apache HTTP Components library... http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e171 . – Pavel Horal Nov 30 '13 at 23:06
  • @PavelHoral whats he best option? whats do you recommend? –  Dec 01 '13 at 04:39
  • I personally would go for HTTP Components... – Pavel Horal Dec 01 '13 at 12:05
  • actually it should be done by HTTPS not http. I did that to be able to see the content of requests using wireshark. Whats your suggestion for https ? –  Dec 02 '13 at 07:39

1 Answers1

0

I'll echo the comments to the question saying that this is a rather poor choice of representation on the part of the server you're communicating with, but if it's the only option that the provider of the service offers then...

If the server requires a URI-encoded query string then you could use the multiple argument constructors of java.net.URI to handle the necessary escaping for you:

URI uri = new URI("http", "xml.example.com", "/service",
          "<List>"
        + "<Credentials username=\"example\" password=\"example1\" remoteIp=\"X.X.X.X\"/>"
        + "<Id>10202</Id>"
        + "</List>", null);
URL page = uri.toURL();

If instead it requires application/x-www-form-urlencoded format (spaces are + rather than %20) then you can use URLEncoder:

URL page = new URL("http://xml.example.com/service?"
    + URLEncoder.encode("<List>"
        + "<Credentials username=\"example\" password=\"example1\" remoteIp=\"X.X.X.X\"/>"
        + "<Id>10202</Id>"
        + "</List>", "UTF-8"));

If you want to POST the data in the request body rather than supplying it in the URL then you need something more like this (exception handling omitted for clarity).

URL page = new URL("http://xml.example.com/service");
HttpURLConnection connection = page.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/xml"); // or text/xml
connection.setDoOutput(true); // need to call this before you can getOutputStream

// write the XML as UTF-8 (which is what an XML parser will expect as you're
// sending it without an <?xml declaration that says anything different)
Writer writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
writer.write("<List>"
        + "<Credentials username=\"example\" password=\"example1\" remoteIp=\"X.X.X.X\"/>"
        + "<Id>10202</Id>"
        + "</List>");
writer.close();
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • thanks, it works as required URI-encoded query string. actually the server needs to be https, the reason I used the http was to be able to make the requests and responses readable and am also highly interested in having the request in post body would you help me with that? should I ask this in a separate question ? –  Nov 30 '13 at 22:29
  • 1
    @Alex I've added an example of how to do this, it's essentially the same as you've shown you already do in [one of your earlier questions](http://stackoverflow.com/q/20190364/592139). – Ian Roberts Dec 01 '13 at 16:32