nghttpx: Log :authority as $http_host if available

This commit is contained in:
Tatsuhiro Tsujikawa 2015-10-28 23:12:16 +09:00
parent b915c24704
commit d9f73c36c3
4 changed files with 83 additions and 33 deletions

View File

@ -515,8 +515,16 @@ std::vector<LogFragment> parse_log_format(const char *optarg) {
if (type == SHRPX_LOGF_NONE) { if (type == SHRPX_LOGF_NONE) {
if (util::istartsWith(var_name, var_namelen, "http_")) { if (util::istartsWith(var_name, var_namelen, "http_")) {
if (util::streq("host", var_name + str_size("http_"),
var_namelen - str_size("http_"))) {
// Special handling of host header field. We will use
// :authority header field if host header is missing. This
// is a typical case in HTTP/2.
type = SHRPX_LOGF_AUTHORITY;
} else {
type = SHRPX_LOGF_HTTP; type = SHRPX_LOGF_HTTP;
value = var_name + str_size("http_"); value = var_name + str_size("http_");
}
} else { } else {
LOG(WARN) << "Unrecognized log format variable: " LOG(WARN) << "Unrecognized log format variable: "
<< std::string(var_name, var_namelen); << std::string(var_name, var_namelen);

View File

@ -62,10 +62,11 @@ void test_shrpx_config_parse_header(void) {
} }
void test_shrpx_config_parse_log_format(void) { void test_shrpx_config_parse_log_format(void) {
auto res = parse_log_format(R"($remote_addr - $remote_user [$time_local] )" auto res =
parse_log_format(R"($remote_addr - $remote_user [$time_local] )"
R"("$request" $status $body_bytes_sent )" R"("$request" $status $body_bytes_sent )"
R"("${http_referer}" "$http_user_agent")"); R"("${http_referer}" $http_host "$http_user_agent")");
CU_ASSERT(14 == res.size()); CU_ASSERT(16 == res.size());
CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[0].type); CU_ASSERT(SHRPX_LOGF_REMOTE_ADDR == res[0].type);
@ -96,14 +97,19 @@ void test_shrpx_config_parse_log_format(void) {
CU_ASSERT(0 == strcmp("referer", res[10].value.get())); CU_ASSERT(0 == strcmp("referer", res[10].value.get()));
CU_ASSERT(SHRPX_LOGF_LITERAL == res[11].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[11].type);
CU_ASSERT(0 == strcmp("\" \"", res[11].value.get())); CU_ASSERT(0 == strcmp("\" ", res[11].value.get()));
CU_ASSERT(SHRPX_LOGF_HTTP == res[12].type); CU_ASSERT(SHRPX_LOGF_AUTHORITY == res[12].type);
CU_ASSERT(0 == strcmp("user-agent", res[12].value.get()));
CU_ASSERT(SHRPX_LOGF_LITERAL == res[13].type); CU_ASSERT(SHRPX_LOGF_LITERAL == res[13].type);
CU_ASSERT(0 == strcmp(" \"", res[13].value.get())); CU_ASSERT(0 == strcmp(" \"", res[13].value.get()));
CU_ASSERT(SHRPX_LOGF_HTTP == res[14].type);
CU_ASSERT(0 == strcmp("user-agent", res[14].value.get()));
CU_ASSERT(SHRPX_LOGF_LITERAL == res[15].type);
CU_ASSERT(0 == strcmp("\"", res[15].value.get()));
res = parse_log_format("$"); res = parse_log_format("$");
CU_ASSERT(1 == res.size()); CU_ASSERT(1 == res.size());

View File

@ -158,14 +158,38 @@ Log::~Log() {
namespace { namespace {
template <typename OutputIterator> template <typename OutputIterator>
std::pair<OutputIterator, size_t> copy(const char *src, size_t avail, std::pair<OutputIterator, size_t> copy(const char *src, size_t srclen,
OutputIterator oitr) { size_t avail, OutputIterator oitr) {
auto nwrite = std::min(strlen(src), avail); auto nwrite = std::min(srclen, avail);
auto noitr = std::copy_n(src, nwrite, oitr); auto noitr = std::copy_n(src, nwrite, oitr);
return std::make_pair(noitr, avail - nwrite); return std::make_pair(noitr, avail - nwrite);
} }
} // namespace } // namespace
namespace {
template <typename OutputIterator>
std::pair<OutputIterator, size_t> copy(const char *src, size_t avail,
OutputIterator oitr) {
return copy(src, strlen(src), avail, oitr);
}
} // namespace
namespace {
template <typename OutputIterator>
std::pair<OutputIterator, size_t> copy(const std::string &src, size_t avail,
OutputIterator oitr) {
return copy(src.c_str(), src.size(), avail, oitr);
}
} // namespace
namespace {
template <size_t N, typename OutputIterator>
std::pair<OutputIterator, size_t> copy_l(const char (&src)[N], size_t avail,
OutputIterator oitr) {
return copy(src, N - 1, avail, oitr);
}
} // namespace
namespace { namespace {
const char LOWER_XDIGITS[] = "0123456789abcdef"; const char LOWER_XDIGITS[] = "0123456789abcdef";
} // namespace } // namespace
@ -212,46 +236,57 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
std::tie(p, avail) = copy(lgsp.remote_addr, avail, p); std::tie(p, avail) = copy(lgsp.remote_addr, avail, p);
break; break;
case SHRPX_LOGF_TIME_LOCAL: case SHRPX_LOGF_TIME_LOCAL:
std::tie(p, avail) = copy(time_local.c_str(), avail, p); std::tie(p, avail) = copy(time_local, avail, p);
break; break;
case SHRPX_LOGF_TIME_ISO8601: case SHRPX_LOGF_TIME_ISO8601:
std::tie(p, avail) = copy(time_iso8601.c_str(), avail, p); std::tie(p, avail) = copy(time_iso8601, avail, p);
break; break;
case SHRPX_LOGF_REQUEST: case SHRPX_LOGF_REQUEST:
std::tie(p, avail) = copy(lgsp.method, avail, p); std::tie(p, avail) = copy(lgsp.method, avail, p);
std::tie(p, avail) = copy(" ", avail, p); std::tie(p, avail) = copy_l(" ", avail, p);
std::tie(p, avail) = copy(lgsp.path, avail, p); std::tie(p, avail) = copy(lgsp.path, avail, p);
std::tie(p, avail) = copy(" HTTP/", avail, p); std::tie(p, avail) = copy_l(" HTTP/", avail, p);
std::tie(p, avail) = copy(util::utos(lgsp.major).c_str(), avail, p); std::tie(p, avail) = copy(util::utos(lgsp.major), avail, p);
if (lgsp.major < 2) { if (lgsp.major < 2) {
std::tie(p, avail) = copy(".", avail, p); std::tie(p, avail) = copy_l(".", avail, p);
std::tie(p, avail) = copy(util::utos(lgsp.minor).c_str(), avail, p); std::tie(p, avail) = copy(util::utos(lgsp.minor), avail, p);
} }
break; break;
case SHRPX_LOGF_STATUS: case SHRPX_LOGF_STATUS:
std::tie(p, avail) = copy(util::utos(lgsp.status).c_str(), avail, p); std::tie(p, avail) = copy(util::utos(lgsp.status), avail, p);
break; break;
case SHRPX_LOGF_BODY_BYTES_SENT: case SHRPX_LOGF_BODY_BYTES_SENT:
std::tie(p, avail) = std::tie(p, avail) = copy(util::utos(lgsp.body_bytes_sent), avail, p);
copy(util::utos(lgsp.body_bytes_sent).c_str(), avail, p);
break; break;
case SHRPX_LOGF_HTTP: case SHRPX_LOGF_HTTP:
if (downstream) { if (downstream) {
auto hd = downstream->get_request_header(lf.value.get()); auto hd = downstream->get_request_header(lf.value.get());
if (hd) { if (hd) {
std::tie(p, avail) = copy((*hd).value.c_str(), avail, p); std::tie(p, avail) = copy((*hd).value, avail, p);
break; break;
} }
} }
std::tie(p, avail) = copy("-", avail, p); std::tie(p, avail) = copy_l("-", avail, p);
break;
case SHRPX_LOGF_AUTHORITY:
if (downstream) {
auto &authority = downstream->get_request_http2_authority();
if (!authority.empty()) {
std::tie(p, avail) = copy(authority, avail, p);
break;
}
}
std::tie(p, avail) = copy_l("-", avail, p);
break; break;
case SHRPX_LOGF_REMOTE_PORT: case SHRPX_LOGF_REMOTE_PORT:
std::tie(p, avail) = copy(lgsp.remote_port, avail, p); std::tie(p, avail) = copy(lgsp.remote_port, avail, p);
break; break;
case SHRPX_LOGF_SERVER_PORT: case SHRPX_LOGF_SERVER_PORT:
std::tie(p, avail) = copy(util::utos(lgsp.server_port).c_str(), avail, p); std::tie(p, avail) = copy(util::utos(lgsp.server_port), avail, p);
break; break;
case SHRPX_LOGF_REQUEST_TIME: { case SHRPX_LOGF_REQUEST_TIME: {
auto t = std::chrono::duration_cast<std::chrono::milliseconds>( auto t = std::chrono::duration_cast<std::chrono::milliseconds>(
@ -265,31 +300,31 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
sec += "."; sec += ".";
sec += frac; sec += frac;
std::tie(p, avail) = copy(sec.c_str(), avail, p); std::tie(p, avail) = copy(sec, avail, p);
} break; } break;
case SHRPX_LOGF_PID: case SHRPX_LOGF_PID:
std::tie(p, avail) = copy(util::utos(lgsp.pid).c_str(), avail, p); std::tie(p, avail) = copy(util::utos(lgsp.pid), avail, p);
break; break;
case SHRPX_LOGF_ALPN: case SHRPX_LOGF_ALPN:
std::tie(p, avail) = copy(lgsp.alpn, avail, p); std::tie(p, avail) = copy(lgsp.alpn, avail, p);
break; break;
case SHRPX_LOGF_SSL_CIPHER: case SHRPX_LOGF_SSL_CIPHER:
if (!lgsp.tls_info) { if (!lgsp.tls_info) {
std::tie(p, avail) = copy("-", avail, p); std::tie(p, avail) = copy_l("-", avail, p);
break; break;
} }
std::tie(p, avail) = copy(lgsp.tls_info->cipher, avail, p); std::tie(p, avail) = copy(lgsp.tls_info->cipher, avail, p);
break; break;
case SHRPX_LOGF_SSL_PROTOCOL: case SHRPX_LOGF_SSL_PROTOCOL:
if (!lgsp.tls_info) { if (!lgsp.tls_info) {
std::tie(p, avail) = copy("-", avail, p); std::tie(p, avail) = copy_l("-", avail, p);
break; break;
} }
std::tie(p, avail) = copy(lgsp.tls_info->protocol, avail, p); std::tie(p, avail) = copy(lgsp.tls_info->protocol, avail, p);
break; break;
case SHRPX_LOGF_SSL_SESSION_ID: case SHRPX_LOGF_SSL_SESSION_ID:
if (!lgsp.tls_info || lgsp.tls_info->session_id_length == 0) { if (!lgsp.tls_info || lgsp.tls_info->session_id_length == 0) {
std::tie(p, avail) = copy("-", avail, p); std::tie(p, avail) = copy_l("-", avail, p);
break; break;
} }
std::tie(p, avail) = std::tie(p, avail) =
@ -298,11 +333,11 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
break; break;
case SHRPX_LOGF_SSL_SESSION_REUSED: case SHRPX_LOGF_SSL_SESSION_REUSED:
if (!lgsp.tls_info) { if (!lgsp.tls_info) {
std::tie(p, avail) = copy("-", avail, p); std::tie(p, avail) = copy_l("-", avail, p);
break; break;
} }
std::tie(p, avail) = std::tie(p, avail) =
copy(lgsp.tls_info->session_reused ? "r" : ".", avail, p); copy_l(lgsp.tls_info->session_reused ? "r" : ".", avail, p);
break; break;
case SHRPX_LOGF_NONE: case SHRPX_LOGF_NONE:
break; break;

View File

@ -118,6 +118,7 @@ enum LogFragmentType {
SHRPX_LOGF_STATUS, SHRPX_LOGF_STATUS,
SHRPX_LOGF_BODY_BYTES_SENT, SHRPX_LOGF_BODY_BYTES_SENT,
SHRPX_LOGF_HTTP, SHRPX_LOGF_HTTP,
SHRPX_LOGF_AUTHORITY,
SHRPX_LOGF_REMOTE_PORT, SHRPX_LOGF_REMOTE_PORT,
SHRPX_LOGF_SERVER_PORT, SHRPX_LOGF_SERVER_PORT,
SHRPX_LOGF_REQUEST_TIME, SHRPX_LOGF_REQUEST_TIME,