📄 errorpage.c
字号:
storeNegativeCache(entry); storeReleaseRequest(entry); storeUnlockObject(entry); errorStateFree(err);}/* * Function: errorSend * * Arguments: err - This object is destroyed after use in this function. * * Abstract: This function generates a error page from the info contained * by 'err' and then sends it to the client. * The callback function errorSendComplete() is called after * the page has been written to the client socket (fd). * errorSendComplete() deallocates 'err'. We need to add * 'err' to the cbdata because comm_write() requires it * for all callback data pointers. * * Note, normally errorSend() should only be called from * routines in ssl.c and pass.c, where we don't have any * StoreEntry's. In client_side.c we must allocate a StoreEntry * for errors and use errorAppendEntry() to account for * persistent/pipeline connections. */voiderrorSend(int fd, ErrorState * err){ HttpReply *rep; debug(4, 3) ("errorSend: FD %d, err=%p\n", fd, err); assert(fd >= 0); /* * ugh, this is how we make sure error codes get back to * the client side for logging and error tracking. */ if (err->request) err->request->err_type = err->type; /* moved in front of errorBuildBuf @?@ */ err->flags.flag_cbdata = 1; cbdataAdd(err, memFree, MEM_ERRORSTATE); rep = errorBuildReply(err); comm_write_mbuf(fd, httpReplyPack(rep), errorSendComplete, err); httpReplyDestroy(rep);}/* * Function: errorSendComplete * * Abstract: Called by commHandleWrite() after data has been written * to the client socket. * * Note: If there is a callback, the callback is responsible for * closeing the FD, otherwise we do it ourseves. */static voiderrorSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data){ ErrorState *err = data; debug(4, 3) ("errorSendComplete: FD %d, size=%d\n", fd, size); if (errflag != COMM_ERR_CLOSING) { if (err->callback) err->callback(fd, err->callback_data, size); else comm_close(fd); } errorStateFree(err);}voiderrorStateFree(ErrorState * err){ requestUnlink(err->request); safe_free(err->redirect_url); safe_free(err->url); safe_free(err->host); safe_free(err->dnsserver_msg); safe_free(err->request_hdrs); if (err->flags.flag_cbdata) cbdataFree(err); else memFree(err, MEM_ERRORSTATE);}#define CVT_BUF_SZ 512/* * B - URL with FTP %2f hack x * c - Squid error code x * d - seconds elapsed since request received x * e - errno x * E - strerror() x * f - FTP request line x * F - FTP reply line x * g - FTP server message x * h - cache hostname x * H - server host name x * i - client IP address x * I - server IP address x * L - HREF link for more info/contact x * M - Request Method x * p - URL port # x * P - Protocol x * R - Full HTTP Request x * S - squid signature from ERR_SIGNATURE x * s - caching proxy software with version x * t - local time x * T - UTC x * U - URL without password x * u - URL without password, %2f added to path x * w - cachemgr email address x * z - dns server error message x */static const char *errorConvert(char token, ErrorState * err){ request_t *r = err->request; static MemBuf mb = MemBufNULL; const char *p = NULL; /* takes priority over mb if set */ memBufReset(&mb); switch (token) { case 'B': p = r ? ftpUrlWith2f(r) : "[no URL]"; break; case 'e': memBufPrintf(&mb, "%d", err->xerrno); break; case 'E': if (err->xerrno) memBufPrintf(&mb, "(%d) %s", err->xerrno, strerror(err->xerrno)); else memBufPrintf(&mb, "[No Error]"); break; case 'f': /* FTP REQUEST LINE */ if (err->ftp.request) p = err->ftp.request; else p = "nothing"; break; case 'F': /* FTP REPLY LINE */ if (err->ftp.request) p = err->ftp.reply; else p = "nothing"; break; case 'g': /* FTP SERVER MESSAGE */ wordlistCat(err->ftp_server_msg, &mb); break; case 'h': memBufPrintf(&mb, "%s", getMyHostname()); break; case 'H': p = r ? r->host : "[unknown host]"; break; case 'i': memBufPrintf(&mb, "%s", inet_ntoa(err->src_addr)); break; case 'I': if (err->host) { memBufPrintf(&mb, "%s", err->host); } else p = "[unknown]"; break; case 'L': if (Config.errHtmlText) { memBufPrintf(&mb, "%s", Config.errHtmlText); } else p = "[not available]"; break; case 'M': p = r ? RequestMethodStr[r->method] : "[unkown method]"; break; case 'p': if (r) { memBufPrintf(&mb, "%d", (int) r->port); } else { p = "[unknown port]"; } break; case 'P': p = r ? ProtocolStr[r->protocol] : "[unkown protocol]"; break; case 'R': if (NULL != r) { Packer p; memBufPrintf(&mb, "%s %s HTTP/%3.1f\n", RequestMethodStr[r->method], strLen(r->urlpath) ? strBuf(r->urlpath) : "/", (double) r->http_ver); packerToMemInit(&p, &mb); httpHeaderPackInto(&r->header, &p); packerClean(&p); } else if (err->request_hdrs) { p = err->request_hdrs; } else { p = "[no request]"; } break; case 's': p = full_appname_string; break; case 'S': /* signature may contain %-escapes, recursion */ if (err->page_id != ERR_SQUID_SIGNATURE) { const int saved_id = err->page_id; MemBuf sign_mb; err->page_id = ERR_SQUID_SIGNATURE; sign_mb = errorBuildContent(err); memBufPrintf(&mb, "%s", sign_mb.buf); memBufClean(&sign_mb); err->page_id = saved_id; } else { /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */ p = "[%S]"; } break; case 't': memBufPrintf(&mb, "%s", mkhttpdlogtime(&squid_curtime)); break; case 'T': memBufPrintf(&mb, "%s", mkrfc1123(squid_curtime)); break; case 'U': p = r ? urlCanonicalClean(r) : err->url ? err->url : "[no URL]"; break; case 'w': if (Config.adminEmail) memBufPrintf(&mb, "%s", Config.adminEmail); else p = "[unknown]"; break; case 'z': if (err->dnsserver_msg) p = err->dnsserver_msg; else p = "[unknown]"; break; case '%': p = "%"; break; default: memBufPrintf(&mb, "%%%c", token); break; } if (!p) p = mb.buf; /* do not use mb after this assignment! */ assert(p); debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p); return p;}/* allocates and initializes an error response */HttpReply *errorBuildReply(ErrorState * err){ HttpReply *rep = httpReplyCreate(); MemBuf content = errorBuildContent(err); /* no LMT for error pages; error pages expire immediately */ httpReplySetHeaders(rep, 1.0, err->http_status, NULL, "text/html", content.size, 0, squid_curtime); /* * 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", errorPageName(err->page_id), err->xerrno); httpBodySet(&rep->body, &content); /* do not memBufClean() the content, it was absorbed by httpBody */ return rep;}static MemBuferrorBuildContent(ErrorState * err){ MemBuf content; const char *m; const char *p; const char *t; assert(err != NULL); assert(err->page_id > ERR_NONE && err->page_id < error_page_count); memBufDefInit(&content); m = error_text[err->page_id]; assert(m); while ((p = strchr(m, '%'))) { memBufAppend(&content, m, p - m); /* copy */ t = errorConvert(*++p, err); /* convert */ memBufPrintf(&content, "%s", t); /* copy */ m = p + 1; /* advance */ } if (*m) memBufPrintf(&content, "%s", m); /* copy tail */ assert(content.size == strlen(content.buf)); return content;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -