You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Garret Wilson <ga...@globalmentor.com> on 2005/01/06 21:10:30 UTC

Re: timeout when reading 401 response [was: persistent HTTP 1.1 connections with Tomcat 5.5.4?]

It looks like the timeout is occurring when the first response is being 
read, so this changes the problem.

I'm receiving a 401 Unauthorized response with the following headers:

Server: Apache-Coyote/1.1
WWW-Authenticate: [...]
Content-Type: text/html;charset=utf-8
Content-Length: 952
Date: Thu, 06 Jan 2005 19:47:43 GMT

I try to read the 952 bytes, and that's when I get the 15-second hang 
before a timeout.

The response is generated on the server with:

response.sendError(401);

Where are those 952 bytes, and why can't I read them, I wonder?

Garret

Garret Wilson wrote:
> Does Tomcat 5.5.4 support HTTP 1.1 persistent connections?
> 
> I'm connecting to a Tomcat servlet from a custom Java client, and the 
> first request/response goes fine:
> 
> socketAddress=new InetSocketAddress(host, port);
> channel=SocketChannel.open(socketAddress);
> inputStream=new BufferedInputStream(newInputStream(channel));
> outputStream=new BufferedOutputStream(newOutputStream(channel));
> 
> The response headers do *not* have a "Connection: close" header, which 
> means the connection should stay open.
> 
> The response is a 401 Unauthorized, so I place credentials in the 
> request and send it again to the same output stream. Then I try to read 
> another response from the same input stream. My program hangs until the 
> connection times out.
> 
> What the matter with persistent connections here?
> 
> Thanks,
> 
> Garret
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: solved: timeout when reading 401 response [was: persistent HTTP1.1 connectionswith Tomcat 5.5.4?]

Posted by Wade Chandler <wc...@redesetgrow.com>.
Garret Wilson wrote:
> Wade Chandler wrote:
> 
>> Actually what is happening is this....  You are using a buffered 
>> stream.  It is reading past the amount returned....and then the tcp/ip 
>> socket is blocking because you have it open as a keep alive.  You have 
>> to only read the number of bytes available and not keep trying to 
>> squeeze the blood out of the turnip... ;-) I'll almost bet you money 
>> that is what is happening.  Try to not use a buffered input stream and 
>> see what you get.  If I'm wrong I'm wrong let me know.  Hope it works.
> 
> 
> Wade, thanks so very much for responding. I was sitting here dumbfounded 
> wondering what in the world could be happening.
> 
> But you're wrong. ;)
> 
> I had already thrown out the BufferedInputStream to eliminate that. I 
> switched to straight sockets. I set up a simple loop that simply read 
> bytes until receiving a timeout. The timeout occurred after the CRLF 
> divider, even though the Content-Length said 952. Accessing the site 
> from Firefox showed all the content.
> 
> Puzzled? Yeah, so was I. Then I realized that in my Java client I was 
> testing my new HTTP routines with the HEAD method!
> 
> (You can start the ridicule, now...)
> 
> The whole point of the HEAD method is that it doesn't send content---it 
> simply sends a Content-Length indicating how long the content would have 
> been. In fact, RFC 2616 says that "the server MUST NOT return a 
> message-body in the response" for the HEAD method (9.4).
> 
> Now, what threw me off is that the response was an error status, a 401 
> Unauthorized. The Content-Length is in line with the spec, returning the 
> length of the content which would have been returned if a GET had been 
> used. As an error was returned, however, the Content-Length was 
> returning the length of the error message---the error message that would 
> have been returned had a GET been used.
> 
> Now, all this is technically to the letter of RFC 2616, but I wonder 
> what would happen if a server were to send back a 405 Method Not Allowed 
> for HEAD. There would be no way to get at the error message, because 
> HEAD doesn't send back content. Using GET would succeed, so technically 
> the Content-Length of HEAD in this case wouldn't be the content length 
> of a response from GET.
> 
> I'm thinking that RFC 2616 should probably have made an exception to the 
> no content rule for HEAD when an error condition is being reported. But 
> that's the least of my worries. I just need to tell my client to ignore 
> all content in a response to HEAD. Oddly, though, this means that a 
> thread can't simply pull HTTP responses down from a persistent 
> connection without knowing to which request each response belongs---i.e. 
> whether to trust the Content-Length or not!
> 
> In any case, thanks for the input. It looks like your responses will be 
> useful when I finally switch over to non-blocking I/O support.
> 
> Garret
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
> 
> 
> 
lol.  I won't ridicule....we all make the mistakes that make us go... 
(Homer Simpson)......DOH!!!!  Glad you got it resolved.

Wade


---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: solved: timeout when reading 401 response [was: persistent HTTP 1.1 connectionswith Tomcat 5.5.4?]

Posted by Garret Wilson <ga...@globalmentor.com>.
Wade Chandler wrote:
> Actually what is happening is this....  You are using a buffered stream. 
>  It is reading past the amount returned....and then the tcp/ip socket is 
> blocking because you have it open as a keep alive.  You have to only 
> read the number of bytes available and not keep trying to squeeze the 
> blood out of the turnip... ;-) I'll almost bet you money that is what is 
> happening.  Try to not use a buffered input stream and see what you get. 
>  If I'm wrong I'm wrong let me know.  Hope it works.

Wade, thanks so very much for responding. I was sitting here dumbfounded 
wondering what in the world could be happening.

But you're wrong. ;)

I had already thrown out the BufferedInputStream to eliminate that. I 
switched to straight sockets. I set up a simple loop that simply read 
bytes until receiving a timeout. The timeout occurred after the CRLF 
divider, even though the Content-Length said 952. Accessing the site 
from Firefox showed all the content.

Puzzled? Yeah, so was I. Then I realized that in my Java client I was 
testing my new HTTP routines with the HEAD method!

(You can start the ridicule, now...)

The whole point of the HEAD method is that it doesn't send content---it 
simply sends a Content-Length indicating how long the content would have 
been. In fact, RFC 2616 says that "the server MUST NOT return a 
message-body in the response" for the HEAD method (9.4).

Now, what threw me off is that the response was an error status, a 401 
Unauthorized. The Content-Length is in line with the spec, returning the 
length of the content which would have been returned if a GET had been 
used. As an error was returned, however, the Content-Length was 
returning the length of the error message---the error message that would 
have been returned had a GET been used.

Now, all this is technically to the letter of RFC 2616, but I wonder 
what would happen if a server were to send back a 405 Method Not Allowed 
for HEAD. There would be no way to get at the error message, because 
HEAD doesn't send back content. Using GET would succeed, so technically 
the Content-Length of HEAD in this case wouldn't be the content length 
of a response from GET.

I'm thinking that RFC 2616 should probably have made an exception to the 
no content rule for HEAD when an error condition is being reported. But 
that's the least of my worries. I just need to tell my client to ignore 
all content in a response to HEAD. Oddly, though, this means that a 
thread can't simply pull HTTP responses down from a persistent 
connection without knowing to which request each response belongs---i.e. 
whether to trust the Content-Length or not!

In any case, thanks for the input. It looks like your responses will be 
useful when I finally switch over to non-blocking I/O support.

Garret

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: timeout when reading 401 response [was: persistent HTTP 1.1 connectionswith Tomcat 5.5.4?]

Posted by Wade Chandler <wc...@redesetgrow.com>.
Wade Chandler wrote:
> Wade Chandler wrote:
> 
>> Garret Wilson wrote:
>>
>>> So this is getting stranger.
>>>
>>> Just to preclude any error on my part, I did a simple loop that 
>>> output every character received from the response. The HTTP response 
>>> status line and headers come down fine, including the CRLF that 
>>> separates the headers from the body. And then---timeout after 15 
>>> seconds.
>>>
>>> But the strange part is that if I connect using Firefox, I can view 
>>> the entire response---an HTML document including the 401 status code. 
>>> This document length is---you guessed it---952 bytes long, just like 
>>> the Content-Length header says.
>>>
>>> Why can't I read the body from Java, yet Firefox can read it? Is 
>>> there a bug with Channels.newInputStream()?
>>>
>>> Garret
>>>
>>> Garret Wilson wrote:
>>>
>>>> It looks like the timeout is occurring when the first response is 
>>>> being read, so this changes the problem.
>>>>
>>>> I'm receiving a 401 Unauthorized response with the following headers:
>>>>
>>>> Server: Apache-Coyote/1.1
>>>> WWW-Authenticate: [...]
>>>> Content-Type: text/html;charset=utf-8
>>>> Content-Length: 952
>>>> Date: Thu, 06 Jan 2005 19:47:43 GMT
>>>>
>>>> I try to read the 952 bytes, and that's when I get the 15-second 
>>>> hang before a timeout.
>>>>
>>>> The response is generated on the server with:
>>>>
>>>> response.sendError(401);
>>>>
>>>> Where are those 952 bytes, and why can't I read them, I wonder?
>>>>
>>>> Garret
>>>>
>>>> Garret Wilson wrote:
>>>>
>>>>> Does Tomcat 5.5.4 support HTTP 1.1 persistent connections?
>>>>>
>>>>> I'm connecting to a Tomcat servlet from a custom Java client, and 
>>>>> the first request/response goes fine:
>>>>>
>>>>> socketAddress=new InetSocketAddress(host, port);
>>>>> channel=SocketChannel.open(socketAddress);
>>>>> inputStream=new BufferedInputStream(newInputStream(channel));
>>>>> outputStream=new BufferedOutputStream(newOutputStream(channel));
>>>>>
>>>>> The response headers do *not* have a "Connection: close" header, 
>>>>> which means the connection should stay open.
>>>>>
>>>>> The response is a 401 Unauthorized, so I place credentials in the 
>>>>> request and send it again to the same output stream. Then I try to 
>>>>> read another response from the same input stream. My program hangs 
>>>>> until the connection times out.
>>>>>
>>>>> What the matter with persistent connections here?
>>>>>
>>>>> Thanks,
>>>>>
>>>>> Garret
>>>>>
>>>>>
>>
>> Actually what is happening is this....  You are using a buffered 
>> stream.  It is reading past the amount returned....and then the tcp/ip 
>> socket is blocking because you have it open as a keep alive.  You have 
>> to only read the number of bytes available and not keep trying to 
>> squeeze the blood out of the turnip... ;-) I'll almost bet you money 
>> that is what is happening.  Try to not use a buffered input stream and 
>> see what you get.  If I'm wrong I'm wrong let me know.  Hope it works.
>>
>> Wade
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
>>
>>
>>
> 
> 
> See the read method of the SocketChannel...as I'm sure it will be 
> getting called by the InputStream wrapper from the object.  Don't think 
> about trying to make the SocketChannel so that isBlocking returns false 
> either because if all the data isn't there and it isn't blocking and the 
> buffer doesn't have any data (at that exact moment you make a call) it 
> will return as if it had read all of the data and then you'd be messed 
> up that way to.
> 
> I'm writing this all assuming you are using keep alives.....
> 
> Wade
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
> 
> 
> 

And one more tad bit....

If you really need to use buffering in this case it might make sense to 
do that in your read loop yourself so you can control the max number of 
bytes read...that or make a buffered input stream which you can set the 
max number of bytes to read into the buffer for....over all max number 
that is.

Wade


---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: timeout when reading 401 response [was: persistent HTTP 1.1 connectionswith Tomcat 5.5.4?]

