Poco::HttpClientSession.receiveResponse() throws NoMessageException without any apparent reason
Asked Answered
E

2

7

I wrote an HTTP server in Java and a client in C++ with Poco. This is a part of the C++ client code:

URI uri("http://127.0.0.1:4444");
HTTPClientSession session(uri.getHost(), uri.getPort());

HTTPRequest req(HTTPRequest::HTTP_POST,
                "/pages/page",
                HTTPMessage::HTTP_1_1);

session.sendRequest(req);
HTTPResponse res;
std::istream &is = session.receiveResponse(res);

In the last line I get the following error:

terminate called after throwing an instance of 'Poco::Net::NoMessageException'
  what():  No message received

But I don't understand why. The connection was established successfully and the page requested exists. I tried the same code with known websites (like Wikipedia) and it works without any exception.

I also tried to make the exact same request with cURL (to my server) in command-line and it shows the response of the server, so the server seems fine.

This is the original response of the server in a string form:

"HTTP/1.1 200 OK\r\n" +
"Server: [server name]\r\n" +
"Content-Type: text/xml; charset=utf-8\r\n" +
"Content-Length:" + bodyBytes.length + "\r\n" +
"Resource: " + job.resId + "\r\n\r\n" + 
"<?xml version=\"1.0\" encoding=\"UTF-8\"?><JobRequest><InputRepresentation id=\"0\"/>    <effectsList><cvtColor><code> CV_RGB2GRAY </code></cvtColor><resize><scaleFactorX> 0.5 </scaleFactorX><scaleFactorY> 0.5 </scaleFactorY><interpolation> INTER_LINEAR </interpolation></resize><GaussianBlur><kSize> 3 </kSize><sigmaX> 2 </sigmaX><sigmaY> 2 </sigmaY><borderType> BORDER_REPLICATE </borderType></GaussianBlur></effectsList></JobRequest>"

I have written a simple HTTP server which respond with a fixed response for every request, to test what's wrong. this is the code:

public class Test {
    public static void main(String[] args) {    
        try {
            ServerSocket serverSocket = new ServerSocket(4449);
            Socket clientSocket = serverSocket.accept();

            String body = "ab";
            byte[] bodyBytes = body.getBytes("UTF-8");

            String headers = "HTTP/1.1 200 OK\r\n" + 
                             "Server: Foo\r\n" +
                             "Content-Type: text/plain\r\n" +
                             "Content-Length: " + bodyBytes.length + "\r\n\r\n";

            byte[] headerBytes = headers.getBytes("UTF-8");

            byte[] responseBytes = new byte[headerBytes.length + bodyBytes.length];

            /* Fill responseBytes with the header and body bytes */
            int i = 0;
            for (int j = 0; j < headerBytes.length; ++j) {
                responseBytes[i] = headerBytes[j];
                ++i;
            }
            for (int j = 0; j < bodyBytes.length; ++j) {
                responseBytes[i] = bodyBytes[j];
                ++i;
            }
            clientSocket.getOutputStream().write(responseBytes);

        } catch (IOException e) {}
    }
}

I get the same exception even with this server. So what's wrong here?

Enterogastrone answered 24/1, 2012 at 0:3 Comment(13)
Most likely, the output of your server violates some protocol rule that cURL tolerates. If you can intercept the raw TCP connection and post the request and the response, that would help. If you just need a quick fix, try HTTP 1.0 instead of 1.1 (in the request) -- there are fewer things to get wrong.Willingham
Tried it. Got the same exception :(Enterogastrone
How can I intercept the raw TCP connection?Enterogastrone
It depends on your platform. Wireshark, tcpdump, and similar tools.Willingham
OK, I am intercepting the connection suing Wireshark. What kind of information can help you? I don't quite understand what's written there.Enterogastrone
David, I added the output of the response packet using Wireshark. I'd appreciate if you take a look.Enterogastrone
Make sure the content length header contains precisely the number of bytes in the body. (Everything after the \r\n\r\n that ends the header.)Willingham
I noticed you didn't escape the quotes in the string "<?xml version="1.0" encoding="UTF-8"?>. Are you sure the data you are sending is what you expect?Willingham
I didn't escape it because I copied the string from within a String object which held this while debugging. So the string is correct.Enterogastrone
David, I added a code to a simple HTTP server which respond with a fixed response. Even with this server I get the same exception. Can you find any error in this server?Enterogastrone
Other than the fact that it sends a response before it gets a query, it looks fine to me.Willingham
OK, this is extremely weird. It happens only during debugging of the client. But when I run it, the exception isn't thrown. Why would that happen?Enterogastrone
I don't exactly know how this bit works byte[] headerBytes = headers.getBytes("UTF-8"); but just to make sure there is no BOM, try replacing it byte[] headerBytes = headers.getBytes("ASCII");. I think UTF-8 is not permitted in HTTP header anyway.Torero
S
2

Based on experimentation, I've found that it's necessary to include a Content-Length header if you are making an empty POST request. I.e.,

req.add("Content-Length", "0");
Silicium answered 23/11, 2015 at 19:3 Comment(0)
A
0

I had to use the following sequence in my handler code for a minimal response to be received without a No message received error:

resp.setStatus( Poco::Net::HTTPResponse::HTTP_OK );
resp.setContentType( "text/json" );
ostream &out = resp.send();
out << "[]";
out.flush();
Asper answered 14/8, 2018 at 1:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.