Hi,
I have arranged the logic to send the request and the body to Tomcat, now it works for both chunked and not-chunked.
What is not yet working is when the Tomcat starts to send data before having all the body and then reads a little more body data.
Cheers
Jean-Frederic
Index: proxy_ajp.c =================================================================== RCS file: /home/cvspublic/httpd-2.0/modules/proxy/proxy_ajp.c,v retrieving revision 1.13 diff -u -r1.13 proxy_ajp.c --- proxy_ajp.c 11 Aug 2004 23:08:04 -0000 1.13 +++ proxy_ajp.c 13 Aug 2004 16:11:00 -0000 @@ -107,6 +107,10 @@ apr_status_t status; int result; apr_bucket_brigade *input_brigade; + ajp_msg_t *msg; + apr_size_t bufsiz; + char *buff; + const char *tenc; /* * Send the AJP request to the remote server @@ -123,51 +127,59 @@ return HTTP_SERVICE_UNAVAILABLE; } - /* read the first bloc of data */ - input_brigade = apr_brigade_create(p, r->connection->bucket_alloc); - status = ap_get_brigade(r->input_filters, input_brigade, - AP_MODE_READBYTES, APR_BLOCK_READ, - AJP13_MAX_SEND_BODY_SZ); - + /* allocate an AJP message to store the data of the buckets */ + status = ajp_alloc_data_msg(r, &buff, &bufsiz, &msg); if (status != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "proxy: ap_get_brigade failed"); - apr_brigade_destroy(input_brigade); - return HTTP_INTERNAL_SERVER_ERROR; + "proxy: ajp_alloc_data_msg failed"); + return status; } - - /* have something */ - if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { + /* read the first bloc of data */ + input_brigade = apr_brigade_create(p, r->connection->bucket_alloc); + tenc = apr_table_get(r->headers_in, "Transfer-Encoding"); + if (tenc && strcasecmp(tenc, "chunked")==0) { + /* The AJP protocol does not want body data yet */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, - "proxy: APR_BUCKET_IS_EOS"); - } - - if (1) { /* XXXX only when something to send ? */ - ajp_msg_t *msg; - apr_size_t bufsiz; - char *buff; - status = ajp_alloc_data_msg(r, &buff, &bufsiz, &msg); + "proxy: request is chunked"); + } else { + status = ap_get_brigade(r->input_filters, input_brigade, + AP_MODE_READBYTES, APR_BLOCK_READ, + AJP13_MAX_SEND_BODY_SZ); + if (status != APR_SUCCESS) { - return status; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: ap_get_brigade failed"); + apr_brigade_destroy(input_brigade); + return HTTP_INTERNAL_SERVER_ERROR; } + + /* have something */ + if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: APR_BUCKET_IS_EOS"); + } + + /* Try to send something */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: data to read (max %d at %08x)", bufsiz, buff); - /* XXXX calls apr_brigade_flatten... */ status = apr_brigade_flatten(input_brigade, buff, &bufsiz); if (status != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, - "proxy: apr_brigade_flatten"); + apr_brigade_destroy(input_brigade); + ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, + "proxy: apr_brigade_flatten"); return HTTP_INTERNAL_SERVER_ERROR; } + apr_brigade_cleanup(input_brigade); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: got %d byte of data", bufsiz); if (bufsiz > 0) { status = ajp_send_data_msg(conn->sock, r, msg, bufsiz); if (status != APR_SUCCESS) { + apr_brigade_destroy(input_brigade); ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, - "proxy: request failed to %pI (%s)", + "proxy: send failed to %pI (%s)", conn->worker->cp->addr, conn->worker->hostname); return HTTP_SERVICE_UNAVAILABLE; @@ -179,8 +191,9 @@ status = ajp_read_header(conn->sock, r, (ajp_msg_t **)&(conn->data)); if (status != APR_SUCCESS) { + apr_brigade_destroy(input_brigade); ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, - "proxy: request failed to %pI (%s)", + "proxy: read response failed from %pI (%s)", conn->worker->cp->addr, conn->worker->hostname); return HTTP_SERVICE_UNAVAILABLE; @@ -188,26 +201,76 @@ /* parse the reponse */ result = ajp_parse_type(r, conn->data); + + bufsiz = AJP13_MAX_SEND_BODY_SZ; + while (result == CMD_AJP13_GET_BODY_CHUNK && bufsiz != 0) { + if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(input_brigade))) { + /* That is the end */ + bufsiz = 0; + ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server, + "proxy: APR_BUCKET_IS_EOS"); + } else { + status = ap_get_brigade(r->input_filters, input_brigade, + AP_MODE_READBYTES, APR_BLOCK_READ, + AJP13_MAX_SEND_BODY_SZ); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server, + "ap_get_brigade failed"); + break; + } + bufsiz = AJP13_MAX_SEND_BODY_SZ; + status = apr_brigade_flatten(input_brigade, buff, &bufsiz); + apr_brigade_cleanup(input_brigade); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server, + "apr_brigade_flatten failed"); + break; + } + } + + ajp_msg_reset(msg); /* will go in ajp_send_data_msg */ + status = ajp_send_data_msg(conn->sock, r, msg, bufsiz); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server, + "ajp_send_data_msg failed"); + break; + } + /* read the response */ + status = ajp_read_header(conn->sock, r, + (ajp_msg_t **)&(conn->data)); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, status, r->server, + "ajp_read_header failed"); + break; + } + result = ajp_parse_type(r, conn->data); + } + apr_brigade_destroy(input_brigade); + + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, + "proxy: send body failed to %pI (%s)", + conn->worker->cp->addr, + conn->worker->hostname); + return HTTP_SERVICE_UNAVAILABLE; + } + + /* Nice we have answer to send to the client */ if (result == CMD_AJP13_SEND_HEADERS) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: got response from %pI (%s)", conn->worker->cp->addr, conn->worker->hostname); - return HTTP_SERVICE_UNAVAILABLE; + return OK; } - /* XXXX: need logic to send the rest of the data */ -/* - status = ajp_send_data(p_conn->sock,r); - if (status != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, - "proxy: request failed to %pI (%s)", - p_conn->addr, p_conn->name); - return status; - } - */ + ap_log_error(APLOG_MARK, APLOG_ERR, status, r->server, + "proxy: got bad response (%d) from %pI (%s)", + result, + conn->worker->cp->addr, + conn->worker->hostname); - return OK; + return HTTP_SERVICE_UNAVAILABLE; } /* @@ -261,7 +324,7 @@ if (status != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error reading headers from remote " - "server %s:%d", + "server %pI:%s", backend->worker->cp->addr, backend->worker->hostname); return ap_proxyerror(r, HTTP_BAD_GATEWAY,