MEDIUM: logs: Add HTTP request-line log format directives
This commit adds 4 new log format variables that parse the HTTP Request-Line for more specific logging than "%r" provides. For example, we can parse the following HTTP Request-Line with these new variables: "GET /foo?bar=baz HTTP/1.1" - %HM: HTTP Method ("GET") - %HV: HTTP Version ("HTTP/1.1") - %HU: HTTP Request-URI ("/foo?bar=baz") - %HP: HTTP Request-URI without query string ("/foo")
This commit is contained in:
parent
e5843b383d
commit
0ebc55f6b4
|
@ -13159,6 +13159,10 @@ Please refer to the table below for currently defined variables :
|
|||
| H | %CC | captured_request_cookie | string |
|
||||
| H | %CS | captured_response_cookie | string |
|
||||
| | %H | hostname | string |
|
||||
| H | %HM | HTTP method (ex: POST) | string |
|
||||
| H | %HP | HTTP request URI without query string (path) | string |
|
||||
| H | %HU | HTTP request URI (ex: /foo?bar=baz) | string |
|
||||
| H | %HV | HTTP version (ex: HTTP/1.0) | string |
|
||||
| | %ID | unique-id | string |
|
||||
| | %ST | status_code | numeric |
|
||||
| | %T | gmt_date_time | date |
|
||||
|
|
|
@ -93,6 +93,10 @@ enum {
|
|||
LOG_FMT_HDRREQUESTLIST,
|
||||
LOG_FMT_HDRRESPONSLIST,
|
||||
LOG_FMT_REQ,
|
||||
LOG_FMT_HTTP_METHOD,
|
||||
LOG_FMT_HTTP_URI,
|
||||
LOG_FMT_HTTP_PATH,
|
||||
LOG_FMT_HTTP_VERSION,
|
||||
LOG_FMT_HOSTNAME,
|
||||
LOG_FMT_UNIQUEID,
|
||||
LOG_FMT_SSL_CIPHER,
|
||||
|
|
164
src/log.c
164
src/log.c
|
@ -32,6 +32,7 @@
|
|||
#include <types/log.h>
|
||||
|
||||
#include <proto/frontend.h>
|
||||
#include <proto/proto_http.h>
|
||||
#include <proto/log.h>
|
||||
#include <proto/sample.h>
|
||||
#include <proto/stream.h>
|
||||
|
@ -108,6 +109,10 @@ static const struct logformat_type logformat_keywords[] = {
|
|||
{ "hrl", LOG_FMT_HDRREQUESTLIST, PR_MODE_TCP, LW_REQHDR, NULL }, /* header request list */
|
||||
{ "hs", LOG_FMT_HDRRESPONS, PR_MODE_TCP, LW_RSPHDR, NULL }, /* header response */
|
||||
{ "hsl", LOG_FMT_HDRRESPONSLIST, PR_MODE_TCP, LW_RSPHDR, NULL }, /* header response list */
|
||||
{ "HM", LOG_FMT_HTTP_METHOD, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP method */
|
||||
{ "HP", LOG_FMT_HTTP_PATH, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP path */
|
||||
{ "HU", LOG_FMT_HTTP_URI, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP full URI */
|
||||
{ "HV", LOG_FMT_HTTP_VERSION, PR_MODE_HTTP, LW_REQ, NULL }, /* HTTP version */
|
||||
{ "lc", LOG_FMT_LOGCNT, PR_MODE_TCP, LW_INIT, NULL }, /* log counter */
|
||||
{ "ms", LOG_FMT_MS, PR_MODE_TCP, LW_INIT, NULL }, /* accept date millisecond */
|
||||
{ "pid", LOG_FMT_PID, PR_MODE_TCP, LW_INIT, NULL }, /* log pid */
|
||||
|
@ -923,11 +928,15 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list
|
|||
struct proxy *fe = sess->fe;
|
||||
struct proxy *be = s->be;
|
||||
struct http_txn *txn = s->txn;
|
||||
struct chunk chunk;
|
||||
char *uri;
|
||||
char *spc;
|
||||
char *end;
|
||||
struct tm tm;
|
||||
int t_request;
|
||||
int hdr;
|
||||
int last_isspace = 1;
|
||||
int nspaces = 0;
|
||||
char *tmplog;
|
||||
char *ret;
|
||||
int iret;
|
||||
|
@ -1523,6 +1532,161 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list
|
|||
last_isspace = 0;
|
||||
break;
|
||||
|
||||
case LOG_FMT_HTTP_PATH: // %HP
|
||||
uri = txn->uri ? txn->uri : "<BADREQ>";
|
||||
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
end = uri + strlen(uri);
|
||||
// look for the first whitespace character
|
||||
while (uri < end && !HTTP_IS_SPHT(*uri))
|
||||
uri++;
|
||||
|
||||
// keep advancing past multiple spaces
|
||||
while (uri < end && HTTP_IS_SPHT(*uri)) {
|
||||
uri++; nspaces++;
|
||||
}
|
||||
|
||||
// look for first space or question mark after url
|
||||
spc = uri;
|
||||
while (spc < end && *spc != '?' && !HTTP_IS_SPHT(*spc))
|
||||
spc++;
|
||||
|
||||
if (!txn->uri || nspaces == 0) {
|
||||
chunk.str = "<BADREQ>";
|
||||
chunk.len = strlen("<BADREQ>");
|
||||
} else {
|
||||
chunk.str = uri;
|
||||
chunk.len = spc - uri;
|
||||
}
|
||||
|
||||
ret = encode_chunk(tmplog, dst + maxsize, '#', url_encode_map, &chunk);
|
||||
if (ret == NULL || *ret != '\0')
|
||||
goto out;
|
||||
|
||||
tmplog = ret;
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
last_isspace = 0;
|
||||
break;
|
||||
|
||||
case LOG_FMT_HTTP_URI: // %HU
|
||||
uri = txn->uri ? txn->uri : "<BADREQ>";
|
||||
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
end = uri + strlen(uri);
|
||||
// look for the first whitespace character
|
||||
while (uri < end && !HTTP_IS_SPHT(*uri))
|
||||
uri++;
|
||||
|
||||
// keep advancing past multiple spaces
|
||||
while (uri < end && HTTP_IS_SPHT(*uri)) {
|
||||
uri++; nspaces++;
|
||||
}
|
||||
|
||||
// look for first space after url
|
||||
spc = uri;
|
||||
while (spc < end && !HTTP_IS_SPHT(*spc))
|
||||
spc++;
|
||||
|
||||
if (!txn->uri || nspaces == 0) {
|
||||
chunk.str = "<BADREQ>";
|
||||
chunk.len = strlen("<BADREQ>");
|
||||
} else {
|
||||
chunk.str = uri;
|
||||
chunk.len = spc - uri;
|
||||
}
|
||||
|
||||
ret = encode_chunk(tmplog, dst + maxsize, '#', url_encode_map, &chunk);
|
||||
if (ret == NULL || *ret != '\0')
|
||||
goto out;
|
||||
|
||||
tmplog = ret;
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
last_isspace = 0;
|
||||
break;
|
||||
|
||||
case LOG_FMT_HTTP_METHOD: // %HM
|
||||
uri = txn->uri ? txn->uri : "<BADREQ>";
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
end = uri + strlen(uri);
|
||||
// look for the first whitespace character
|
||||
spc = uri;
|
||||
while (spc < end && !HTTP_IS_SPHT(*spc))
|
||||
spc++;
|
||||
|
||||
if (spc == end) { // odd case, we have txn->uri, but we only got a verb
|
||||
chunk.str = "<BADREQ>";
|
||||
chunk.len = strlen("<BADREQ>");
|
||||
} else {
|
||||
chunk.str = uri;
|
||||
chunk.len = spc - uri;
|
||||
}
|
||||
|
||||
ret = encode_chunk(tmplog, dst + maxsize, '#', url_encode_map, &chunk);
|
||||
if (ret == NULL || *ret != '\0')
|
||||
goto out;
|
||||
|
||||
tmplog = ret;
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
last_isspace = 0;
|
||||
break;
|
||||
|
||||
case LOG_FMT_HTTP_VERSION: // %HV
|
||||
uri = txn->uri ? txn->uri : "<BADREQ>";
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
end = uri + strlen(uri);
|
||||
// look for the first whitespace character
|
||||
while (uri < end && !HTTP_IS_SPHT(*uri))
|
||||
uri++;
|
||||
|
||||
// keep advancing past multiple spaces
|
||||
while (uri < end && HTTP_IS_SPHT(*uri)) {
|
||||
uri++; nspaces++;
|
||||
}
|
||||
|
||||
// look for the next whitespace character
|
||||
while (uri < end && !HTTP_IS_SPHT(*uri))
|
||||
uri++;
|
||||
|
||||
// keep advancing past multiple spaces
|
||||
while (uri < end && HTTP_IS_SPHT(*uri))
|
||||
uri++;
|
||||
|
||||
if (!txn->uri || nspaces == 0) {
|
||||
chunk.str = "<BADREQ>";
|
||||
chunk.len = strlen("<BADREQ>");
|
||||
} else if (uri == end) {
|
||||
chunk.str = "HTTP/0.9";
|
||||
chunk.len = strlen("HTTP/0.9");
|
||||
} else {
|
||||
chunk.str = uri;
|
||||
chunk.len = end - uri;
|
||||
}
|
||||
|
||||
ret = encode_chunk(tmplog, dst + maxsize, '#', url_encode_map, &chunk);
|
||||
if (ret == NULL || *ret != '\0')
|
||||
goto out;
|
||||
|
||||
tmplog = ret;
|
||||
if (tmp->options && LOG_OPT_QUOTE)
|
||||
LOGCHAR('"');
|
||||
|
||||
last_isspace = 0;
|
||||
break;
|
||||
|
||||
case LOG_FMT_COUNTER: // %rt
|
||||
if (tmp->options & LOG_OPT_HEXA) {
|
||||
iret = snprintf(tmplog, dst + maxsize - tmplog, "%04X", s->uniq_id);
|
||||
|
|
Loading…
Reference in New Issue