/* allocates and initializes an error response */ HttpReply * errorBuildReply(ErrorState * err) { HttpReply *rep = httpReplyCreate(); const char *name = errorPageName(err->page_id); /* no LMT for error pages; error pages expire immediately */ if (strchr(name, ':')) { /* Redirection */ httpReplySetHeaders(rep, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, -1, -1); if (err->request) { char *quoted_url = rfc1738_escape_part(urlCanonical(err->request)); httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url); } httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s", err->http_status, "Access Denied"); } else { MemBuf content = errorBuildContent(err); httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, -1); /* * include some information for downstream caches. Implicit * replaceable content. This isn't quite sufficient. xerrno is not * necessarily meaningful to another system, so we really should * expand it. Additionally, we should identify ourselves. Someone * might want to know. Someone _will_ want to know OTOH, the first * X-CACHE-MISS entry should tell us who. */ httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d", name, err->xerrno); httpBodySet(&rep->body, &content); /* do not memBufClean() the content, it was absorbed by httpBody */ } return rep; }
MemBuf httpPackedReply(http_version_t ver, http_status status, const char *ctype, squid_off_t clen, time_t lmt, time_t expires) { HttpReply *rep = httpReplyCreate(); MemBuf mb; httpReplySetHeaders(rep, ver, status, ctype, NULL, clen, lmt, expires); mb = httpReplyPack(rep); httpReplyDestroy(rep); return mb; }
/* * The helper program receives queries on stdin, one * per line, and must return the result on on stdout */ static void refreshCheckHandleReply(void *data, char *reply) { refreshCheckState *state = data; refreshCheckState *next; int freshness = -1; char *log = NULL; MemBuf hdrs = MemBufNULL; debug(84, 2) ("refreshCheckHandleReply: reply=\"%s\"\n", reply); if (reply) { char *t = NULL; char *token = strwordtok(reply, &t); if (token && strcmp(token, "FRESH") == 0) freshness = 0; else if (token && strcmp(token, "OK") == 0) freshness = 0; while ((token = strwordtok(NULL, &t))) { char *value = strchr(token, '='); if (value) { *value++ = '\0'; /* terminate the token, and move up to the value */ rfc1738_unescape(value); if (strcmp(token, "freshness") == 0) freshness = atoi(value); else if (strcmp(token, "log") == 0) log = value; else if (strncmp(token, "res{", 4) == 0) { char *header, *t; header = token + 4; t = strrchr(header, '}'); if (!t) continue; *t = '\0'; if (!hdrs.buf) memBufDefInit(&hdrs); memBufPrintf(&hdrs, "%s: %s\r\n", header, value); } } } } if (freshness >= 0) { if (hdrs.size) { HttpReply *rep = httpReplyCreate(); httpHeaderParse(&rep->header, hdrs.buf, hdrs.buf + hdrs.size); httpReplyUpdateOnNotModified(state->entry->mem_obj->reply, rep); storeTimestampsSet(state->entry); if (!httpHeaderHas(&rep->header, HDR_DATE)) { state->entry->timestamp = squid_curtime; state->entry->expires = squid_curtime + freshness; } else if (freshness) { state->entry->expires = squid_curtime + freshness; } httpReplyDestroy(rep); storeUpdate(state->entry, NULL); } else { state->entry->timestamp = squid_curtime; state->entry->expires = squid_curtime + freshness; } } if (hdrs.buf) memBufClean(&hdrs); dlinkDelete(&state->list, &state->def->queue); do { cbdataUnlock(state->def); state->def = NULL; if (state->callback && cbdataValid(state->callback_data)) state->callback(state->callback_data, freshness >= 0, log); cbdataUnlock(state->callback_data); state->callback_data = NULL; next = state->queue; cbdataFree(state); state = next; } while (state); }
static int buildRespModHeader(MemBuf * mb, IcapStateData * icap, char *buf, ssize_t len, int theEnd) { MemBuf mb_hdr; char *client_addr; int o2=0; int o3=0; int hlen; int consumed; icap_service *service; HttpReply *r; if (memBufIsNull(&icap->respmod.req_hdr_copy)) memBufDefInit(&icap->respmod.req_hdr_copy); memBufAppend(&icap->respmod.req_hdr_copy, buf, len); if (icap->respmod.req_hdr_copy.size > 4 && strncmp(icap->respmod.req_hdr_copy.buf, "HTTP/", 5)) { debug(81, 3) ("buildRespModHeader: Non-HTTP-compliant header: '%s'\n", buf); /* *Possible we can consider that we did not have http responce headers *(maybe HTTP 0.9 protocol), lets returning -1... */ consumed=-1; o2=-1; memBufDefInit(&mb_hdr); } else{ hlen = headersEnd(icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size); debug(81, 3) ("buildRespModHeader: headersEnd = %d(%s)\n", hlen,buf); if (0 == hlen) return 0; /* * calc how many bytes from this 'buf' went towards the * reply header. */ consumed = hlen - (icap->respmod.req_hdr_copy.size - len); debug(81, 3) ("buildRespModHeader: consumed = %d\n", consumed); /* * now, truncate our req_hdr_copy at the header end. * this 'if' statement might be unncessary? */ if (hlen < icap->respmod.req_hdr_copy.size) icap->respmod.req_hdr_copy.size = hlen; /* Copy request header */ memBufDefInit(&mb_hdr); httpBuildRequestPrefix(icap->request, icap->request, icap->respmod.entry, &mb_hdr, icap->http_flags); o2 = mb_hdr.size; } /* Copy response header - Append to request header mbuffer */ memBufAppend(&mb_hdr, icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size); o3 = mb_hdr.size; service = icap->current_service; assert(service); client_addr = inet_ntoa(icap->request->client_addr); r = httpReplyCreate(); httpReplyParse(r, icap->respmod.req_hdr_copy.buf, icap->respmod.req_hdr_copy.size); icap->respmod.res_body_sz = httpReplyBodySize(icap->request->method, r); httpReplyDestroy(r); if (icap->respmod.res_body_sz) getICAPRespModString(mb, 0, o2, o3, client_addr, icap, service); else getICAPRespModString(mb, 0, o2, -o3, client_addr, icap, service); if (Config.icapcfg.preview_enable) if (icap->preview_size >= 0) { memBufPrintf(mb, "Preview: %d\r\n", icap->preview_size); icap->flags.preview_done = 0; } if(service->keep_alive){ icap->flags.keep_alive = 1; memBufAppend(mb, "Connection: keep-alive\r\n", 24); } else{ icap->flags.keep_alive = 0; memBufAppend(mb, "Connection: close\r\n", 19); } memBufAppend(mb, crlf, 2); memBufAppend(mb, mb_hdr.buf, mb_hdr.size); memBufClean(&mb_hdr); return consumed; }
static int process_miss_in_error_page(clientHttpRequest* http ,int *ret) { debug(115, 4)("mod_customized_server_side_error_page process_miss_in_error_page\n"); int fd = http->conn->fd; if(fd_table[fd].cc_run_state[mod->slot]>0) { mod_config* cfg = cc_get_mod_param(fd,mod); if(squid_curtime < cfg->error_page_expires ) { ErrorState* err = NULL; /**********************************/ err_type page_id; int status = cfg->ResponseStatus; // add by xueye.zhao // 2013-4-18 if (is_http_move_status(status)) { HttpReply *rep = httpReplyCreate(); http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags); http->log_type = LOG_TCP_HIT; storeReleaseRequest(http->entry); httpRedirectReply(rep, cfg->ResponseStatus, cfg->location); httpReplySwapOut(rep, http->entry); storeComplete(http->entry); *ret = 1; return *ret; } //end add switch(status) { case HTTP_BAD_REQUEST: case HTTP_LENGTH_REQUIRED: case HTTP_EXPECTATION_FAILED: page_id = ERR_INVALID_REQ; break; case HTTP_UNAUTHORIZED: case HTTP_FORBIDDEN: case HTTP_METHOD_NOT_ALLOWED: case HTTP_NOT_ACCEPTABLE: case HTTP_PROXY_AUTHENTICATION_REQUIRED: case HTTP_REQUEST_TIMEOUT: case HTTP_CONFLICT: case HTTP_GONE: case HTTP_PRECONDITION_FAILED: case HTTP_UNSUPPORTED_MEDIA_TYPE: case HTTP_UNPROCESSABLE_ENTITY: case HTTP_LOCKED: case HTTP_FAILED_DEPENDENCY: page_id = ERR_ACCESS_DENIED; break; case HTTP_NOT_FOUND : page_id = ERR_FTP_NOT_FOUND; break; case HTTP_REQUEST_ENTITY_TOO_LARGE: case HTTP_REQUEST_URI_TOO_LONG: page_id = ERR_TOO_BIG; break; case HTTP_INTERNAL_SERVER_ERROR: page_id= ERR_SOCKET_FAILURE; break; case HTTP_NOT_IMPLEMENTED: page_id = ERR_UNSUP_REQ; break; case HTTP_BAD_GATEWAY: case HTTP_GATEWAY_TIMEOUT: page_id = ERR_CONNECT_FAIL; break; case HTTP_SERVICE_UNAVAILABLE: page_id = ERR_FTP_UNAVAILABLE; break; default: page_id = ERR_HTTP_SPECIAL; } /**********************************/ debug(115, 5)("mod_customized_server_side_error_page: cc_error_page running, don't back source server\n"); http->al.http.code = HTTP_FORBIDDEN; err = errorCon(page_id, cfg->ResponseStatus,http->request); // err->request = requestLink(http->request); err->src_addr = http->conn->peer.sin_addr; http->log_type = LOG_TCP_DENIED; http->entry = clientCreateStoreEntry(http, http->request->method, null_request_flags); errorAppendEntry(http->entry, err); *ret =1; } } return *ret; }
/*handle errorEntry here*/ static int repl_send_start(clientHttpRequest *http, int *ret) { debug(115, 4)("mod_customized_server_side_error_page repl_send_start\n"); int fd= http->conn->fd; mod_config* cfg = cc_get_mod_param(fd,mod); //mod_config *cfg = ((mod_config*)(param->param)); if(fd_table[fd].cc_run_state[mod->slot]>0) { error_page_private_data* pd = (error_page_private_data*) cc_get_mod_private_data(REQUEST_PRIVATE_DATA,http,mod); if(pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0 && cfg->customized_error_text.buf != NULL/* && pd->ResponseStatus <400 */) { debug(115,4)("customized_server_side_error_page: repl_send_start the recusive_time is: %d\n",pd->recusive_time); ErrorState *err; err_type page_id; int status = pd->ResponseStatus; switch(status) { case HTTP_BAD_REQUEST: case HTTP_LENGTH_REQUIRED: case HTTP_EXPECTATION_FAILED: page_id = ERR_INVALID_REQ; break; case HTTP_UNAUTHORIZED: case HTTP_FORBIDDEN: case HTTP_METHOD_NOT_ALLOWED: case HTTP_NOT_ACCEPTABLE: case HTTP_PROXY_AUTHENTICATION_REQUIRED: case HTTP_REQUEST_TIMEOUT: case HTTP_CONFLICT: case HTTP_GONE: case HTTP_PRECONDITION_FAILED: case HTTP_UNSUPPORTED_MEDIA_TYPE: case HTTP_UNPROCESSABLE_ENTITY: case HTTP_LOCKED: case HTTP_FAILED_DEPENDENCY: page_id = ERR_ACCESS_DENIED; break; case HTTP_NOT_FOUND : page_id = ERR_FTP_NOT_FOUND; break; case HTTP_REQUEST_ENTITY_TOO_LARGE: case HTTP_REQUEST_URI_TOO_LONG: page_id = ERR_TOO_BIG; break; case HTTP_INTERNAL_SERVER_ERROR: page_id= ERR_SOCKET_FAILURE; break; case HTTP_NOT_IMPLEMENTED: page_id = ERR_UNSUP_REQ; break; case HTTP_BAD_GATEWAY: case HTTP_GATEWAY_TIMEOUT: page_id = ERR_CONNECT_FAIL; break; case HTTP_SERVICE_UNAVAILABLE: page_id = ERR_FTP_UNAVAILABLE; break; default: page_id = ERR_HTTP_SPECIAL; } // err = errorCon(page_id, err = errorCon(page_id,pd->ResponseStatus,http->request); /********************may be leak here**********************************/ assert(err!=NULL); if(squid_curtime > cfg->error_page_expires) cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive; //err->request = requestLink(http->request); storeClientUnregister(http->sc,http->entry,http); http->sc = NULL; storeUnlockObject(http->entry); http->log_type = LOG_TCP_HIT; http->entry = clientCreateStoreEntry(http,http->request->method,null_request_flags); debug(115,4)("mod_customized_server_side_error_page repl_send_start: before errorAppendEntry, the err->page_id is: %d, the err->http_status is: %d , the err->type is: %d \n",err->page_id, err->http_status,err->type); errorAppendEntry(http->entry,err); /********************may be leak here**********************************/ *ret = 1; } // add by xueye.zhao // 2013-4-18 else if (pd->OfflineTimeToLive > 0&& pd->recusive_time<2 && pd->recusive_time > 0) { if(squid_curtime > cfg->error_page_expires) cfg->error_page_expires = squid_curtime + pd->OfflineTimeToLive; HttpReply *rep = httpReplyCreate(); http->entry = clientCreateStoreEntry(http, http->request->method, http->request->flags); http->log_type = LOG_TCP_MISS; storeReleaseRequest(http->entry); httpRedirectReply(rep, cfg->ResponseStatus, cfg->location); httpReplySwapOut(rep, http->entry); storeComplete(http->entry); *ret = 1; return *ret; } // end add } return *ret; }