Posted by Wade Chandler <wc...@redesetgrow.com>.
Wade Chandler wrote:
> Garret Wilson wrote:
> 
>> So this is getting stranger.
>>
>> Just to preclude any error on my part, I did a simple loop that output 
>> every character received from the response. The HTTP response status 
>> line and headers come down fine, including the CRLF that separates the 
>> headers from the body. And then---timeout after 15 seconds.
>>
>> But the strange part is that if I connect using Firefox, I can view 
>> the entire response---an HTML document including the 401 status code. 
>> This document length is---you guessed it---952 bytes long, just like 
>> the Content-Length header says.
>>
>> Why can't I read the body from Java, yet Firefox can read it? Is there 
>> a bug with Channels.newInputStream()?
>>
>> Garret
>>
>> Garret Wilson wrote:
>>
>>> It looks like the timeout is occurring when the first response is 
>>> being read, so this changes the problem.
>>>
>>> I'm receiving a 401 Unauthorized response with the following headers:
>>>
>>> Server: Apache-Coyote/1.1
>>> WWW-Authenticate: [...]
>>> Content-Type: text/html;charset=utf-8
>>> Content-Length: 952
>>> Date: Thu, 06 Jan 2005 19:47:43 GMT
>>>
>>> I try to read the 952 bytes, and that's when I get the 15-second hang 
>>> before a timeout.
>>>
>>> The response is generated on the server with:
>>>
>>> response.sendError(401);
>>>
>>> Where are those 952 bytes, and why can't I read them, I wonder?
>>>
>>> Garret
>>>
>>> Garret Wilson wrote:
>>>
>>>> Does Tomcat 5.5.4 support HTTP 1.1 persistent connections?
>>>>
>>>> I'm connecting to a Tomcat servlet from a custom Java client, and 
>>>> the first request/response goes fine:
>>>>
>>>> socketAddress=new InetSocketAddress(host, port);
>>>> channel=SocketChannel.open(socketAddress);
>>>> inputStream=new BufferedInputStream(newInputStream(channel));
>>>> outputStream=new BufferedOutputStream(newOutputStream(channel));
>>>>
>>>> The response headers do *not* have a "Connection: close" header, 
>>>> which means the connection should stay open.
>>>>
>>>> The response is a 401 Unauthorized, so I place credentials in the 
>>>> request and send it again to the same output stream. Then I try to 
>>>> read another response from the same input stream. My program hangs 
>>>> until the connection times out.
>>>>
>>>> What the matter with persistent connections here?
>>>>
>>>> Thanks,
>>>>
>>>> Garret
>>>>
>>>>
> 
> Actually what is happening is this....  You are using a buffered stream. 
>  It is reading past the amount returned....and then the tcp/ip socket is 
> blocking because you have it open as a keep alive.  You have to only 
> read the number of bytes available and not keep trying to squeeze the 
> blood out of the turnip... ;-) I'll almost bet you money that is what is 
> happening.  Try to not use a buffered input stream and see what you get. 
>  If I'm wrong I'm wrong let me know.  Hope it works.
> 
> Wade
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
> 
> 
> 


See the read method of the SocketChannel...as I'm sure it will be 
getting called by the InputStream wrapper from the object.  Don't think 
about trying to make the SocketChannel so that isBlocking returns false 
either because if all the data isn't there and it isn't blocking and the 
buffer doesn't have any data (at that exact moment you make a call) it 
will return as if it had read all of the data and then you'd be messed 
up that way to.

I'm writing this all assuming you are using keep alives.....

Wade


---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: timeout when reading 401 response [was: persistent HTTP 1.1 connectionswith Tomcat 5.5.4?]

