Beispiel #1
0
/* 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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
/*
 * 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);
}
Beispiel #4
0
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;	
}