2698
2724
http->request = requestLink(request);
2700
* We need to set the keepalive flag before doing some
2701
* hacks for POST/PUT requests below. Maybe we could
2702
* set keepalive flag even earlier.
2704
2725
clientSetKeepaliveFlag(http);
2706
* break here if the request has a content-length
2707
* because there is a reqeust body following and we
2708
* don't want to parse it as though it was new request.
2710
if (request->content_length >= 0) {
2711
int copy_len = XMIN(conn->in.offset, request->content_length);
2713
assert(conn->in.offset >= copy_len);
2714
request->body_sz = copy_len;
2715
request->body = xmalloc(request->body_sz);
2716
xmemcpy(request->body, conn->in.buf, request->body_sz);
2717
conn->in.offset -= copy_len;
2718
if (conn->in.offset)
2719
xmemmove(conn->in.buf, conn->in.buf + copy_len, conn->in.offset);
2722
* if we didn't get the full body now, then more will
2723
* be arriving on the client socket. Lets cancel
2724
* the read handler until this request gets forwarded.
2726
if (request->body_sz < request->content_length)
2727
commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
2728
if (request->content_length < 0)
2730
else if (clientRequestBodyTooLarge(request->content_length)) {
2726
/* Do we expect a request-body? */
2727
if (request->content_length > 0) {
2728
conn->body.size_left = request->content_length;
2729
request->body_connection = conn;
2730
/* Is it too large? */
2731
if (clientRequestBodyTooLarge(request->content_length)) {
2731
2732
err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE);
2732
2733
err->request = requestLink(request);
2733
2734
http->entry = clientCreateStoreEntry(http,
2780
} /* while offset > 0 && conn->body.size_left == 0 */
2781
/* Check if a half-closed connection was aborted in the middle */
2782
if (F->flags.socket_eof) {
2783
if (conn->in.offset != conn->body.size_left) { /* != 0 when no request body */
2784
/* Partial request received. Abort client connection! */
2785
debug(33, 3) ("clientReadRequest: FD %d aborted\n", fd);
2792
/* file_read like function, for reading body content */
2794
clientReadBody(request_t * request, char *buf, size_t size, CBCB * callback, void *cbdata)
2796
ConnStateData *conn = request->body_connection;
2798
debug(33, 5) ("clientReadBody: no body to read, request=%p\n", request);
2799
callback(buf, 0, cbdata); /* Signal end of body */
2802
debug(33, 2) ("clientReadBody: start fd=%d body_size=%d in.offset=%d cb=%p req=%p\n", conn->fd, conn->body.size_left, conn->in.offset, callback, request);
2803
conn->body.callback = callback;
2804
conn->body.cbdata = cbdata;
2805
conn->body.buf = buf;
2806
conn->body.bufsize = size;
2807
conn->body.request = requestLink(request);
2808
if (conn->in.offset) {
2809
/* Data available */
2810
clientProcessBody(conn);
2812
debug(33, 2) ("clientReadBody: fd %d wait for clientReadRequest\n", conn->fd);
2816
/* Called by clientReadRequest to process body content */
2818
clientProcessBody(ConnStateData * conn)
2821
char *buf = conn->body.buf;
2822
void *cbdata = conn->body.cbdata;
2823
CBCB *callback = conn->body.callback;
2824
request_t *request = conn->body.request;
2825
/* Note: request is null while eating "aborted" transfers */
2826
debug(33, 2) ("clientProcessBody: start fd=%d body_size=%d in.offset=%d cb=%p req=%p\n", conn->fd, conn->body.size_left, conn->in.offset, callback, request);
2827
/* Some sanity checks... */
2828
assert(conn->body.size_left > 0);
2829
assert(conn->in.offset > 0);
2830
assert(callback != NULL);
2831
assert(buf != NULL);
2832
/* How much do we have to process? */
2833
size = conn->in.offset;
2834
if (size > conn->body.size_left) /* only process the body part */
2835
size = conn->body.size_left;
2836
if (size > conn->body.bufsize) /* don't copy more than requested */
2837
size = conn->body.bufsize;
2838
xmemcpy(buf, conn->in.buf, size);
2839
conn->body.size_left -= size;
2840
/* Move any remaining data */
2841
conn->in.offset -= size;
2842
if (conn->in.offset > 0)
2843
xmemmove(conn->in.buf, conn->in.buf + size, conn->in.offset);
2844
/* Remove request link if this is the last part of the body, as
2845
* clientReadRequest automatically continues to process next request */
2846
if (conn->body.size_left <= 0 && request != NULL)
2847
request->body_connection = NULL;
2848
/* Remove clientReadBody arguments (the call is completed) */
2849
conn->body.request = NULL;
2850
conn->body.callback = NULL;
2851
conn->body.buf = NULL;
2852
conn->body.bufsize = 0;
2853
/* Remember that we have touched the body, not restartable */
2854
if (request != NULL)
2855
request->flags.body_sent = 1;
2856
/* Invoke callback function */
2857
callback(buf, size, cbdata);
2858
if (request != NULL)
2859
requestUnlink(request); /* Linked in clientReadBody */
2860
debug(33, 2) ("clientProcessBody: end fd=%d size=%d body_size=%d in.offset=%d cb=%p req=%p\n", conn->fd, size, conn->body.size_left, conn->in.offset, callback, request);
2864
/* A dummy handler that throws away a request-body */
2865
static char bodyAbortBuf[SQUID_TCP_SO_RCVBUF];
2867
clientReadBodyAbortHandler(char *buf, size_t size, void *data)
2869
ConnStateData *conn = (ConnStateData *) data;
2870
debug(33, 2) ("clientReadBodyAbortHandler: fd=%d body_size=%d in.offset=%d\n", conn->fd, conn->body.size_left, conn->in.offset);
2871
if (size != 0 && conn->body.size_left != 0) {
2872
debug(33, 3) ("clientReadBodyAbortHandler: fd=%d shedule next read\n", conn->fd);
2873
conn->body.callback = clientReadBodyAbortHandler;
2874
conn->body.buf = bodyAbortBuf;
2875
conn->body.bufsize = sizeof(bodyAbortBuf);
2876
conn->body.cbdata = data;
2880
/* Abort a body request */
2882
clientAbortBody(request_t * request)
2884
ConnStateData *conn = request->body_connection;
2888
request->body_connection = NULL;
2889
if (!conn || conn->body.size_left <= 0)
2890
return 0; /* No body to abort */
2891
if (conn->body.callback != NULL) {
2892
buf = conn->body.buf;
2893
callback = conn->body.callback;
2894
cbdata = conn->body.cbdata;
2895
assert(request == conn->body.request);
2896
conn->body.buf = NULL;
2897
conn->body.callback = NULL;
2898
conn->body.cbdata = NULL;
2899
conn->body.request = NULL;
2900
callback(buf, -1, cbdata); /* Signal abort to clientReadBody caller */
2901
requestUnlink(request);
2903
clientReadBodyAbortHandler(NULL, -1, conn); /* Install abort handler */
2904
/* clientProcessBody() */
2905
return 1; /* Aborted */
2782
2908
/* general lifetime handler for HTTP requests */