nghttpx: Rewrite logging system
This change rewrites logging system of nghttpx. Previously access log and error log are written to stderr or syslog and there was no option to change stderr to something else. With this change, file path of access log and error log can be configured separately and logging to regular file is now added. To support rotating log, if SIGUSR1 signal is received by nghttpx, it closes the current log files and reopen it with the same name. The format of access log is changed and has same look of apache's. But not all columns are not supported yet.
This commit is contained in:
parent
57230b4029
commit
0ce848a611
|
@ -113,7 +113,7 @@ NGHTTPX_SRCS = \
|
||||||
shrpx_ssl.cc shrpx_ssl.h \
|
shrpx_ssl.cc shrpx_ssl.h \
|
||||||
shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \
|
shrpx_thread_event_receiver.cc shrpx_thread_event_receiver.h \
|
||||||
shrpx_worker.cc shrpx_worker.h \
|
shrpx_worker.cc shrpx_worker.h \
|
||||||
shrpx_accesslog.cc shrpx_accesslog.h
|
shrpx_worker_config.cc shrpx_worker_config.h
|
||||||
|
|
||||||
if HAVE_SPDYLAY
|
if HAVE_SPDYLAY
|
||||||
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
|
NGHTTPX_SRCS += shrpx_spdy_upstream.cc shrpx_spdy_upstream.h
|
||||||
|
|
112
src/shrpx.cc
112
src/shrpx.cc
|
@ -35,6 +35,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_listen_handler.h"
|
#include "shrpx_listen_handler.h"
|
||||||
#include "shrpx_ssl.h"
|
#include "shrpx_ssl.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "app_helper.h"
|
#include "app_helper.h"
|
||||||
#include "ssl.h"
|
#include "ssl.h"
|
||||||
|
@ -60,6 +62,10 @@ using namespace nghttp2;
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const int REOPEN_LOG_SIGNAL = SIGUSR1;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void ssl_acceptcb(evconnlistener *listener, int fd,
|
void ssl_acceptcb(evconnlistener *listener, int fd,
|
||||||
sockaddr *addr, int addrlen, void *arg)
|
sockaddr *addr, int addrlen, void *arg)
|
||||||
|
@ -252,9 +258,28 @@ void save_pid()
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void reopen_log_signal_cb(evutil_socket_t sig, short events, void *arg)
|
||||||
|
{
|
||||||
|
auto listener_handler = static_cast<ListenHandler*>(arg);
|
||||||
|
|
||||||
|
if(LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Reopening log files: worker_info(" << &worker_config << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)reopen_log_files();
|
||||||
|
|
||||||
|
if(get_config()->num_worker > 1) {
|
||||||
|
listener_handler->worker_reopen_log_files();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int event_loop()
|
int event_loop()
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
|
||||||
auto evbase = event_base_new();
|
auto evbase = event_base_new();
|
||||||
if(!evbase) {
|
if(!evbase) {
|
||||||
LOG(FATAL) << "event_base_new() failed";
|
LOG(FATAL) << "event_base_new() failed";
|
||||||
|
@ -298,16 +323,47 @@ int event_loop()
|
||||||
// After that, we drop the root privileges if needed.
|
// After that, we drop the root privileges if needed.
|
||||||
drop_privileges();
|
drop_privileges();
|
||||||
|
|
||||||
|
sigset_t signals;
|
||||||
|
sigemptyset(&signals);
|
||||||
|
sigaddset(&signals, REOPEN_LOG_SIGNAL);
|
||||||
|
|
||||||
|
rv = pthread_sigmask(SIG_BLOCK, &signals, nullptr);
|
||||||
|
if(rv != 0) {
|
||||||
|
LOG(ERROR) << "Blocking REOPEN_LOG_SIGNAL failed: " << strerror(rv);
|
||||||
|
}
|
||||||
|
|
||||||
if(get_config()->num_worker > 1) {
|
if(get_config()->num_worker > 1) {
|
||||||
listener_handler->create_worker_thread(get_config()->num_worker);
|
listener_handler->create_worker_thread(get_config()->num_worker);
|
||||||
} else if(get_config()->downstream_proto == PROTO_HTTP2) {
|
} else if(get_config()->downstream_proto == PROTO_HTTP2) {
|
||||||
listener_handler->create_http2_session();
|
listener_handler->create_http2_session();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = pthread_sigmask(SIG_UNBLOCK, &signals, nullptr);
|
||||||
|
if(rv != 0) {
|
||||||
|
LOG(ERROR) << "Unblocking REOPEN_LOG_SIGNAL failed: " << strerror(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto reopen_log_signal_event = evsignal_new(evbase, REOPEN_LOG_SIGNAL,
|
||||||
|
reopen_log_signal_cb,
|
||||||
|
listener_handler);
|
||||||
|
|
||||||
|
if(!reopen_log_signal_event) {
|
||||||
|
LOG(ERROR) << "evsignal_new failed";
|
||||||
|
} else {
|
||||||
|
rv = event_add(reopen_log_signal_event, nullptr);
|
||||||
|
if(rv < 0) {
|
||||||
|
LOG(ERROR) << "event_add for reopen_log_signal_event failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
LOG(INFO) << "Entering event loop";
|
LOG(INFO) << "Entering event loop";
|
||||||
}
|
}
|
||||||
event_base_loop(evbase, 0);
|
event_base_loop(evbase, 0);
|
||||||
|
|
||||||
|
if(reopen_log_signal_event) {
|
||||||
|
event_free(reopen_log_signal_event);
|
||||||
|
}
|
||||||
if(evlistener4) {
|
if(evlistener4) {
|
||||||
evconnlistener_free(evlistener4);
|
evconnlistener_free(evlistener4);
|
||||||
}
|
}
|
||||||
|
@ -399,11 +455,12 @@ void fill_default_config()
|
||||||
mod_config()->http2_max_concurrent_streams = 100;
|
mod_config()->http2_max_concurrent_streams = 100;
|
||||||
mod_config()->add_x_forwarded_for = false;
|
mod_config()->add_x_forwarded_for = false;
|
||||||
mod_config()->no_via = false;
|
mod_config()->no_via = false;
|
||||||
mod_config()->accesslog = false;
|
mod_config()->accesslog_file = nullptr;
|
||||||
|
mod_config()->accesslog_syslog = false;
|
||||||
|
mod_config()->errorlog_file = strcopy("/dev/stderr");
|
||||||
|
mod_config()->errorlog_syslog = false;
|
||||||
mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf");
|
mod_config()->conf_path = strcopy("/etc/nghttpx/nghttpx.conf");
|
||||||
mod_config()->syslog = false;
|
|
||||||
mod_config()->syslog_facility = LOG_DAEMON;
|
mod_config()->syslog_facility = LOG_DAEMON;
|
||||||
mod_config()->use_syslog = false;
|
|
||||||
// Default accept() backlog
|
// Default accept() backlog
|
||||||
mod_config()->backlog = -1;
|
mod_config()->backlog = -1;
|
||||||
mod_config()->ciphers = nullptr;
|
mod_config()->ciphers = nullptr;
|
||||||
|
@ -419,7 +476,6 @@ void fill_default_config()
|
||||||
mod_config()->gid = 0;
|
mod_config()->gid = 0;
|
||||||
mod_config()->backend_ipv4 = false;
|
mod_config()->backend_ipv4 = false;
|
||||||
mod_config()->backend_ipv6 = false;
|
mod_config()->backend_ipv6 = false;
|
||||||
mod_config()->tty = isatty(fileno(stderr));
|
|
||||||
mod_config()->cert_tree = nullptr;
|
mod_config()->cert_tree = nullptr;
|
||||||
mod_config()->downstream_http_proxy_userinfo = nullptr;
|
mod_config()->downstream_http_proxy_userinfo = nullptr;
|
||||||
mod_config()->downstream_http_proxy_host = nullptr;
|
mod_config()->downstream_http_proxy_host = nullptr;
|
||||||
|
@ -719,8 +775,19 @@ Logging:
|
||||||
Set the severity level of log output. <LEVEL>
|
Set the severity level of log output. <LEVEL>
|
||||||
must be one of INFO, WARNING, ERROR and FATAL.
|
must be one of INFO, WARNING, ERROR and FATAL.
|
||||||
Default: WARNING
|
Default: WARNING
|
||||||
--accesslog Print simple accesslog to stderr.
|
--accesslog-file=<PATH>
|
||||||
--syslog Send log messages to syslog.
|
Set path to write access log. To reopen file,
|
||||||
|
send USR1 signal to nghttpx.
|
||||||
|
--accesslog-syslog
|
||||||
|
Send access log to syslog. If this option is
|
||||||
|
used, --access-file option is ignored.
|
||||||
|
--errorlog-file=<PATH>
|
||||||
|
Set path to write error log. To reopen file,
|
||||||
|
send USR1 signal to nghttpx.
|
||||||
|
Default: )"
|
||||||
|
<< get_config()->errorlog_file.get() << R"(
|
||||||
|
--errorlog-syslog Send error log to syslog. If this option is
|
||||||
|
used, --errorlog-file option is ignored.
|
||||||
--syslog-facility=<FACILITY>
|
--syslog-facility=<FACILITY>
|
||||||
Set syslog facility to <FACILITY>.
|
Set syslog facility to <FACILITY>.
|
||||||
Default: )"
|
Default: )"
|
||||||
|
@ -807,13 +874,12 @@ int main(int argc, char **argv)
|
||||||
{"frontend-write-timeout", required_argument, &flag, 4},
|
{"frontend-write-timeout", required_argument, &flag, 4},
|
||||||
{"backend-read-timeout", required_argument, &flag, 5},
|
{"backend-read-timeout", required_argument, &flag, 5},
|
||||||
{"backend-write-timeout", required_argument, &flag, 6},
|
{"backend-write-timeout", required_argument, &flag, 6},
|
||||||
{"accesslog", no_argument, &flag, 7},
|
{"accesslog-file", required_argument, &flag, 7},
|
||||||
{"backend-keep-alive-timeout", required_argument, &flag, 8},
|
{"backend-keep-alive-timeout", required_argument, &flag, 8},
|
||||||
{"frontend-http2-window-bits", required_argument, &flag, 9},
|
{"frontend-http2-window-bits", required_argument, &flag, 9},
|
||||||
{"pid-file", required_argument, &flag, 10},
|
{"pid-file", required_argument, &flag, 10},
|
||||||
{"user", required_argument, &flag, 11},
|
{"user", required_argument, &flag, 11},
|
||||||
{"conf", required_argument, &flag, 12},
|
{"conf", required_argument, &flag, 12},
|
||||||
{"syslog", no_argument, &flag, 13},
|
|
||||||
{"syslog-facility", required_argument, &flag, 14},
|
{"syslog-facility", required_argument, &flag, 14},
|
||||||
{"backlog", required_argument, &flag, 15},
|
{"backlog", required_argument, &flag, 15},
|
||||||
{"ciphers", required_argument, &flag, 16},
|
{"ciphers", required_argument, &flag, 16},
|
||||||
|
@ -850,6 +916,9 @@ int main(int argc, char **argv)
|
||||||
{"altsvc", required_argument, &flag, 54},
|
{"altsvc", required_argument, &flag, 54},
|
||||||
{"add-response-header", required_argument, &flag, 55},
|
{"add-response-header", required_argument, &flag, 55},
|
||||||
{"worker-frontend-connections", required_argument, &flag, 56},
|
{"worker-frontend-connections", required_argument, &flag, 56},
|
||||||
|
{"accesslog-syslog", no_argument, &flag, 57},
|
||||||
|
{"errorlog-file", required_argument, &flag, 58},
|
||||||
|
{"errorlog-syslog", no_argument, &flag, 59},
|
||||||
{nullptr, 0, nullptr, 0 }
|
{nullptr, 0, nullptr, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -930,7 +999,7 @@ int main(int argc, char **argv)
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_WRITE_TIMEOUT, optarg);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG, "yes");
|
cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_FILE, optarg);
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
// --backend-keep-alive-timeout
|
// --backend-keep-alive-timeout
|
||||||
|
@ -950,10 +1019,6 @@ int main(int argc, char **argv)
|
||||||
// --conf
|
// --conf
|
||||||
mod_config()->conf_path = strcopy(optarg);
|
mod_config()->conf_path = strcopy(optarg);
|
||||||
break;
|
break;
|
||||||
case 13:
|
|
||||||
// --syslog
|
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG, "yes");
|
|
||||||
break;
|
|
||||||
case 14:
|
case 14:
|
||||||
// --syslog-facility
|
// --syslog-facility
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_SYSLOG_FACILITY, optarg);
|
||||||
|
@ -1102,6 +1167,18 @@ int main(int argc, char **argv)
|
||||||
// --worker-frontend-connections
|
// --worker-frontend-connections
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_WORKER_FRONTEND_CONNECTIONS, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 57:
|
||||||
|
// --accesslog-syslog
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_ACCESSLOG_SYSLOG, "yes");
|
||||||
|
break;
|
||||||
|
case 58:
|
||||||
|
// --errorlog-file
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_FILE, optarg);
|
||||||
|
break;
|
||||||
|
case 59:
|
||||||
|
// --errorlog-syslog
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_ERRORLOG_SYSLOG, "yes");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1140,11 +1217,14 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config()->syslog) {
|
if(get_config()->accesslog_syslog || get_config()->errorlog_syslog) {
|
||||||
openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
|
openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
|
||||||
get_config()->syslog_facility);
|
get_config()->syslog_facility);
|
||||||
mod_config()->use_syslog = true;
|
}
|
||||||
mod_config()->tty = false;
|
|
||||||
|
if(reopen_log_files() != 0) {
|
||||||
|
LOG(FATAL) << "Failed to open log file";
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config()->npn_list.empty()) {
|
if(get_config()->npn_list.empty()) {
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
/*
|
|
||||||
* nghttp2 - HTTP/2 C Library
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 Tatsuhiro Tsujikawa
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the
|
|
||||||
* "Software"), to deal in the Software without restriction, including
|
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
* the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be
|
|
||||||
* included in all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
#include "shrpx_accesslog.h"
|
|
||||||
|
|
||||||
#include <syslog.h>
|
|
||||||
|
|
||||||
#include <ctime>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#include "shrpx_config.h"
|
|
||||||
#include "shrpx_downstream.h"
|
|
||||||
|
|
||||||
namespace shrpx {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
std::string get_datestr()
|
|
||||||
{
|
|
||||||
char buf[64];
|
|
||||||
time_t now = time(0);
|
|
||||||
if(ctime_r(&now, buf) == 0) {
|
|
||||||
buf[0] = '\0';
|
|
||||||
} else {
|
|
||||||
size_t len = strlen(buf);
|
|
||||||
if(len == 0) {
|
|
||||||
buf[0] = '\0';
|
|
||||||
} else {
|
|
||||||
buf[strlen(buf)-1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void upstream_connect(const std::string& client_ip)
|
|
||||||
{
|
|
||||||
if(get_config()->use_syslog) {
|
|
||||||
syslog(LOG_INFO, "%s ACCEPT\n", client_ip.c_str());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s [%s] ACCEPT\n", client_ip.c_str(),
|
|
||||||
get_datestr().c_str());
|
|
||||||
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
const char* status_code_color(unsigned int status_code)
|
|
||||||
{
|
|
||||||
if(status_code <= 199) {
|
|
||||||
return "\033[1;36m";
|
|
||||||
} else if(status_code <= 299) {
|
|
||||||
return "\033[1;32m";
|
|
||||||
} else if(status_code <= 399) {
|
|
||||||
return "\033[1;34m";
|
|
||||||
} else if(status_code <= 499) {
|
|
||||||
return "\033[1;31m";
|
|
||||||
} else if(status_code <= 599) {
|
|
||||||
return "\033[1;35m";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void upstream_response(const std::string& client_ip, unsigned int status_code,
|
|
||||||
Downstream *downstream)
|
|
||||||
{
|
|
||||||
if(!downstream) {
|
|
||||||
if(get_config()->use_syslog) {
|
|
||||||
syslog(LOG_INFO, "%s %u 0 \"-\"\n", client_ip.c_str(), status_code);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s%s [%s] %u%s 0 \"-\"\n",
|
|
||||||
get_config()->tty ? status_code_color(status_code) : "",
|
|
||||||
client_ip.c_str(), get_datestr().c_str(),
|
|
||||||
status_code,
|
|
||||||
get_config()->tty ? "\033[0m" : "");
|
|
||||||
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *path;
|
|
||||||
|
|
||||||
if(downstream->get_request_path().empty()) {
|
|
||||||
path = downstream->get_request_http2_authority().c_str();
|
|
||||||
} else {
|
|
||||||
path = downstream->get_request_path().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(get_config()->use_syslog) {
|
|
||||||
syslog(LOG_INFO, "%s %u %d \"%s %s HTTP/%u.%u\"",
|
|
||||||
client_ip.c_str(),
|
|
||||||
status_code,
|
|
||||||
downstream->get_stream_id(),
|
|
||||||
downstream->get_request_method().c_str(),
|
|
||||||
path,
|
|
||||||
downstream->get_request_major(),
|
|
||||||
downstream->get_request_minor());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s [%s] %s%u%s stream(%d) \"%s %s HTTP/%u.%u\"\n",
|
|
||||||
client_ip.c_str(), get_datestr().c_str(),
|
|
||||||
get_config()->tty ? status_code_color(status_code) : "",
|
|
||||||
status_code,
|
|
||||||
get_config()->tty ? "\033[0m" : "",
|
|
||||||
downstream->get_stream_id(),
|
|
||||||
downstream->get_request_method().c_str(),
|
|
||||||
path,
|
|
||||||
downstream->get_request_major(),
|
|
||||||
downstream->get_request_minor());
|
|
||||||
|
|
||||||
fflush(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace shrpx
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_http_downstream_connection.h"
|
#include "shrpx_http_downstream_connection.h"
|
||||||
#include "shrpx_http2_downstream_connection.h"
|
#include "shrpx_http2_downstream_connection.h"
|
||||||
#include "shrpx_accesslog.h"
|
|
||||||
#include "shrpx_ssl.h"
|
#include "shrpx_ssl.h"
|
||||||
#include "shrpx_worker.h"
|
#include "shrpx_worker.h"
|
||||||
#ifdef HAVE_SPDYLAY
|
#ifdef HAVE_SPDYLAY
|
||||||
|
|
|
@ -74,7 +74,10 @@ const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[] = "frontend-read-timeout";
|
||||||
const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[] = "frontend-write-timeout";
|
const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[] = "frontend-write-timeout";
|
||||||
const char SHRPX_OPT_BACKEND_READ_TIMEOUT[] = "backend-read-timeout";
|
const char SHRPX_OPT_BACKEND_READ_TIMEOUT[] = "backend-read-timeout";
|
||||||
const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[] = "backend-write-timeout";
|
const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[] = "backend-write-timeout";
|
||||||
const char SHRPX_OPT_ACCESSLOG[] = "accesslog";
|
const char SHRPX_OPT_ACCESSLOG_FILE[] = "accesslog-file";
|
||||||
|
const char SHRPX_OPT_ACCESSLOG_SYSLOG[] = "accesslog-syslog";
|
||||||
|
const char SHRPX_OPT_ERRORLOG_FILE[] = "errorlog-file";
|
||||||
|
const char SHRPX_OPT_ERRORLOG_SYSLOG[] = "errorlog-syslog";
|
||||||
const char
|
const char
|
||||||
SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[] = "backend-keep-alive-timeout";
|
SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[] = "backend-keep-alive-timeout";
|
||||||
const char
|
const char
|
||||||
|
@ -89,7 +92,6 @@ const char SHRPX_OPT_BACKEND_NO_TLS[] = "backend-no-tls";
|
||||||
const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[] = "backend-tls-sni-field";
|
const char SHRPX_OPT_BACKEND_TLS_SNI_FIELD[] = "backend-tls-sni-field";
|
||||||
const char SHRPX_OPT_PID_FILE[] = "pid-file";
|
const char SHRPX_OPT_PID_FILE[] = "pid-file";
|
||||||
const char SHRPX_OPT_USER[] = "user";
|
const char SHRPX_OPT_USER[] = "user";
|
||||||
const char SHRPX_OPT_SYSLOG[] = "syslog";
|
|
||||||
const char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility";
|
const char SHRPX_OPT_SYSLOG_FACILITY[] = "syslog-facility";
|
||||||
const char SHRPX_OPT_BACKLOG[] = "backlog";
|
const char SHRPX_OPT_BACKLOG[] = "backlog";
|
||||||
const char SHRPX_OPT_CIPHERS[] = "ciphers";
|
const char SHRPX_OPT_CIPHERS[] = "ciphers";
|
||||||
|
@ -401,8 +403,26 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(util::strieq(opt, SHRPX_OPT_ACCESSLOG)) {
|
if(util::strieq(opt, SHRPX_OPT_ACCESSLOG_FILE)) {
|
||||||
mod_config()->accesslog = util::strieq(optarg, "yes");
|
mod_config()->accesslog_file = strcopy(optarg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(util::strieq(opt, SHRPX_OPT_ACCESSLOG_SYSLOG)) {
|
||||||
|
mod_config()->accesslog_syslog = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(util::strieq(opt, SHRPX_OPT_ERRORLOG_FILE)) {
|
||||||
|
mod_config()->errorlog_file = strcopy(optarg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(util::strieq(opt, SHRPX_OPT_ERRORLOG_SYSLOG)) {
|
||||||
|
mod_config()->errorlog_syslog = util::strieq(optarg, "yes");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -540,12 +560,6 @@ int parse_config(const char *opt, const char *optarg)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(util::strieq(opt, SHRPX_OPT_SYSLOG)) {
|
|
||||||
mod_config()->syslog = util::strieq(optarg, "yes");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(util::strieq(opt, SHRPX_OPT_SYSLOG_FACILITY)) {
|
if(util::strieq(opt, SHRPX_OPT_SYSLOG_FACILITY)) {
|
||||||
int facility = int_syslog_facility(optarg);
|
int facility = int_syslog_facility(optarg);
|
||||||
if(facility == -1) {
|
if(facility == -1) {
|
||||||
|
|
|
@ -70,7 +70,10 @@ extern const char SHRPX_OPT_FRONTEND_READ_TIMEOUT[];
|
||||||
extern const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[];
|
extern const char SHRPX_OPT_FRONTEND_WRITE_TIMEOUT[];
|
||||||
extern const char SHRPX_OPT_BACKEND_READ_TIMEOUT[];
|
extern const char SHRPX_OPT_BACKEND_READ_TIMEOUT[];
|
||||||
extern const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[];
|
extern const char SHRPX_OPT_BACKEND_WRITE_TIMEOUT[];
|
||||||
extern const char SHRPX_OPT_ACCESSLOG[];
|
extern const char SHRPX_OPT_ACCESSLOG_FILE[];
|
||||||
|
extern const char SHRPX_OPT_ACCESSLOG_SYSLOG[];
|
||||||
|
extern const char SHRPX_OPT_ERRORLOG_FILE[];
|
||||||
|
extern const char SHRPX_OPT_ERRORLOG_SYSLOG[];
|
||||||
extern const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[];
|
extern const char SHRPX_OPT_BACKEND_KEEP_ALIVE_TIMEOUT[];
|
||||||
extern const char SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS[];
|
extern const char SHRPX_OPT_FRONTEND_HTTP2_WINDOW_BITS[];
|
||||||
extern const char SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS[];
|
extern const char SHRPX_OPT_BACKEND_HTTP2_WINDOW_BITS[];
|
||||||
|
@ -80,7 +83,6 @@ extern const char SHRPX_OPT_FRONTEND_NO_TLS[];
|
||||||
extern const char SHRPX_OPT_BACKEND_NO_TLS[];
|
extern const char SHRPX_OPT_BACKEND_NO_TLS[];
|
||||||
extern const char SHRPX_OPT_PID_FILE[];
|
extern const char SHRPX_OPT_PID_FILE[];
|
||||||
extern const char SHRPX_OPT_USER[];
|
extern const char SHRPX_OPT_USER[];
|
||||||
extern const char SHRPX_OPT_SYSLOG[];
|
|
||||||
extern const char SHRPX_OPT_SYSLOG_FACILITY[];
|
extern const char SHRPX_OPT_SYSLOG_FACILITY[];
|
||||||
extern const char SHRPX_OPT_BACKLOG[];
|
extern const char SHRPX_OPT_BACKLOG[];
|
||||||
extern const char SHRPX_OPT_CIPHERS[];
|
extern const char SHRPX_OPT_CIPHERS[];
|
||||||
|
@ -192,6 +194,8 @@ struct Config {
|
||||||
std::unique_ptr<char[]> verify_client_cacert;
|
std::unique_ptr<char[]> verify_client_cacert;
|
||||||
std::unique_ptr<char[]> client_private_key_file;
|
std::unique_ptr<char[]> client_private_key_file;
|
||||||
std::unique_ptr<char[]> client_cert_file;
|
std::unique_ptr<char[]> client_cert_file;
|
||||||
|
std::unique_ptr<char[]> accesslog_file;
|
||||||
|
std::unique_ptr<char[]> errorlog_file;
|
||||||
FILE *http2_upstream_dump_request_header;
|
FILE *http2_upstream_dump_request_header;
|
||||||
FILE *http2_upstream_dump_response_header;
|
FILE *http2_upstream_dump_response_header;
|
||||||
nghttp2_option *http2_option;
|
nghttp2_option *http2_option;
|
||||||
|
@ -235,20 +239,18 @@ struct Config {
|
||||||
bool client_proxy;
|
bool client_proxy;
|
||||||
bool add_x_forwarded_for;
|
bool add_x_forwarded_for;
|
||||||
bool no_via;
|
bool no_via;
|
||||||
bool accesslog;
|
|
||||||
bool upstream_no_tls;
|
bool upstream_no_tls;
|
||||||
bool downstream_no_tls;
|
bool downstream_no_tls;
|
||||||
bool syslog;
|
// Send accesslog to syslog, ignoring accesslog_file.
|
||||||
// This member finally decides syslog is used or not
|
bool accesslog_syslog;
|
||||||
bool use_syslog;
|
// Send errorlog to syslog, ignoring errorlog_file.
|
||||||
|
bool errorlog_syslog;
|
||||||
bool client;
|
bool client;
|
||||||
// true if --client or --client-proxy are enabled.
|
// true if --client or --client-proxy are enabled.
|
||||||
bool client_mode;
|
bool client_mode;
|
||||||
bool insecure;
|
bool insecure;
|
||||||
bool backend_ipv4;
|
bool backend_ipv4;
|
||||||
bool backend_ipv6;
|
bool backend_ipv6;
|
||||||
// true if stderr refers to a terminal and syslog is not used
|
|
||||||
bool tty;
|
|
||||||
bool http2_no_cookie_crumbling;
|
bool http2_no_cookie_crumbling;
|
||||||
bool upstream_frame_debug;
|
bool upstream_frame_debug;
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace shrpx {
|
||||||
|
|
||||||
Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
||||||
: request_bodylen_(0),
|
: request_bodylen_(0),
|
||||||
|
response_bodylen_(0),
|
||||||
upstream_(upstream),
|
upstream_(upstream),
|
||||||
dconn_(nullptr),
|
dconn_(nullptr),
|
||||||
response_body_buf_(nullptr),
|
response_body_buf_(nullptr),
|
||||||
|
@ -408,6 +409,16 @@ void Downstream::set_request_connection_close(bool f)
|
||||||
request_connection_close_ = f;
|
request_connection_close_ = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downstream::set_request_user_agent(std::string user_agent)
|
||||||
|
{
|
||||||
|
request_user_agent_ = std::move(user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& Downstream::get_request_user_agent() const
|
||||||
|
{
|
||||||
|
return request_user_agent_;
|
||||||
|
}
|
||||||
|
|
||||||
bool Downstream::get_request_http2_expect_body() const
|
bool Downstream::get_request_http2_expect_body() const
|
||||||
{
|
{
|
||||||
return request_http2_expect_body_;
|
return request_http2_expect_body_;
|
||||||
|
@ -675,6 +686,16 @@ evbuffer* Downstream::get_response_body_buf()
|
||||||
return response_body_buf_;
|
return response_body_buf_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downstream::add_response_bodylen(size_t amount)
|
||||||
|
{
|
||||||
|
response_bodylen_ += amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t Downstream::get_response_bodylen() const
|
||||||
|
{
|
||||||
|
return response_bodylen_;
|
||||||
|
}
|
||||||
|
|
||||||
void Downstream::set_priority(int32_t pri)
|
void Downstream::set_priority(int32_t pri)
|
||||||
{
|
{
|
||||||
priority_ = pri;
|
priority_ = pri;
|
||||||
|
|
|
@ -140,6 +140,8 @@ public:
|
||||||
void set_chunked_request(bool f);
|
void set_chunked_request(bool f);
|
||||||
bool get_request_connection_close() const;
|
bool get_request_connection_close() const;
|
||||||
void set_request_connection_close(bool f);
|
void set_request_connection_close(bool f);
|
||||||
|
void set_request_user_agent(std::string user_agent);
|
||||||
|
const std::string& get_request_user_agent() const;
|
||||||
bool get_request_http2_expect_body() const;
|
bool get_request_http2_expect_body() const;
|
||||||
void set_request_http2_expect_body(bool f);
|
void set_request_http2_expect_body(bool f);
|
||||||
bool get_expect_100_continue() const;
|
bool get_expect_100_continue() const;
|
||||||
|
@ -207,6 +209,8 @@ public:
|
||||||
int get_response_state() const;
|
int get_response_state() const;
|
||||||
int init_response_body_buf();
|
int init_response_body_buf();
|
||||||
evbuffer* get_response_body_buf();
|
evbuffer* get_response_body_buf();
|
||||||
|
void add_response_bodylen(size_t amount);
|
||||||
|
int64_t get_response_bodylen() const;
|
||||||
nghttp2_error_code get_response_rst_stream_error_code() const;
|
nghttp2_error_code get_response_rst_stream_error_code() const;
|
||||||
void set_response_rst_stream_error_code(nghttp2_error_code error_code);
|
void set_response_rst_stream_error_code(nghttp2_error_code error_code);
|
||||||
// Inspects HTTP/1 response. This checks tranfer-encoding etc.
|
// Inspects HTTP/1 response. This checks tranfer-encoding etc.
|
||||||
|
@ -230,6 +234,7 @@ private:
|
||||||
|
|
||||||
std::string request_method_;
|
std::string request_method_;
|
||||||
std::string request_path_;
|
std::string request_path_;
|
||||||
|
std::string request_user_agent_;
|
||||||
std::string request_http2_scheme_;
|
std::string request_http2_scheme_;
|
||||||
std::string request_http2_authority_;
|
std::string request_http2_authority_;
|
||||||
std::string assembled_request_cookie_;
|
std::string assembled_request_cookie_;
|
||||||
|
@ -237,6 +242,8 @@ private:
|
||||||
|
|
||||||
// the length of request body
|
// the length of request body
|
||||||
int64_t request_bodylen_;
|
int64_t request_bodylen_;
|
||||||
|
// the length of response body
|
||||||
|
int64_t response_bodylen_;
|
||||||
|
|
||||||
Upstream *upstream_;
|
Upstream *upstream_;
|
||||||
DownstreamConnection *dconn_;
|
DownstreamConnection *dconn_;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_log.h"
|
#include "shrpx_log.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "shrpx_error.h"
|
#include "shrpx_error.h"
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
#include "shrpx_http2_session.h"
|
#include "shrpx_http2_session.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "shrpx_client_handler.h"
|
#include "shrpx_client_handler.h"
|
||||||
#include "shrpx_ssl.h"
|
#include "shrpx_ssl.h"
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
@ -1120,6 +1121,8 @@ int on_data_chunk_recv_callback(nghttp2_session *session,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downstream->add_response_bodylen(len);
|
||||||
|
|
||||||
auto upstream = downstream->get_upstream();
|
auto upstream = downstream->get_upstream();
|
||||||
rv = upstream->on_downstream_body(downstream, data, len, false);
|
rv = upstream->on_downstream_body(downstream, data, len, false);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "shrpx_downstream_connection.h"
|
#include "shrpx_downstream_connection.h"
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
#include "shrpx_accesslog.h"
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
@ -310,6 +310,8 @@ int on_request_headers(Http2Upstream *upstream,
|
||||||
auto path = http2::get_unique_header(nva, ":path");
|
auto path = http2::get_unique_header(nva, ":path");
|
||||||
auto method = http2::get_unique_header(nva, ":method");
|
auto method = http2::get_unique_header(nva, ":method");
|
||||||
auto scheme = http2::get_unique_header(nva, ":scheme");
|
auto scheme = http2::get_unique_header(nva, ":scheme");
|
||||||
|
auto user_agent = http2::get_header(nva, "user-agent");
|
||||||
|
|
||||||
bool is_connect = method && "CONNECT" == method->value;
|
bool is_connect = method && "CONNECT" == method->value;
|
||||||
bool having_host = http2::non_empty_value(host);
|
bool having_host = http2::non_empty_value(host);
|
||||||
bool having_authority = http2::non_empty_value(authority);
|
bool having_authority = http2::non_empty_value(authority);
|
||||||
|
@ -345,7 +347,7 @@ int on_request_headers(Http2Upstream *upstream,
|
||||||
downstream->set_request_http2_scheme(http2::value_to_str(scheme));
|
downstream->set_request_http2_scheme(http2::value_to_str(scheme));
|
||||||
downstream->set_request_http2_authority(http2::value_to_str(authority));
|
downstream->set_request_http2_authority(http2::value_to_str(authority));
|
||||||
downstream->set_request_path(http2::value_to_str(path));
|
downstream->set_request_path(http2::value_to_str(path));
|
||||||
|
downstream->set_request_user_agent(http2::value_to_str(user_agent));
|
||||||
|
|
||||||
if(!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
|
if(!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
|
||||||
downstream->set_request_http2_expect_body(true);
|
downstream->set_request_http2_expect_body(true);
|
||||||
|
@ -1015,6 +1017,10 @@ ssize_t downstream_data_read_callback(nghttp2_session *session,
|
||||||
if(!downstream->get_upgraded()) {
|
if(!downstream->get_upgraded()) {
|
||||||
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
|
||||||
|
|
||||||
|
upstream_accesslog(upstream->get_client_handler()->get_ipaddr(),
|
||||||
|
downstream->get_response_http_status(),
|
||||||
|
downstream);
|
||||||
|
|
||||||
if(nghttp2_session_get_stream_remote_close(session, stream_id) == 0) {
|
if(nghttp2_session_get_stream_remote_close(session, stream_id) == 0) {
|
||||||
upstream->rst_stream(downstream, NGHTTP2_NO_ERROR);
|
upstream->rst_stream(downstream, NGHTTP2_NO_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -1044,6 +1050,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
auto html = http::create_error_html(status_code);
|
auto html = http::create_error_html(status_code);
|
||||||
|
downstream->set_response_http_status(status_code);
|
||||||
downstream->init_response_body_buf();
|
downstream->init_response_body_buf();
|
||||||
auto body = downstream->get_response_body_buf();
|
auto body = downstream->get_response_body_buf();
|
||||||
rv = evbuffer_add(body, html.c_str(), html.size());
|
rv = evbuffer_add(body, html.c_str(), html.size());
|
||||||
|
@ -1073,10 +1080,6 @@ int Http2Upstream::error_reply(Downstream *downstream,
|
||||||
<< nghttp2_strerror(rv);
|
<< nghttp2_strerror(rv);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(get_client_handler()->get_ipaddr(),
|
|
||||||
status_code, downstream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1188,10 +1191,10 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
ULOG(FATAL, this) << "nghttp2_submit_response() failed";
|
ULOG(FATAL, this) << "nghttp2_submit_response() failed";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(get_client_handler()->get_ipaddr(),
|
if(downstream->get_upgraded()) {
|
||||||
downstream->get_response_http_status(),
|
upstream_accesslog(get_client_handler()->get_ipaddr(),
|
||||||
downstream);
|
downstream->get_response_http_status(), downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream->clear_response_headers();
|
downstream->clear_response_headers();
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_error.h"
|
#include "shrpx_error.h"
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -234,7 +235,7 @@ int HttpDownstreamConnection::push_request_headers()
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
const char *hdrp;
|
const char *hdrp;
|
||||||
std::string nhdrs;
|
std::string nhdrs;
|
||||||
if(get_config()->tty) {
|
if(worker_config.errorlog_tty) {
|
||||||
nhdrs = http::colorizeHeaders(hdrs.c_str());
|
nhdrs = http::colorizeHeaders(hdrs.c_str());
|
||||||
hdrp = nhdrs.c_str();
|
hdrp = nhdrs.c_str();
|
||||||
} else {
|
} else {
|
||||||
|
@ -492,6 +493,9 @@ namespace {
|
||||||
int htp_bodycb(http_parser *htp, const char *data, size_t len)
|
int htp_bodycb(http_parser *htp, const char *data, size_t len)
|
||||||
{
|
{
|
||||||
auto downstream = static_cast<Downstream*>(htp->data);
|
auto downstream = static_cast<Downstream*>(htp->data);
|
||||||
|
|
||||||
|
downstream->add_response_bodylen(len);
|
||||||
|
|
||||||
return downstream->get_upstream()->on_downstream_body
|
return downstream->get_upstream()->on_downstream_body
|
||||||
(downstream, reinterpret_cast<const uint8_t*>(data), len, true);
|
(downstream, reinterpret_cast<const uint8_t*>(data), len, true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_error.h"
|
#include "shrpx_error.h"
|
||||||
#include "shrpx_accesslog.h"
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -150,8 +150,6 @@ int htp_hdrs_completecb(http_parser *htp)
|
||||||
|
|
||||||
downstream->set_request_connection_close(!http_should_keep_alive(htp));
|
downstream->set_request_connection_close(!http_should_keep_alive(htp));
|
||||||
|
|
||||||
downstream->inspect_http1_request();
|
|
||||||
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << downstream->get_request_method() << " "
|
ss << downstream->get_request_method() << " "
|
||||||
|
@ -166,6 +164,15 @@ int htp_hdrs_completecb(http_parser *htp)
|
||||||
ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str();
|
ULOG(INFO, upstream) << "HTTP request headers\n" << ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downstream->normalize_request_headers();
|
||||||
|
auto& nva = downstream->get_request_headers();
|
||||||
|
|
||||||
|
auto user_agent = http2::get_header(nva, "user-agent");
|
||||||
|
|
||||||
|
downstream->set_request_user_agent(http2::value_to_str(user_agent));
|
||||||
|
|
||||||
|
downstream->inspect_http1_request();
|
||||||
|
|
||||||
if(get_config()->client_proxy &&
|
if(get_config()->client_proxy &&
|
||||||
downstream->get_request_method() != "CONNECT") {
|
downstream->get_request_method() != "CONNECT") {
|
||||||
// Make sure that request path is an absolute URI.
|
// Make sure that request path is an absolute URI.
|
||||||
|
@ -658,6 +665,12 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
||||||
int HttpsUpstream::error_reply(unsigned int status_code)
|
int HttpsUpstream::error_reply(unsigned int status_code)
|
||||||
{
|
{
|
||||||
auto html = http::create_error_html(status_code);
|
auto html = http::create_error_html(status_code);
|
||||||
|
auto downstream = get_downstream();
|
||||||
|
|
||||||
|
if(downstream) {
|
||||||
|
downstream->set_response_http_status(status_code);
|
||||||
|
}
|
||||||
|
|
||||||
std::string header;
|
std::string header;
|
||||||
header.reserve(512);
|
header.reserve(512);
|
||||||
header += "HTTP/1.1 ";
|
header += "HTTP/1.1 ";
|
||||||
|
@ -677,14 +690,11 @@ int HttpsUpstream::error_reply(unsigned int status_code)
|
||||||
ULOG(FATAL, this) << "evbuffer_add() failed";
|
ULOG(FATAL, this) << "evbuffer_add() failed";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
auto downstream = get_downstream();
|
|
||||||
if(downstream) {
|
if(downstream) {
|
||||||
downstream->set_response_state(Downstream::MSG_COMPLETE);
|
downstream->set_response_state(Downstream::MSG_COMPLETE);
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(this->get_client_handler()->get_ipaddr(), status_code,
|
|
||||||
downstream);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -811,7 +821,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
const char *hdrp;
|
const char *hdrp;
|
||||||
std::string nhdrs;
|
std::string nhdrs;
|
||||||
if(get_config()->tty) {
|
if(worker_config.errorlog_tty) {
|
||||||
nhdrs = http::colorizeHeaders(hdrs.c_str());
|
nhdrs = http::colorizeHeaders(hdrs.c_str());
|
||||||
hdrp = nhdrs.c_str();
|
hdrp = nhdrs.c_str();
|
||||||
} else {
|
} else {
|
||||||
|
@ -824,9 +834,10 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
ULOG(FATAL, this) << "evbuffer_add() failed";
|
ULOG(FATAL, this) << "evbuffer_add() failed";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(this->get_client_handler()->get_ipaddr(),
|
if(downstream->get_upgraded()) {
|
||||||
downstream->get_response_http_status(), downstream);
|
upstream_accesslog(this->get_client_handler()->get_ipaddr(),
|
||||||
|
downstream->get_response_http_status(), downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream->clear_response_headers();
|
downstream->clear_response_headers();
|
||||||
|
@ -879,6 +890,13 @@ int HttpsUpstream::on_downstream_body_complete(Downstream *downstream)
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
DLOG(INFO, downstream) << "HTTP response completed";
|
DLOG(INFO, downstream) << "HTTP response completed";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!downstream->get_upgraded()) {
|
||||||
|
upstream_accesslog(get_client_handler()->get_ipaddr(),
|
||||||
|
downstream->get_response_http_status(),
|
||||||
|
downstream);
|
||||||
|
}
|
||||||
|
|
||||||
if(downstream->get_request_connection_close() ||
|
if(downstream->get_request_connection_close() ||
|
||||||
downstream->get_response_connection_close()) {
|
downstream->get_response_connection_close()) {
|
||||||
auto handler = get_client_handler();
|
auto handler = get_client_handler();
|
||||||
|
|
|
@ -52,7 +52,6 @@ ListenHandler::ListenHandler(event_base *evbase, SSL_CTX *sv_ssl_ctx,
|
||||||
rate_limit_group_(bufferevent_rate_limit_group_new
|
rate_limit_group_(bufferevent_rate_limit_group_new
|
||||||
(evbase, get_config()->worker_rate_limit_cfg)),
|
(evbase, get_config()->worker_rate_limit_cfg)),
|
||||||
worker_stat_(util::make_unique<WorkerStat>()),
|
worker_stat_(util::make_unique<WorkerStat>()),
|
||||||
num_worker_(0),
|
|
||||||
worker_round_robin_cnt_(0)
|
worker_round_robin_cnt_(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -61,22 +60,33 @@ ListenHandler::~ListenHandler()
|
||||||
bufferevent_rate_limit_group_free(rate_limit_group_);
|
bufferevent_rate_limit_group_free(rate_limit_group_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListenHandler::worker_reopen_log_files()
|
||||||
|
{
|
||||||
|
WorkerEvent wev;
|
||||||
|
|
||||||
|
memset(&wev, 0, sizeof(wev));
|
||||||
|
wev.type = REOPEN_LOG;
|
||||||
|
|
||||||
|
for(auto& info : workers_) {
|
||||||
|
bufferevent_write(info.bev, &wev, sizeof(wev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ListenHandler::create_worker_thread(size_t num)
|
void ListenHandler::create_worker_thread(size_t num)
|
||||||
{
|
{
|
||||||
workers_.resize(num);
|
workers_.resize(0);
|
||||||
num_worker_ = 0;
|
|
||||||
for(size_t i = 0; i < num; ++i) {
|
for(size_t i = 0; i < num; ++i) {
|
||||||
int rv;
|
int rv;
|
||||||
auto info = &workers_[num_worker_];
|
auto info = WorkerInfo();
|
||||||
rv = socketpair(AF_UNIX, SOCK_STREAM, 0, info->sv);
|
rv = socketpair(AF_UNIX, SOCK_STREAM, 0, info.sv);
|
||||||
if(rv == -1) {
|
if(rv == -1) {
|
||||||
LLOG(ERROR, this) << "socketpair() failed: errno=" << errno;
|
LLOG(ERROR, this) << "socketpair() failed: errno=" << errno;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
evutil_make_socket_nonblocking(info->sv[0]);
|
evutil_make_socket_nonblocking(info.sv[0]);
|
||||||
evutil_make_socket_nonblocking(info->sv[1]);
|
evutil_make_socket_nonblocking(info.sv[1]);
|
||||||
info->sv_ssl_ctx = sv_ssl_ctx_;
|
info.sv_ssl_ctx = sv_ssl_ctx_;
|
||||||
info->cl_ssl_ctx = cl_ssl_ctx_;
|
info.cl_ssl_ctx = cl_ssl_ctx_;
|
||||||
try {
|
try {
|
||||||
auto thread = std::thread{start_threaded_worker, info};
|
auto thread = std::thread{start_threaded_worker, info};
|
||||||
thread.detach();
|
thread.detach();
|
||||||
|
@ -84,24 +94,26 @@ void ListenHandler::create_worker_thread(size_t num)
|
||||||
LLOG(ERROR, this) << "Could not start thread: code=" << error.code()
|
LLOG(ERROR, this) << "Could not start thread: code=" << error.code()
|
||||||
<< " msg=" << error.what();
|
<< " msg=" << error.what();
|
||||||
for(size_t j = 0; j < 2; ++j) {
|
for(size_t j = 0; j < 2; ++j) {
|
||||||
close(info->sv[j]);
|
close(info.sv[j]);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto bev = bufferevent_socket_new(evbase_, info->sv[0],
|
auto bev = bufferevent_socket_new(evbase_, info.sv[0],
|
||||||
BEV_OPT_DEFER_CALLBACKS);
|
BEV_OPT_DEFER_CALLBACKS);
|
||||||
if(!bev) {
|
if(!bev) {
|
||||||
LLOG(ERROR, this) << "bufferevent_socket_new() failed";
|
LLOG(ERROR, this) << "bufferevent_socket_new() failed";
|
||||||
for(size_t j = 0; j < 2; ++j) {
|
for(size_t j = 0; j < 2; ++j) {
|
||||||
close(info->sv[j]);
|
close(info.sv[j]);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
info->bev = bev;
|
info.bev = bev;
|
||||||
|
|
||||||
|
workers_.push_back(info);
|
||||||
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
LLOG(INFO, this) << "Created thread #" << num_worker_;
|
LLOG(INFO, this) << "Created thread #" << workers_.size() - 1;
|
||||||
}
|
}
|
||||||
++num_worker_;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +123,7 @@ int ListenHandler::accept_connection(evutil_socket_t fd,
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
LLOG(INFO, this) << "Accepted connection. fd=" << fd;
|
LLOG(INFO, this) << "Accepted connection. fd=" << fd;
|
||||||
}
|
}
|
||||||
if(num_worker_ == 0) {
|
if(get_config()->num_worker == 1) {
|
||||||
|
|
||||||
if(worker_stat_->num_connections >=
|
if(worker_stat_->num_connections >=
|
||||||
get_config()->worker_frontend_connections) {
|
get_config()->worker_frontend_connections) {
|
||||||
|
@ -138,10 +150,11 @@ int ListenHandler::accept_connection(evutil_socket_t fd,
|
||||||
client->set_http2_session(http2session_.get());
|
client->set_http2_session(http2session_.get());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
size_t idx = worker_round_robin_cnt_ % num_worker_;
|
size_t idx = worker_round_robin_cnt_ % workers_.size();
|
||||||
++worker_round_robin_cnt_;
|
++worker_round_robin_cnt_;
|
||||||
WorkerEvent wev;
|
WorkerEvent wev;
|
||||||
memset(&wev, 0, sizeof(wev));
|
memset(&wev, 0, sizeof(wev));
|
||||||
|
wev.type = NEW_CONNECTION;
|
||||||
wev.client_fd = fd;
|
wev.client_fd = fd;
|
||||||
memcpy(&wev.client_addr, addr, addrlen);
|
memcpy(&wev.client_addr, addr, addrlen);
|
||||||
wev.client_addrlen = addrlen;
|
wev.client_addrlen = addrlen;
|
||||||
|
|
|
@ -56,6 +56,7 @@ public:
|
||||||
~ListenHandler();
|
~ListenHandler();
|
||||||
int accept_connection(evutil_socket_t fd, sockaddr *addr, int addrlen);
|
int accept_connection(evutil_socket_t fd, sockaddr *addr, int addrlen);
|
||||||
void create_worker_thread(size_t num);
|
void create_worker_thread(size_t num);
|
||||||
|
void worker_reopen_log_files();
|
||||||
event_base* get_evbase() const;
|
event_base* get_evbase() const;
|
||||||
int create_http2_session();
|
int create_http2_session();
|
||||||
private:
|
private:
|
||||||
|
@ -70,7 +71,6 @@ private:
|
||||||
std::unique_ptr<Http2Session> http2session_;
|
std::unique_ptr<Http2Session> http2session_;
|
||||||
bufferevent_rate_limit_group *rate_limit_group_;
|
bufferevent_rate_limit_group *rate_limit_group_;
|
||||||
std::unique_ptr<WorkerStat> worker_stat_;
|
std::unique_ptr<WorkerStat> worker_stat_;
|
||||||
size_t num_worker_;
|
|
||||||
unsigned int worker_round_robin_cnt_;
|
unsigned int worker_round_robin_cnt_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
194
src/shrpx_log.cc
194
src/shrpx_log.cc
|
@ -25,11 +25,20 @@
|
||||||
#include "shrpx_log.h"
|
#include "shrpx_log.h"
|
||||||
|
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
|
#include "shrpx_downstream.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
using namespace nghttp2;
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
@ -48,6 +57,28 @@ const char *SEVERITY_COLOR[] = {
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::string get_datestr()
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
// Format data like this:
|
||||||
|
// 03/Jul/2014:00:19:38 +0900
|
||||||
|
char buf[64];
|
||||||
|
struct tm tms;
|
||||||
|
auto now = time(nullptr);
|
||||||
|
|
||||||
|
if(localtime_r(&now, &tms) == nullptr) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strftime(buf, sizeof(buf), "%d/%b/%Y:%T %z", &tms) == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
int Log::severity_thres_ = WARNING;
|
int Log::severity_thres_ = WARNING;
|
||||||
|
|
||||||
void Log::set_severity_level(int severity)
|
void Log::set_severity_level(int severity)
|
||||||
|
@ -90,26 +121,163 @@ Log::Log(int severity, const char *filename, int linenum)
|
||||||
|
|
||||||
Log::~Log()
|
Log::~Log()
|
||||||
{
|
{
|
||||||
if(!log_enabled(severity_)) {
|
int rv;
|
||||||
|
|
||||||
|
if(!log_enabled(severity_) ||
|
||||||
|
(worker_config.errorlog_fd == -1 && !get_config()->errorlog_syslog)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config()->use_syslog) {
|
if(get_config()->errorlog_syslog) {
|
||||||
syslog(severity_to_syslog_level(severity_), "%s (%s:%d)",
|
syslog(severity_to_syslog_level(severity_), "[%s] %s (%s:%d)",
|
||||||
stream_.str().c_str(), filename_, linenum_);
|
SEVERITY_STR[severity_], stream_.str().c_str(),
|
||||||
|
filename_, linenum_);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "[%s%s%s] %s\n %s(%s:%d)%s\n",
|
char buf[4096];
|
||||||
get_config()->tty ? SEVERITY_COLOR[severity_] : "",
|
auto tty = worker_config.errorlog_tty;
|
||||||
SEVERITY_STR[severity_],
|
|
||||||
get_config()->tty ? "\033[0m" : "",
|
rv = snprintf(buf, sizeof(buf),
|
||||||
stream_.str().c_str(),
|
"%s [%s%s%s] %s\n %s(%s:%d)%s\n",
|
||||||
get_config()->tty ? "\033[1;30m" : "",
|
get_datestr().c_str(),
|
||||||
filename_, linenum_,
|
tty ? SEVERITY_COLOR[severity_] : "",
|
||||||
get_config()->tty ? "\033[0m" : "");
|
SEVERITY_STR[severity_],
|
||||||
fflush(stderr);
|
tty ? "\033[0m" : "",
|
||||||
|
stream_.str().c_str(),
|
||||||
|
tty ? "\033[1;30m" : "",
|
||||||
|
filename_, linenum_,
|
||||||
|
tty ? "\033[0m" : "");
|
||||||
|
|
||||||
|
if(rv < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nwrite = std::min(static_cast<size_t>(rv), sizeof(buf) - 1);
|
||||||
|
|
||||||
|
write(worker_config.errorlog_fd, buf, nwrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void upstream_accesslog(const std::string& client_ip, unsigned int status_code,
|
||||||
|
Downstream *downstream)
|
||||||
|
{
|
||||||
|
if(worker_config.accesslog_fd == -1 && !get_config()->accesslog_syslog) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[1024];
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
const char *path;
|
||||||
|
const char *method;
|
||||||
|
unsigned int major, minor;
|
||||||
|
const char *user_agent;
|
||||||
|
int64_t response_bodylen;
|
||||||
|
|
||||||
|
if(!downstream) {
|
||||||
|
path = "-";
|
||||||
|
method = "-";
|
||||||
|
major = 1;
|
||||||
|
minor = 0;
|
||||||
|
user_agent = "-";
|
||||||
|
response_bodylen = 0;
|
||||||
|
} else {
|
||||||
|
if(downstream->get_request_path().empty()) {
|
||||||
|
path = downstream->get_request_http2_authority().c_str();
|
||||||
|
} else {
|
||||||
|
path = downstream->get_request_path().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
method = downstream->get_request_method().c_str();
|
||||||
|
major = downstream->get_request_major();
|
||||||
|
minor = downstream->get_request_minor();
|
||||||
|
user_agent = downstream->get_request_user_agent().c_str();
|
||||||
|
response_bodylen = downstream->get_response_bodylen();
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char fmt[] =
|
||||||
|
"%s - - [%s] \"%s %s HTTP/%u.%u\" %u %" PRId64 " \"-\" \"%s\"\n";
|
||||||
|
|
||||||
|
rv = snprintf(buf, sizeof(buf), fmt,
|
||||||
|
client_ip.c_str(),
|
||||||
|
get_datestr().c_str(),
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
status_code,
|
||||||
|
response_bodylen,
|
||||||
|
user_agent);
|
||||||
|
|
||||||
|
if(rv < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nwrite = std::min(static_cast<size_t>(rv), sizeof(buf) - 1);
|
||||||
|
|
||||||
|
if(get_config()->accesslog_syslog) {
|
||||||
|
syslog(LOG_INFO, "%s", buf);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
write(worker_config.accesslog_fd, buf, nwrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
int reopen_log_files()
|
||||||
|
{
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if(worker_config.accesslog_fd != -1) {
|
||||||
|
close(worker_config.accesslog_fd);
|
||||||
|
worker_config.accesslog_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!get_config()->accesslog_syslog && get_config()->accesslog_file) {
|
||||||
|
|
||||||
|
worker_config.accesslog_fd =
|
||||||
|
util::reopen_log_file(get_config()->accesslog_file.get());
|
||||||
|
|
||||||
|
if(worker_config.accesslog_fd == -1) {
|
||||||
|
LOG(ERROR) << "Failed to open accesslog file "
|
||||||
|
<< get_config()->accesslog_file.get();
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_errorlog_fd = -1;
|
||||||
|
|
||||||
|
if(!get_config()->errorlog_syslog && get_config()->errorlog_file) {
|
||||||
|
|
||||||
|
new_errorlog_fd = util::reopen_log_file(get_config()->errorlog_file.get());
|
||||||
|
|
||||||
|
if(new_errorlog_fd == -1) {
|
||||||
|
if(worker_config.errorlog_fd != -1) {
|
||||||
|
LOG(ERROR) << "Failed to open errorlog file "
|
||||||
|
<< get_config()->errorlog_file.get();
|
||||||
|
} else {
|
||||||
|
std::cerr << "Failed to open errorlog file "
|
||||||
|
<< get_config()->errorlog_file.get()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(worker_config.errorlog_fd != -1) {
|
||||||
|
close(worker_config.errorlog_fd);
|
||||||
|
worker_config.errorlog_fd = -1;
|
||||||
|
worker_config.errorlog_tty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_errorlog_fd != -1) {
|
||||||
|
worker_config.errorlog_fd = new_errorlog_fd;
|
||||||
|
worker_config.errorlog_tty = isatty(worker_config.errorlog_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
class Downstream;
|
||||||
|
|
||||||
#define ENABLE_LOG 1
|
#define ENABLE_LOG 1
|
||||||
|
|
||||||
#define LOG_ENABLED(SEVERITY) (ENABLE_LOG && Log::log_enabled(SEVERITY))
|
#define LOG_ENABLED(SEVERITY) (ENABLE_LOG && Log::log_enabled(SEVERITY))
|
||||||
|
@ -95,8 +97,13 @@ private:
|
||||||
static int severity_thres_;
|
static int severity_thres_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TTY_HTTP_HD (get_config()->tty ? "\033[1;34m" : "")
|
#define TTY_HTTP_HD (worker_config.errorlog_tty ? "\033[1;34m" : "")
|
||||||
#define TTY_RST (get_config()->tty ? "\033[0m" : "")
|
#define TTY_RST (worker_config.errorlog_tty ? "\033[0m" : "")
|
||||||
|
|
||||||
|
void upstream_accesslog(const std::string& client_ip, unsigned int status_code,
|
||||||
|
Downstream *downstream);
|
||||||
|
|
||||||
|
int reopen_log_files();
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include "shrpx_downstream_connection.h"
|
#include "shrpx_downstream_connection.h"
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_http.h"
|
#include "shrpx_http.h"
|
||||||
#include "shrpx_accesslog.h"
|
#include "shrpx_worker_config.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -164,7 +164,9 @@ void on_ctrl_recv_callback
|
||||||
const char *scheme = nullptr;
|
const char *scheme = nullptr;
|
||||||
const char *host = nullptr;
|
const char *host = nullptr;
|
||||||
const char *method = nullptr;
|
const char *method = nullptr;
|
||||||
const char *content_length = 0;
|
const char *content_length = nullptr;
|
||||||
|
const char *user_agent = nullptr;
|
||||||
|
|
||||||
for(size_t i = 0; nv[i]; i += 2) {
|
for(size_t i = 0; nv[i]; i += 2) {
|
||||||
if(strcmp(nv[i], ":path") == 0) {
|
if(strcmp(nv[i], ":path") == 0) {
|
||||||
path = nv[i+1];
|
path = nv[i+1];
|
||||||
|
@ -177,6 +179,8 @@ void on_ctrl_recv_callback
|
||||||
} else if(nv[i][0] != ':') {
|
} else if(nv[i][0] != ':') {
|
||||||
if(strcmp(nv[i], "content-length") == 0) {
|
if(strcmp(nv[i], "content-length") == 0) {
|
||||||
content_length = nv[i+1];
|
content_length = nv[i+1];
|
||||||
|
} else if(strcmp(nv[i], "user-agent") == 0) {
|
||||||
|
user_agent = nv[i+1];
|
||||||
}
|
}
|
||||||
downstream->add_request_header(nv[i], nv[i+1]);
|
downstream->add_request_header(nv[i], nv[i+1]);
|
||||||
}
|
}
|
||||||
|
@ -204,6 +208,10 @@ void on_ctrl_recv_callback
|
||||||
downstream->set_request_path(path);
|
downstream->set_request_path(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(user_agent) {
|
||||||
|
downstream->set_request_user_agent(user_agent);
|
||||||
|
}
|
||||||
|
|
||||||
if(!(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN)) {
|
if(!(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN)) {
|
||||||
downstream->set_request_http2_expect_body(true);
|
downstream->set_request_http2_expect_body(true);
|
||||||
}
|
}
|
||||||
|
@ -773,6 +781,9 @@ ssize_t spdy_data_read_callback(spdylay_session *session,
|
||||||
downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
downstream->get_response_state() == Downstream::MSG_COMPLETE) {
|
||||||
if(!downstream->get_upgraded()) {
|
if(!downstream->get_upgraded()) {
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
|
|
||||||
|
upstream_accesslog(upstream->get_client_handler()->get_ipaddr(),
|
||||||
|
downstream->get_response_http_status(), downstream);
|
||||||
} else {
|
} else {
|
||||||
// For tunneling, issue RST_STREAM to finish the stream.
|
// For tunneling, issue RST_STREAM to finish the stream.
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
|
@ -800,6 +811,7 @@ int SpdyUpstream::error_reply(Downstream *downstream, unsigned int status_code)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
auto html = http::create_error_html(status_code);
|
auto html = http::create_error_html(status_code);
|
||||||
|
downstream->set_response_http_status(status_code);
|
||||||
downstream->init_response_body_buf();
|
downstream->init_response_body_buf();
|
||||||
auto body = downstream->get_response_body_buf();
|
auto body = downstream->get_response_body_buf();
|
||||||
rv = evbuffer_add(body, html.c_str(), html.size());
|
rv = evbuffer_add(body, html.c_str(), html.size());
|
||||||
|
@ -831,10 +843,7 @@ int SpdyUpstream::error_reply(Downstream *downstream, unsigned int status_code)
|
||||||
<< spdylay_strerror(rv);
|
<< spdylay_strerror(rv);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(get_client_handler()->get_ipaddr(),
|
|
||||||
status_code, downstream);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,10 +958,10 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
ULOG(FATAL, this) << "spdylay_submit_response() failed";
|
ULOG(FATAL, this) << "spdylay_submit_response() failed";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_response(get_client_handler()->get_ipaddr(),
|
if(downstream->get_upgraded()) {
|
||||||
downstream->get_response_http_status(),
|
upstream_accesslog(get_client_handler()->get_ipaddr(),
|
||||||
downstream);
|
downstream->get_response_http_status(), downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream->clear_response_headers();
|
downstream->clear_response_headers();
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
#include "shrpx_log.h"
|
#include "shrpx_log.h"
|
||||||
#include "shrpx_client_handler.h"
|
#include "shrpx_client_handler.h"
|
||||||
#include "shrpx_config.h"
|
#include "shrpx_config.h"
|
||||||
#include "shrpx_accesslog.h"
|
|
||||||
#include "shrpx_worker.h"
|
#include "shrpx_worker.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ssl.h"
|
#include "ssl.h"
|
||||||
|
@ -476,10 +475,6 @@ ClientHandler* accept_connection
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(get_config()->accesslog) {
|
|
||||||
upstream_connect(host);
|
|
||||||
}
|
|
||||||
|
|
||||||
int val = 1;
|
int val = 1;
|
||||||
rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
|
rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
|
||||||
reinterpret_cast<char *>(&val), sizeof(val));
|
reinterpret_cast<char *>(&val), sizeof(val));
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "shrpx_client_handler.h"
|
#include "shrpx_client_handler.h"
|
||||||
#include "shrpx_http2_session.h"
|
#include "shrpx_http2_session.h"
|
||||||
#include "shrpx_worker.h"
|
#include "shrpx_worker.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
@ -68,6 +69,18 @@ void ThreadEventReceiver::on_read(bufferevent *bev)
|
||||||
<< sizeof(wev) << " Actual:" << nread;
|
<< sizeof(wev) << " Actual:" << nread;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(wev.type == REOPEN_LOG) {
|
||||||
|
if(LOG_ENABLED(INFO)) {
|
||||||
|
LOG(INFO) << "Reopening log files: worker_info("
|
||||||
|
<< &worker_config << ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
reopen_log_files();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
TLOG(INFO, this) << "WorkerEvent: client_fd=" << wev.client_fd
|
TLOG(INFO, this) << "WorkerEvent: client_fd=" << wev.client_fd
|
||||||
<< ", addrlen=" << wev.client_addrlen;
|
<< ", addrlen=" << wev.client_addrlen;
|
||||||
|
|
|
@ -40,10 +40,20 @@ namespace shrpx {
|
||||||
class Http2Session;
|
class Http2Session;
|
||||||
struct WorkerStat;
|
struct WorkerStat;
|
||||||
|
|
||||||
|
enum WorkerEventType {
|
||||||
|
NEW_CONNECTION = 0x01,
|
||||||
|
REOPEN_LOG = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
struct WorkerEvent {
|
struct WorkerEvent {
|
||||||
sockaddr_union client_addr;
|
WorkerEventType type;
|
||||||
size_t client_addrlen;
|
union {
|
||||||
evutil_socket_t client_fd;
|
struct {
|
||||||
|
sockaddr_union client_addr;
|
||||||
|
size_t client_addrlen;
|
||||||
|
evutil_socket_t client_fd;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadEventReceiver {
|
class ThreadEventReceiver {
|
||||||
|
|
|
@ -36,16 +36,17 @@
|
||||||
#include "shrpx_thread_event_receiver.h"
|
#include "shrpx_thread_event_receiver.h"
|
||||||
#include "shrpx_log.h"
|
#include "shrpx_log.h"
|
||||||
#include "shrpx_http2_session.h"
|
#include "shrpx_http2_session.h"
|
||||||
|
#include "shrpx_worker_config.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
Worker::Worker(WorkerInfo *info)
|
Worker::Worker(const WorkerInfo& info)
|
||||||
: sv_ssl_ctx_(info->sv_ssl_ctx),
|
: sv_ssl_ctx_(info.sv_ssl_ctx),
|
||||||
cl_ssl_ctx_(info->cl_ssl_ctx),
|
cl_ssl_ctx_(info.cl_ssl_ctx),
|
||||||
fd_(info->sv[1])
|
fd_(info.sv[1])
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Worker::~Worker()
|
Worker::~Worker()
|
||||||
|
@ -76,6 +77,8 @@ void eventcb(bufferevent *bev, short events, void *arg)
|
||||||
|
|
||||||
void Worker::run()
|
void Worker::run()
|
||||||
{
|
{
|
||||||
|
(void)reopen_log_files();
|
||||||
|
|
||||||
auto evbase = std::unique_ptr<event_base, decltype(&event_base_free)>
|
auto evbase = std::unique_ptr<event_base, decltype(&event_base_free)>
|
||||||
(event_base_new(), event_base_free);
|
(event_base_new(), event_base_free);
|
||||||
if(!evbase) {
|
if(!evbase) {
|
||||||
|
@ -105,7 +108,7 @@ void Worker::run()
|
||||||
event_base_loop(evbase.get(), 0);
|
event_base_loop(evbase.get(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_threaded_worker(WorkerInfo *info)
|
void start_threaded_worker(WorkerInfo info)
|
||||||
{
|
{
|
||||||
Worker worker(info);
|
Worker worker(info);
|
||||||
worker.run();
|
worker.run();
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct WorkerStat {
|
||||||
|
|
||||||
class Worker {
|
class Worker {
|
||||||
public:
|
public:
|
||||||
Worker(WorkerInfo *info);
|
Worker(const WorkerInfo& info);
|
||||||
~Worker();
|
~Worker();
|
||||||
void run();
|
void run();
|
||||||
private:
|
private:
|
||||||
|
@ -52,7 +52,7 @@ private:
|
||||||
int fd_;
|
int fd_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void start_threaded_worker(WorkerInfo *info);
|
void start_threaded_worker(WorkerInfo info);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* nghttp2 - HTTP/2 C Library
|
* nghttp2 - HTTP/2 C Library
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 Tatsuhiro Tsujikawa
|
* Copyright (c) 2014 Tatsuhiro Tsujikawa
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
* a copy of this software and associated documentation files (the
|
* a copy of this software and associated documentation files (the
|
||||||
|
@ -22,21 +22,17 @@
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifndef SHRPX_ACCESSLOG_H
|
#include "shrpx_worker_config.h"
|
||||||
#define SHRPX_ACCESSLOG_H
|
|
||||||
|
|
||||||
#include "shrpx.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
class Downstream;
|
WorkerConfig::WorkerConfig()
|
||||||
|
: accesslog_fd(-1),
|
||||||
|
errorlog_fd(-1),
|
||||||
|
errorlog_tty(false)
|
||||||
|
{}
|
||||||
|
|
||||||
void upstream_connect(const std::string& client_ip);
|
thread_local WorkerConfig worker_config;
|
||||||
void upstream_response(const std::string& client_ip, unsigned int status_code,
|
|
||||||
Downstream *downstream);
|
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
#endif // SHRPX_LOG_H
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* nghttp2 - HTTP/2 C Library
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Tatsuhiro Tsujikawa
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
* a copy of this software and associated documentation files (the
|
||||||
|
* "Software"), to deal in the Software without restriction, including
|
||||||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
* the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be
|
||||||
|
* included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef SHRPX_WORKER_CONFIG_H
|
||||||
|
#define SHRPX_WORKER_CONFIG_H
|
||||||
|
|
||||||
|
#include "shrpx.h"
|
||||||
|
|
||||||
|
namespace shrpx {
|
||||||
|
|
||||||
|
struct WorkerConfig {
|
||||||
|
int accesslog_fd;
|
||||||
|
int errorlog_fd;
|
||||||
|
// true if errorlog_fd is referring to a terminal.
|
||||||
|
bool errorlog_tty;
|
||||||
|
|
||||||
|
WorkerConfig();
|
||||||
|
};
|
||||||
|
|
||||||
|
// We need WorkerConfig per thread
|
||||||
|
extern thread_local WorkerConfig worker_config;
|
||||||
|
|
||||||
|
} // namespace shrpx
|
||||||
|
|
||||||
|
#endif // SHRPX_WORKER_CONFIG_H
|
14
src/util.cc
14
src/util.cc
|
@ -28,6 +28,8 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -585,6 +587,18 @@ bool numeric_host(const char *hostname)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int reopen_log_file(const char *path)
|
||||||
|
{
|
||||||
|
auto fd = open(path, O_WRONLY | O_APPEND | O_CREAT,
|
||||||
|
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||||
|
|
||||||
|
if(fd == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -478,6 +478,11 @@ private:
|
||||||
|
|
||||||
bool numeric_host(const char *hostname);
|
bool numeric_host(const char *hostname);
|
||||||
|
|
||||||
|
// Opens |path| with O_APPEND enabled. If file does not exist, it is
|
||||||
|
// created first. This function returns file descriptor referring the
|
||||||
|
// opened file if it succeeds, or -1.
|
||||||
|
int reopen_log_file(const char *path);
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
Loading…
Reference in New Issue