Posted by Wade Chandler <wc...@redesetgrow.com>.
Garret Wilson wrote:
> So this is getting stranger.
> 
> Just to preclude any error on my part, I did a simple loop that output 
> every character received from the response. The HTTP response status 
> line and headers come down fine, including the CRLF that separates the 
> headers from the body. And then---timeout after 15 seconds.
> 
> But the strange part is that if I connect using Firefox, I can view the 
> entire response---an HTML document including the 401 status code. This 
> document length is---you guessed it---952 bytes long, just like the 
> Content-Length header says.
> 
> Why can't I read the body from Java, yet Firefox can read it? Is there a 
> bug with Channels.newInputStream()?
> 
> Garret
> 
> Garret Wilson wrote:
> 
>> It looks like the timeout is occurring when the first response is 
>> being read, so this changes the problem.
>>
>> I'm receiving a 401 Unauthorized response with the following headers:
>>
>> Server: Apache-Coyote/1.1
>> WWW-Authenticate: [...]
>> Content-Type: text/html;charset=utf-8
>> Content-Length: 952
>> Date: Thu, 06 Jan 2005 19:47:43 GMT
>>
>> I try to read the 952 bytes, and that's when I get the 15-second hang 
>> before a timeout.
>>
>> The response is generated on the server with:
>>
>> response.sendError(401);
>>
>> Where are those 952 bytes, and why can't I read them, I wonder?
>>
>> Garret
>>
>> Garret Wilson wrote:
>>
>>> Does Tomcat 5.5.4 support HTTP 1.1 persistent connections?
>>>
>>> I'm connecting to a Tomcat servlet from a custom Java client, and the 
>>> first request/response goes fine:
>>>
>>> socketAddress=new InetSocketAddress(host, port);
>>> channel=SocketChannel.open(socketAddress);
>>> inputStream=new BufferedInputStream(newInputStream(channel));
>>> outputStream=new BufferedOutputStream(newOutputStream(channel));
>>>
>>> The response headers do *not* have a "Connection: close" header, 
>>> which means the connection should stay open.
>>>
>>> The response is a 401 Unauthorized, so I place credentials in the 
>>> request and send it again to the same output stream. Then I try to 
>>> read another response from the same input stream. My program hangs 
>>> until the connection times out.
>>>
>>> What the matter with persistent connections here?
>>>
>>> Thanks,
>>>
>>> Garret
>>>
>>>

Actually what is happening is this....  You are using a buffered stream. 
  It is reading past the amount returned....and then the tcp/ip socket 
is blocking because you have it open as a keep alive.  You have to only 
read the number of bytes available and not keep trying to squeeze the 
blood out of the turnip... ;-) I'll almost bet you money that is what is 
happening.  Try to not use a buffered input stream and see what you get. 
  If I'm wrong I'm wrong let me know.  Hope it works.

Wade


---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org


Re: timeout when reading 401 response [was: persistent HTTP 1.1 connections with Tomcat 5.5.4?]

Posted by Garret Wilson <ga...@globalmentor.com>.
So this is getting stranger.

Just to preclude any error on my part, I did a simple loop that output 
every character received from the response. The HTTP response status 
line and headers come down fine, including the CRLF that separates the 
headers from the body. And then---timeout after 15 seconds.

But the strange part is that if I connect using Firefox, I can view the 
entire response---an HTML document including the 401 status code. This 
document length is---you guessed it---952 bytes long, just like the 
Content-Length header says.

Why can't I read the body from Java, yet Firefox can read it? Is there a 
bug with Channels.newInputStream()?

Garret

Garret Wilson wrote:
> It looks like the timeout is occurring when the first response is being 
> read, so this changes the problem.
> 
> I'm receiving a 401 Unauthorized response with the following headers:
> 
> Server: Apache-Coyote/1.1
> WWW-Authenticate: [...]
> Content-Type: text/html;charset=utf-8
> Content-Length: 952
> Date: Thu, 06 Jan 2005 19:47:43 GMT
> 
> I try to read the 952 bytes, and that's when I get the 15-second hang 
> before a timeout.
> 
> The response is generated on the server with:
> 
> response.sendError(401);
> 
> Where are those 952 bytes, and why can't I read them, I wonder?
> 
> Garret
> 
> Garret Wilson wrote:
> 
>> Does Tomcat 5.5.4 support HTTP 1.1 persistent connections?
>>
>> I'm connecting to a Tomcat servlet from a custom Java client, and the 
>> first request/response goes fine:
>>
>> socketAddress=new InetSocketAddress(host, port);
>> channel=SocketChannel.open(socketAddress);
>> inputStream=new BufferedInputStream(newInputStream(channel));
>> outputStream=new BufferedOutputStream(newOutputStream(channel));
>>
>> The response headers do *not* have a "Connection: close" header, which 
>> means the connection should stay open.
>>
>> The response is a 401 Unauthorized, so I place credentials in the 
>> request and send it again to the same output stream. Then I try to 
>> read another response from the same input stream. My program hangs 
>> until the connection times out.
>>
>> What the matter with persistent connections here?
>>
>> Thanks,
>>
>> Garret
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-user-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: tomcat-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tomcat-user-help@jakarta.apache.org