It seems to resolve it by
making sure the entire request body is read off the netbuf before
turning around and starting the response (which occurs in this case
because an authentication challenge is sent before the entire request is
read by tomcat). I don't mean to offer this as a fix, but I was
wondering if this is a known issue and if there is a better fix
somewhere.
I sent a slightly different version of this email to the tomcat-user
list a couple of weeks ago and apologize for the cross-post.
Thanks,
Kevin Convy
Icebox LLC
static int ajp_process_callback(jk_msg_buf_t *msg,
jk_msg_buf_t *pmsg,
ajp_endpoint_t * ae,
jk_ws_service_t *r, jk_logger_t *l)
{
int code = (int)jk_b_get_byte(msg);
// KCADD
int bytesread = 0;
unsigned char buf1[AJP13_MAX_SEND_BODY_SZ];
JK_TRACE_ENTER(l);
switch (code) {
case JK_AJP13_SEND_HEADERS:
{
jk_res_data_t res;
if (!ajp_unmarshal_response(msg, &res, ae, l)) {
jk_log(l, JK_LOG_ERROR,
"ajp_unmarshal_response failed\n");
JK_TRACE_EXIT(l);
return JK_AJP13_ERROR;
}
//KCADD
// make sure the entire request body has been read.
jk_log(l, JK_LOG_INFO, "KCDEBUG: this many bytes left: %d",
ae->left_bytes_to_send);
while(ae->left_bytes_to_send > 0) {
r->read(r, buf1, AJP13_MAX_SEND_BODY_SZ, &bytesread);
ae->left_bytes_to_send -= bytesread;
}
r->start_response(r, res.status, res.msg,
(const char *const *)res.header_names,
(const char *const *)res.header_values,
res.num_headers);
}
return JK_AJP13_SEND_HEADERS;
case JK_AJP13_SEND_BODY_CHUNK:
{
unsigned len = (unsigned)jk_b_get_int(msg);
if (!r->write(r, jk_b_get_buff(msg) + jk_b_get_pos(msg),
len)) {
jk_log(l, JK_LOG_INFO,
"Connection aborted or network problems\n");
JK_TRACE_EXIT(l);
return JK_CLIENT_ERROR;
}
}
break;
case JK_AJP13_GET_BODY_CHUNK:
{
int len = (int)jk_b_get_int(msg);
if (len < 0) {
len = 0;
}
if (len > AJP13_MAX_SEND_BODY_SZ) {
len = AJP13_MAX_SEND_BODY_SZ;
}
if ((unsigned int)len > ae->left_bytes_to_send) {
len = ae->left_bytes_to_send;
}
/* the right place to add file storage for upload */
if ((len = ajp_read_into_msg_buff(ae, r, pmsg, len, l)) >=
0) {
r->content_read += len;
JK_TRACE_EXIT(l);
return JK_AJP13_HAS_RESPONSE;
}
jk_log(l, JK_LOG_INFO,
"Connection aborted or network problems\n");
JK_TRACE_EXIT(l);
return JK_CLIENT_ERROR;
}
break;
case JK_AJP13_END_RESPONSE:
{
ae->reuse = (int)jk_b_get_byte(msg);
if (!ae->reuse) {
/*
* Strange protocol error.
*/
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG, "Reuse: %d\n", ae->reuse);
ae->reuse = JK_FALSE;
}
/* Reuse in all cases */
ae->reuse = JK_TRUE;
}
JK_TRACE_EXIT(l);
return JK_AJP13_END_RESPONSE;
break;
default:
jk_log(l, JK_LOG_ERROR,
"Invalid code: %d\n", code);
JK_TRACE_EXIT(l);
return JK_AJP13_ERROR;
}
JK_TRACE_EXIT(l);
return JK_AJP13_NO_RESPONSE;
}