I've completed the part for 'HTTP/1.1 100 Continue'

From: zsx <shuxin.zheng@dont-contact.us>
Date: Wed, 25 Oct 2006 17:59:44 +0800 (CST)

Hi, I've completed the codes for 'HTTP/1.1 100 Continue', and the squid with these codes worked well, I've test some cases for it. Can anybody else give me some suggest to do it better? Thanks zsx 2006.10.25 The codes added or changed for squid are below: 1) struct.h struct _HttpStateData { StoreEntry *entry; request_t *request; MemBuf reply_hdr; + MemBuf reply_hdr_buf; /* add by zsx for HTTP1.1---10.1.1 */ ...... 2) HttpReply.c static int httpReplyParseStep(HttpReply * rep, const char *buf, int atEnd) { const char *parse_start = buf; const char *blk_start, *blk_end; const char **parse_end_ptr = &blk_end; assert(rep); assert(parse_start); assert(rep->pstate < psParsed); *parse_end_ptr = parse_start; if (rep->pstate == psReadyToParseStartLine) { if (!httpReplyIsolateStart(&parse_start, &blk_start, &blk_end)) return 0; if (!httpStatusLineParse(&rep->sline, blk_start, blk_end)) return httpReplyParseError(rep); *parse_end_ptr = parse_start; rep->hdr_sz = *parse_end_ptr - buf; + /* changed by zsx for http1.1--10.1.1 */ - rep->pstate++; + if (rep->sline.status != HTTP_CONTINUE) + rep->pstate++; ...... 3) http.c 3.1) I changed the old function from "httpProcessReplyHeader()" to "httpProcessReplyHeader()" and "httpProcessReplyHeader2()", as below: static void httpProcessReplyHeader2(HttpStateData * httpState) { StoreEntry *entry = httpState->entry; MemObject *mem = entry->mem_obj; HttpReply *reply = mem->reply; if (!peer_supports_connection_pinning(httpState)) httpState->orig_request->flags.no_connection_auth = 1; storeTimestampsSet(entry); if (httpHeaderHas(&reply->header, HDR_VARY) #if X_ACCELERATOR_VARY || httpHeaderHas(&reply->header, HDR_X_ACCELERATOR_VARY) #endif ) { const char *vary = NULL; if (Config.onoff.cache_vary) vary = httpMakeVaryMark(httpState->orig_request, reply); if (!vary) { httpMakePrivate(entry); goto no_cache; } entry->mem_obj->vary_headers = xstrdup(vary); if (strBuf(httpState->orig_request->vary_encoding)) entry->mem_obj->vary_encoding = xstrdup(strBuf(httpState->orig_request->vary_encoding)); } switch (httpCachableReply(httpState)) { case 1: httpMakePublic(entry); break; case 0: httpMakePrivate(entry); break; case -1: if (Config.negativeTtl > 0) httpCacheNegatively(entry); else httpMakePrivate(entry); break; default: assert(0); break; } no_cache: if (reply->cache_control) { if (EBIT_TEST(reply->cache_control->mask, CC_PROXY_REVALIDATE)) EBIT_SET(entry->flags, ENTRY_REVALIDATE); else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE)) EBIT_SET(entry->flags, ENTRY_REVALIDATE); } if (neighbors_do_private_keys && !Config.onoff.collapsed_forwarding) httpMaybeRemovePublic(entry, reply->sline.status); if (httpState->flags.keepalive) if (httpState->peer) httpState->peer->stats.n_keepalives_sent++; if (reply->keep_alive) { if (httpState->peer) httpState->peer->stats.n_keepalives_recv++; if (Config.onoff.detect_broken_server_pconns && httpReplyBodySize(httpState->request->method, reply) == -1) { debug(11, 1) ("httpProcessReplyHeader: Impossible keep-alive header from '%s'\n", storeUrl(entry)); debug(11, 2) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", httpState->reply_hdr.buf); httpState->flags.keepalive_broken = 1; } } if (reply->date > -1 && !httpState->peer) { int skew = abs(reply->date - squid_curtime); if (skew > 86400) debug(11, 3) ("%s's clock is skewed by %d seconds!\n", httpState->request->host, skew); } #if HEADERS_LOG headersLog(1, 0, httpState->request->method, reply); #endif } static int httpProcessReplyHeader(HttpStateData *httpState, const char *buf, int size) { char myname[] = "httpProccessReplyHeader"; StoreEntry *entry = httpState->entry; size_t hdr_len; size_t hdr_size; MemObject *mem = entry->mem_obj; HttpReply *reply = mem->reply; Ctx ctx = ctx_enter(mem->url); const char *ptr; int dlen; #undef RETURN #define RETURN(_x_) do { \ ctx_exit(ctx); \ return (_x_); \ } while (0) assert(httpState->reply_hdr_state == 0); debug(11, 3) ("%s: key '%s'\n", myname, storeKeyText(entry->hash.key)); if (memBufIsNull(&httpState->reply_hdr)) memBufDefInit(&httpState->reply_hdr); if (memBufIsNull(&httpState->reply_hdr_buf)) memBufDefInit(&httpState->reply_hdr_buf); safe_free(entry->mem_obj->vary_headers); safe_free(entry->mem_obj->vary_encoding); /* loop parse the header data, just in order to ignore * the "HTTP/1.1 100 Continue" header, http1.1--10.1.1 */ ptr = buf; dlen = size; while (1) { memBufAppend(&httpState->reply_hdr, ptr, dlen); memBufAppend(&httpState->reply_hdr_buf, ptr, dlen); hdr_len = httpState->reply_hdr.size; if (hdr_len > 4 && strncmp(httpState->reply_hdr.buf, "HTTP/", 5)) { debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", httpState->reply_hdr.buf); httpState->reply_hdr_state += 2; memBufClean(&httpState->reply_hdr); httpBuildVersion(&reply->sline.version, 0, 9); reply->sline.status = HTTP_INVALID_HEADER; if (!memBufIsNull(&httpState->reply_hdr_buf)) memBufClean(&httpState->reply_hdr_buf); RETURN (-1); } hdr_size = headersEnd(httpState->reply_hdr.buf, hdr_len); /* if "hdr_size == 0", the data in buf is not a complete http reply header, * else the http reply header is complete. */ if (hdr_size) hdr_len = hdr_size; if (hdr_len > Config.maxReplyHeaderSize) { debug(11, 1) ("httpProcessReplyHeader: Too large reply header\n"); if (!memBufIsNull(&httpState->reply_hdr)) memBufClean(&httpState->reply_hdr); if (!memBufIsNull(&httpState->reply_hdr_buf)) memBufClean(&httpState->reply_hdr_buf); reply->sline.status = HTTP_HEADER_TOO_LARGE; httpState->reply_hdr_state += 2; RETURN (-1); } /* headers can be incomplete only if object still arriving */ if (!hdr_size) { if (httpState->eof) hdr_size = hdr_len; else RETURN (0); /* headers not complete */ } /* Cut away any excess body data (only needed for debug?) */ memBufAppend(&httpState->reply_hdr, "\0", 1); httpState->reply_hdr.buf[hdr_size] = '\0'; httpState->reply_hdr_state++; assert(httpState->reply_hdr_state == 1); httpState->reply_hdr_state++; debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", httpState->reply_hdr.buf); /* Parse headers into reply structure */ /* what happens if we fail to parse here? */ httpReplyParse(reply, httpState->reply_hdr.buf, hdr_size); if (reply->sline.status == HTTP_CONTINUE) { httpState->reply_hdr_state = 0; if (!memBufIsNull(&httpState->reply_hdr)) memBufReset(&httpState->reply_hdr); if (!memBufIsNull(&httpState->reply_hdr_buf)) memBufReset(&httpState->reply_hdr_buf); } else break; if (httpState->eof) break; ptr += hdr_size; dlen -= hdr_size; assert(dlen >= 0); } /* end while */ /* the other http reply status */ if (reply->sline.status >= HTTP_INVALID_HEADER) { debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'\n", httpState->reply_hdr.buf); memBufClean(&httpState->reply_hdr); if (!memBufIsNull(&httpState->reply_hdr_buf)) memBufClean(&httpState->reply_hdr_buf); RETURN (-1); } /* Check if object is cacheable or not based on reply code */ debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %d\n", reply->sline.status); httpProcessReplyHeader2(httpState); RETURN (0); } 3.2) in httpReadReply() function static void httpReadReply(int fd, void *data) { ...... } else if (len == 0) { /* Connection closed; retrieval done. */ httpState->eof = 1; if (httpState->reply_hdr_state < 2) /* * Yes Henrik, there is a point to doing this. When we * called httpProcessReplyHeader() before, we didn't find * the end of headers, but now we are definately at EOF, so * we want to process the reply headers. */ /* hexun: changed by zsx for HTTP-ZIP, http1.1-10.1.1, 2006.10.24 */ /* httpProcessReplyHeader(httpState, buf, len); */ httpProcessReplyHeader(httpState, buf, len); /* end changed */ if (entry->mem_obj->reply->sline.status == HTTP_HEADER_TOO_LARGE) { storeEntryReset(entry); fwdFail(httpState->fwd, errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY)); httpState->fwd->flags.dont_retry = 1; } else if (entry->mem_obj->reply->sline.status == HTTP_INVALID_HEADER && !(entry->mem_obj->reply->sline.version.major == 0 && entry->mem_obj->reply->sline.version.minor == 9)) { storeEntryReset(entry); fwdFail(httpState->fwd, errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY)); httpState->fwd->flags.dont_retry = 1; } else { fwdComplete(httpState->fwd); } comm_close(fd); return; } else { + int store_reply_hdr = 0; if (httpState->reply_hdr_state < 2) { httpProcessReplyHeader(httpState, buf, len); ...... + if (store_reply_hdr == 1) + storeAppend(entry, httpState->reply_hdr_buf.buf, httpState->reply_hdr_buf.size); + else if (httpState->reply_hdr_state == 2) + storeAppend(entry, buf, len); if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { /* * the above storeAppend() call could ABORT this entry, * in that case, the server FD should already be closed. * there's nothing for us to do. */ return; } + if (httpState->reply_hdr_state < 2) { + commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0); + return; + } switch (httpPconnTransferDone(httpState)) { ...... } 3.3) in httpStateFree() static void httpStateFree(int fd, void *data) { ...... if (!memBufIsNull(&httpState->reply_hdr)) { memBufClean(&httpState->reply_hdr); } + if (!memBufIsNull(&httpState->reply_hdr_buf)) { + memBufClean(&httpState->reply_hdr_buf); + } ...... } ___________________________________________________________ Mp3疯狂搜-新歌热歌高速下 http://music.yahoo.com.cn/?source=mail_mailbox_footer
Received on Wed Oct 25 2006 - 04:00:00 MDT

This archive was generated by hypermail pre-2.1.9 : Wed Nov 01 2006 - 12:00:06 MST