nghttpx: Add custom error pages
This commit is contained in:
parent
db1ee3aa88
commit
d7051f5207
|
@ -127,7 +127,8 @@ OPTIONS = [
|
||||||
"backend-http2-max-concurrent-streams",
|
"backend-http2-max-concurrent-streams",
|
||||||
"backend-connections-per-frontend",
|
"backend-connections-per-frontend",
|
||||||
"backend-tls",
|
"backend-tls",
|
||||||
"backend-connections-per-host"
|
"backend-connections-per-host",
|
||||||
|
"error-page",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
|
@ -1899,11 +1899,15 @@ void acceptcb(struct ev_loop *loop, ev_io *w, int revents) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
FileEntry make_status_body(int status, uint16_t port) {
|
FileEntry make_status_body(int status, uint16_t port) {
|
||||||
|
BlockAllocator balloc(1024, 1024);
|
||||||
|
|
||||||
|
auto status_string = http2::get_status_string(balloc, status);
|
||||||
|
|
||||||
std::string body;
|
std::string body;
|
||||||
body = "<html><head><title>";
|
body = "<html><head><title>";
|
||||||
body += http2::get_status_string(status);
|
body += status_string;
|
||||||
body += "</title></head><body><h1>";
|
body += "</title></head><body><h1>";
|
||||||
body += http2::get_status_string(status);
|
body += status_string;
|
||||||
body += "</h1><hr><address>";
|
body += "</h1><hr><address>";
|
||||||
body += NGHTTPD_SERVER;
|
body += NGHTTPD_SERVER;
|
||||||
body += " at port ";
|
body += " at port ";
|
||||||
|
|
|
@ -33,9 +33,10 @@ namespace server {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
std::string create_html(int status_code) {
|
std::string create_html(int status_code) {
|
||||||
|
BlockAllocator balloc(1024, 1024);
|
||||||
std::string res;
|
std::string res;
|
||||||
res.reserve(512);
|
res.reserve(512);
|
||||||
auto status = ::nghttp2::http2::get_status_string(status_code);
|
auto status = ::nghttp2::http2::get_status_string(balloc, status_code);
|
||||||
res += R"(<!DOCTYPE html><html lang="en"><title>)";
|
res += R"(<!DOCTYPE html><html lang="en"><title>)";
|
||||||
res += status;
|
res += status;
|
||||||
res += "</title><body><h1>";
|
res += "</title><body><h1>";
|
||||||
|
|
106
src/http2.cc
106
src/http2.cc
|
@ -30,111 +30,111 @@ namespace nghttp2 {
|
||||||
|
|
||||||
namespace http2 {
|
namespace http2 {
|
||||||
|
|
||||||
std::string get_status_string(unsigned int status_code) {
|
StringRef get_status_string(BlockAllocator &balloc, unsigned int status_code) {
|
||||||
switch (status_code) {
|
switch (status_code) {
|
||||||
case 100:
|
case 100:
|
||||||
return "100 Continue";
|
return StringRef::from_lit("100 Continue");
|
||||||
case 101:
|
case 101:
|
||||||
return "101 Switching Protocols";
|
return StringRef::from_lit("101 Switching Protocols");
|
||||||
case 200:
|
case 200:
|
||||||
return "200 OK";
|
return StringRef::from_lit("200 OK");
|
||||||
case 201:
|
case 201:
|
||||||
return "201 Created";
|
return StringRef::from_lit("201 Created");
|
||||||
case 202:
|
case 202:
|
||||||
return "202 Accepted";
|
return StringRef::from_lit("202 Accepted");
|
||||||
case 203:
|
case 203:
|
||||||
return "203 Non-Authoritative Information";
|
return StringRef::from_lit("203 Non-Authoritative Information");
|
||||||
case 204:
|
case 204:
|
||||||
return "204 No Content";
|
return StringRef::from_lit("204 No Content");
|
||||||
case 205:
|
case 205:
|
||||||
return "205 Reset Content";
|
return StringRef::from_lit("205 Reset Content");
|
||||||
case 206:
|
case 206:
|
||||||
return "206 Partial Content";
|
return StringRef::from_lit("206 Partial Content");
|
||||||
case 300:
|
case 300:
|
||||||
return "300 Multiple Choices";
|
return StringRef::from_lit("300 Multiple Choices");
|
||||||
case 301:
|
case 301:
|
||||||
return "301 Moved Permanently";
|
return StringRef::from_lit("301 Moved Permanently");
|
||||||
case 302:
|
case 302:
|
||||||
return "302 Found";
|
return StringRef::from_lit("302 Found");
|
||||||
case 303:
|
case 303:
|
||||||
return "303 See Other";
|
return StringRef::from_lit("303 See Other");
|
||||||
case 304:
|
case 304:
|
||||||
return "304 Not Modified";
|
return StringRef::from_lit("304 Not Modified");
|
||||||
case 305:
|
case 305:
|
||||||
return "305 Use Proxy";
|
return StringRef::from_lit("305 Use Proxy");
|
||||||
// case 306: return "306 (Unused)";
|
// case 306: return StringRef::from_lit("306 (Unused)");
|
||||||
case 307:
|
case 307:
|
||||||
return "307 Temporary Redirect";
|
return StringRef::from_lit("307 Temporary Redirect");
|
||||||
case 308:
|
case 308:
|
||||||
return "308 Permanent Redirect";
|
return StringRef::from_lit("308 Permanent Redirect");
|
||||||
case 400:
|
case 400:
|
||||||
return "400 Bad Request";
|
return StringRef::from_lit("400 Bad Request");
|
||||||
case 401:
|
case 401:
|
||||||
return "401 Unauthorized";
|
return StringRef::from_lit("401 Unauthorized");
|
||||||
case 402:
|
case 402:
|
||||||
return "402 Payment Required";
|
return StringRef::from_lit("402 Payment Required");
|
||||||
case 403:
|
case 403:
|
||||||
return "403 Forbidden";
|
return StringRef::from_lit("403 Forbidden");
|
||||||
case 404:
|
case 404:
|
||||||
return "404 Not Found";
|
return StringRef::from_lit("404 Not Found");
|
||||||
case 405:
|
case 405:
|
||||||
return "405 Method Not Allowed";
|
return StringRef::from_lit("405 Method Not Allowed");
|
||||||
case 406:
|
case 406:
|
||||||
return "406 Not Acceptable";
|
return StringRef::from_lit("406 Not Acceptable");
|
||||||
case 407:
|
case 407:
|
||||||
return "407 Proxy Authentication Required";
|
return StringRef::from_lit("407 Proxy Authentication Required");
|
||||||
case 408:
|
case 408:
|
||||||
return "408 Request Timeout";
|
return StringRef::from_lit("408 Request Timeout");
|
||||||
case 409:
|
case 409:
|
||||||
return "409 Conflict";
|
return StringRef::from_lit("409 Conflict");
|
||||||
case 410:
|
case 410:
|
||||||
return "410 Gone";
|
return StringRef::from_lit("410 Gone");
|
||||||
case 411:
|
case 411:
|
||||||
return "411 Length Required";
|
return StringRef::from_lit("411 Length Required");
|
||||||
case 412:
|
case 412:
|
||||||
return "412 Precondition Failed";
|
return StringRef::from_lit("412 Precondition Failed");
|
||||||
case 413:
|
case 413:
|
||||||
return "413 Payload Too Large";
|
return StringRef::from_lit("413 Payload Too Large");
|
||||||
case 414:
|
case 414:
|
||||||
return "414 URI Too Long";
|
return StringRef::from_lit("414 URI Too Long");
|
||||||
case 415:
|
case 415:
|
||||||
return "415 Unsupported Media Type";
|
return StringRef::from_lit("415 Unsupported Media Type");
|
||||||
case 416:
|
case 416:
|
||||||
return "416 Requested Range Not Satisfiable";
|
return StringRef::from_lit("416 Requested Range Not Satisfiable");
|
||||||
case 417:
|
case 417:
|
||||||
return "417 Expectation Failed";
|
return StringRef::from_lit("417 Expectation Failed");
|
||||||
case 421:
|
case 421:
|
||||||
return "421 Misdirected Request";
|
return StringRef::from_lit("421 Misdirected Request");
|
||||||
case 426:
|
case 426:
|
||||||
return "426 Upgrade Required";
|
return StringRef::from_lit("426 Upgrade Required");
|
||||||
case 428:
|
case 428:
|
||||||
return "428 Precondition Required";
|
return StringRef::from_lit("428 Precondition Required");
|
||||||
case 429:
|
case 429:
|
||||||
return "429 Too Many Requests";
|
return StringRef::from_lit("429 Too Many Requests");
|
||||||
case 431:
|
case 431:
|
||||||
return "431 Request Header Fields Too Large";
|
return StringRef::from_lit("431 Request Header Fields Too Large");
|
||||||
case 451:
|
case 451:
|
||||||
return "451 Unavailable For Legal Reasons";
|
return StringRef::from_lit("451 Unavailable For Legal Reasons");
|
||||||
case 500:
|
case 500:
|
||||||
return "500 Internal Server Error";
|
return StringRef::from_lit("500 Internal Server Error");
|
||||||
case 501:
|
case 501:
|
||||||
return "501 Not Implemented";
|
return StringRef::from_lit("501 Not Implemented");
|
||||||
case 502:
|
case 502:
|
||||||
return "502 Bad Gateway";
|
return StringRef::from_lit("502 Bad Gateway");
|
||||||
case 503:
|
case 503:
|
||||||
return "503 Service Unavailable";
|
return StringRef::from_lit("503 Service Unavailable");
|
||||||
case 504:
|
case 504:
|
||||||
return "504 Gateway Timeout";
|
return StringRef::from_lit("504 Gateway Timeout");
|
||||||
case 505:
|
case 505:
|
||||||
return "505 HTTP Version Not Supported";
|
return StringRef::from_lit("505 HTTP Version Not Supported");
|
||||||
case 511:
|
case 511:
|
||||||
return "511 Network Authentication Required";
|
return StringRef::from_lit("511 Network Authentication Required");
|
||||||
default:
|
default:
|
||||||
return util::utos(status_code);
|
return util::make_string_ref_uint(balloc, status_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef stringify_status(unsigned int status_code) {
|
StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code) {
|
||||||
switch (status_code) {
|
switch (status_code) {
|
||||||
case 100:
|
case 100:
|
||||||
return StringRef::from_lit("100");
|
return StringRef::from_lit("100");
|
||||||
|
@ -234,7 +234,7 @@ StringRef stringify_status(unsigned int status_code) {
|
||||||
case 511:
|
case 511:
|
||||||
return StringRef::from_lit("511");
|
return StringRef::from_lit("511");
|
||||||
default:
|
default:
|
||||||
return StringRef{};
|
return util::make_string_ref_uint(balloc, status_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,11 +94,12 @@ using HeaderRefs = std::vector<HeaderRef>;
|
||||||
|
|
||||||
namespace http2 {
|
namespace http2 {
|
||||||
|
|
||||||
std::string get_status_string(unsigned int status_code);
|
// Returns string version of |status code| followed by reason
|
||||||
|
// string. (e.g., "404 Not Found").
|
||||||
|
StringRef get_status_string(BlockAllocator &balloc, unsigned int status_code);
|
||||||
|
|
||||||
// Returns string version of |status_code|. This function can handle
|
// Returns string version of |status_code|. (e.g., "404")
|
||||||
// only predefined status code. Otherwise, returns nullptr.
|
StringRef stringify_status(BlockAllocator &balloc, unsigned int status_code);
|
||||||
StringRef stringify_status(unsigned int status_code);
|
|
||||||
|
|
||||||
void capitalize(DefaultMemchunks *buf, const StringRef &s);
|
void capitalize(DefaultMemchunks *buf, const StringRef &s);
|
||||||
|
|
||||||
|
|
11
src/shrpx.cc
11
src/shrpx.cc
|
@ -1843,6 +1843,12 @@ HTTP:
|
||||||
towards this number.
|
towards this number.
|
||||||
Default: )" << get_config()->http.max_response_header_fields
|
Default: )" << get_config()->http.max_response_header_fields
|
||||||
<< R"(
|
<< R"(
|
||||||
|
--error-page=<CODE>=<PATH>
|
||||||
|
Set file path to custom error page served when nghttpx
|
||||||
|
originally generates HTTP error status code <CODE>.
|
||||||
|
<CODE> must be greater than or equal to 400, and at most
|
||||||
|
599. If error status code comes from backend server,
|
||||||
|
the custom error pages are not used.
|
||||||
|
|
||||||
Debug:
|
Debug:
|
||||||
--frontend-http2-dump-request-header=<PATH>
|
--frontend-http2-dump-request-header=<PATH>
|
||||||
|
@ -2464,6 +2470,7 @@ int main(int argc, char **argv) {
|
||||||
119},
|
119},
|
||||||
{SHRPX_OPT_BACKEND_TLS, no_argument, &flag, 120},
|
{SHRPX_OPT_BACKEND_TLS, no_argument, &flag, 120},
|
||||||
{SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST, required_argument, &flag, 121},
|
{SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST, required_argument, &flag, 121},
|
||||||
|
{SHRPX_OPT_ERROR_PAGE, required_argument, &flag, 122},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -2982,6 +2989,10 @@ int main(int argc, char **argv) {
|
||||||
// --backend-connections-per-host
|
// --backend-connections-per-host
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST, optarg);
|
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 122:
|
||||||
|
// --error-page
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_ERROR_PAGE, optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -704,6 +704,57 @@ int parse_forwarded_node_type(const std::string &optarg) {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int parse_error_page(std::vector<ErrorPage> &error_pages, const char *opt,
|
||||||
|
const char *optarg) {
|
||||||
|
auto arg = StringRef{optarg};
|
||||||
|
auto eq = std::find(std::begin(arg), std::end(arg), '=');
|
||||||
|
if (eq == std::end(arg) || eq + 1 == std::end(arg)) {
|
||||||
|
LOG(ERROR) << opt << ": bad value: '" << arg << "'";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto codestr = StringRef{std::begin(arg), eq};
|
||||||
|
auto code = util::parse_uint(codestr);
|
||||||
|
|
||||||
|
if (code == -1 || code < 400 || code > 599) {
|
||||||
|
LOG(ERROR) << opt << ": bad code: '" << codestr << "'";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto path = StringRef{eq + 1, std::end(arg)};
|
||||||
|
|
||||||
|
std::vector<uint8_t> content;
|
||||||
|
auto fd = open(path.c_str(), O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fd_closer = defer(close, fd);
|
||||||
|
|
||||||
|
std::array<uint8_t, 4096> buf;
|
||||||
|
for (;;) {
|
||||||
|
auto n = read(fd, buf.data(), buf.size());
|
||||||
|
if (n == -1) {
|
||||||
|
auto error = errno;
|
||||||
|
LOG(ERROR) << opt << ": " << optarg << ": " << strerror(error);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
content.insert(std::end(content), std::begin(buf), std::begin(buf) + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_pages.push_back(
|
||||||
|
ErrorPage{std::move(content), static_cast<unsigned int>(code)});
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// generated by gennghttpxfun.py
|
// generated by gennghttpxfun.py
|
||||||
enum {
|
enum {
|
||||||
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL,
|
SHRPX_OPTID_ACCEPT_PROXY_PROTOCOL,
|
||||||
|
@ -748,6 +799,7 @@ enum {
|
||||||
SHRPX_OPTID_CONF,
|
SHRPX_OPTID_CONF,
|
||||||
SHRPX_OPTID_DAEMON,
|
SHRPX_OPTID_DAEMON,
|
||||||
SHRPX_OPTID_DH_PARAM_FILE,
|
SHRPX_OPTID_DH_PARAM_FILE,
|
||||||
|
SHRPX_OPTID_ERROR_PAGE,
|
||||||
SHRPX_OPTID_ERRORLOG_FILE,
|
SHRPX_OPTID_ERRORLOG_FILE,
|
||||||
SHRPX_OPTID_ERRORLOG_SYSLOG,
|
SHRPX_OPTID_ERRORLOG_SYSLOG,
|
||||||
SHRPX_OPTID_FASTOPEN,
|
SHRPX_OPTID_FASTOPEN,
|
||||||
|
@ -963,6 +1015,9 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
case 10:
|
case 10:
|
||||||
switch (name[9]) {
|
switch (name[9]) {
|
||||||
case 'e':
|
case 'e':
|
||||||
|
if (util::strieq_l("error-pag", name, 9)) {
|
||||||
|
return SHRPX_OPTID_ERROR_PAGE;
|
||||||
|
}
|
||||||
if (util::strieq_l("mruby-fil", name, 9)) {
|
if (util::strieq_l("mruby-fil", name, 9)) {
|
||||||
return SHRPX_OPTID_MRUBY_FILE;
|
return SHRPX_OPTID_MRUBY_FILE;
|
||||||
}
|
}
|
||||||
|
@ -2437,6 +2492,8 @@ int parse_config(const char *opt, const char *optarg,
|
||||||
case SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS:
|
case SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS:
|
||||||
return parse_uint(&mod_config()->http2.downstream.max_concurrent_streams,
|
return parse_uint(&mod_config()->http2.downstream.max_concurrent_streams,
|
||||||
opt, optarg);
|
opt, optarg);
|
||||||
|
case SHRPX_OPTID_ERROR_PAGE:
|
||||||
|
return parse_error_page(mod_config()->http.error_pages, opt, optarg);
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,7 @@ constexpr char SHRPX_OPT_BACKEND_CONNECTIONS_PER_FRONTEND[] =
|
||||||
constexpr char SHRPX_OPT_BACKEND_TLS[] = "backend-tls";
|
constexpr char SHRPX_OPT_BACKEND_TLS[] = "backend-tls";
|
||||||
constexpr char SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST[] =
|
constexpr char SHRPX_OPT_BACKEND_CONNECTIONS_PER_HOST[] =
|
||||||
"backend-connections-per-host";
|
"backend-connections-per-host";
|
||||||
|
constexpr char SHRPX_OPT_ERROR_PAGE[] = "error-page";
|
||||||
|
|
||||||
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
||||||
|
|
||||||
|
@ -438,6 +439,13 @@ struct TLSConfig {
|
||||||
bool no_http2_cipher_black_list;
|
bool no_http2_cipher_black_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// custom error page
|
||||||
|
struct ErrorPage {
|
||||||
|
// not NULL-terminated
|
||||||
|
std::vector<uint8_t> content;
|
||||||
|
unsigned int http_status;
|
||||||
|
};
|
||||||
|
|
||||||
struct HttpConfig {
|
struct HttpConfig {
|
||||||
struct {
|
struct {
|
||||||
// obfuscated value used in "by" parameter of Forwarded header
|
// obfuscated value used in "by" parameter of Forwarded header
|
||||||
|
@ -459,6 +467,7 @@ struct HttpConfig {
|
||||||
bool strip_incoming;
|
bool strip_incoming;
|
||||||
} xff;
|
} xff;
|
||||||
std::vector<AltSvc> altsvcs;
|
std::vector<AltSvc> altsvcs;
|
||||||
|
std::vector<ErrorPage> error_pages;
|
||||||
Headers add_request_headers;
|
Headers add_request_headers;
|
||||||
Headers add_response_headers;
|
Headers add_response_headers;
|
||||||
StringRef server_name;
|
StringRef server_name;
|
||||||
|
|
|
@ -35,19 +35,33 @@ namespace shrpx {
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
std::string create_error_html(unsigned int status_code) {
|
StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) {
|
||||||
std::string res;
|
auto &httpconf = get_config()->http;
|
||||||
res.reserve(512);
|
|
||||||
auto status = http2::get_status_string(status_code);
|
const auto &error_pages = httpconf.error_pages;
|
||||||
res += R"(<!DOCTYPE html><html lang="en"><title>)";
|
for (const auto &page : error_pages) {
|
||||||
res += status;
|
if (page.http_status == http_status) {
|
||||||
res += "</title><body><h1>";
|
return StringRef{std::begin(page.content), std::end(page.content)};
|
||||||
res += status;
|
}
|
||||||
res += "</h1><footer>";
|
}
|
||||||
const auto &server_name = get_config()->http.server_name;
|
|
||||||
res.append(server_name.c_str(), server_name.size());
|
auto status_string = http2::get_status_string(balloc, http_status);
|
||||||
res += "</footer></body></html>";
|
const auto &server_name = httpconf.server_name;
|
||||||
return res;
|
|
||||||
|
size_t len = 256 + server_name.size() + status_string.size() * 2;
|
||||||
|
|
||||||
|
auto iov = make_byte_ref(balloc, len + 1);
|
||||||
|
auto p = iov.base;
|
||||||
|
|
||||||
|
p = util::copy_lit(p, R"(<!DOCTYPE html><html lang="en"><title>)");
|
||||||
|
p = std::copy(std::begin(status_string), std::end(status_string), p);
|
||||||
|
p = util::copy_lit(p, "</title><body><h1>");
|
||||||
|
p = std::copy(std::begin(status_string), std::end(status_string), p);
|
||||||
|
p = util::copy_lit(p, "</h1><footer>");
|
||||||
|
p = std::copy(std::begin(server_name), std::end(server_name), p);
|
||||||
|
p = util::copy_lit(p, "</footer></body></html>");
|
||||||
|
*p = '\0';
|
||||||
|
return StringRef{iov.base, p};
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef create_forwarded(BlockAllocator &balloc, int params,
|
StringRef create_forwarded(BlockAllocator &balloc, int params,
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace shrpx {
|
||||||
|
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
std::string create_error_html(unsigned int status_code);
|
StringRef create_error_html(BlockAllocator &balloc, unsigned int status_code);
|
||||||
|
|
||||||
template <typename OutputIt>
|
template <typename OutputIt>
|
||||||
OutputIt create_via_header_value(OutputIt dst, int major, int minor) {
|
OutputIt create_via_header_value(OutputIt dst, int major, int minor) {
|
||||||
|
|
|
@ -1241,10 +1241,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
// 2 for :status and server
|
// 2 for :status and server
|
||||||
nva.reserve(2 + headers.size() + httpconf.add_response_headers.size());
|
nva.reserve(2 + headers.size() + httpconf.add_response_headers.size());
|
||||||
|
|
||||||
auto response_status = http2::stringify_status(resp.http_status);
|
auto response_status = http2::stringify_status(balloc, resp.http_status);
|
||||||
if (response_status.empty()) {
|
|
||||||
response_status = util::make_string_ref_uint(balloc, resp.http_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
||||||
|
|
||||||
|
@ -1297,7 +1294,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
|
||||||
|
|
||||||
auto &balloc = downstream->get_block_allocator();
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
auto html = http::create_error_html(status_code);
|
auto html = http::create_error_html(balloc, status_code);
|
||||||
resp.http_status = status_code;
|
resp.http_status = status_code;
|
||||||
auto body = downstream->get_response_buf();
|
auto body = downstream->get_response_buf();
|
||||||
body->append(html);
|
body->append(html);
|
||||||
|
@ -1310,11 +1307,7 @@ int Http2Upstream::error_reply(Downstream *downstream,
|
||||||
auto lgconf = log_config();
|
auto lgconf = log_config();
|
||||||
lgconf->update_tstamp(std::chrono::system_clock::now());
|
lgconf->update_tstamp(std::chrono::system_clock::now());
|
||||||
|
|
||||||
auto response_status = http2::stringify_status(status_code);
|
auto response_status = http2::stringify_status(balloc, status_code);
|
||||||
if (response_status.empty()) {
|
|
||||||
response_status = util::make_string_ref_uint(balloc, status_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto content_length = util::make_string_ref_uint(balloc, html.size());
|
auto content_length = util::make_string_ref_uint(balloc, html.size());
|
||||||
auto date = make_string_ref(balloc, StringRef{lgconf->time_http_str});
|
auto date = make_string_ref(balloc, StringRef{lgconf->time_http_str});
|
||||||
|
|
||||||
|
@ -1405,10 +1398,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
nva.reserve(resp.fs.headers().size() + 4 +
|
nva.reserve(resp.fs.headers().size() + 4 +
|
||||||
httpconf.add_response_headers.size());
|
httpconf.add_response_headers.size());
|
||||||
|
|
||||||
auto response_status = http2::stringify_status(resp.http_status);
|
auto response_status = http2::stringify_status(balloc, resp.http_status);
|
||||||
if (response_status.empty()) {
|
|
||||||
response_status = util::make_string_ref_uint(balloc, resp.http_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
nva.push_back(http2::make_nv_ls_nocopy(":status", response_status));
|
||||||
|
|
||||||
|
|
|
@ -810,6 +810,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
size_t bodylen) {
|
size_t bodylen) {
|
||||||
const auto &req = downstream->request();
|
const auto &req = downstream->request();
|
||||||
auto &resp = downstream->response();
|
auto &resp = downstream->response();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
auto connection_close = false;
|
auto connection_close = false;
|
||||||
if (req.http_major <= 0 || (req.http_major == 1 && req.http_minor == 0)) {
|
if (req.http_major <= 0 || (req.http_major == 1 && req.http_minor == 0)) {
|
||||||
|
@ -829,7 +830,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
auto output = downstream->get_response_buf();
|
auto output = downstream->get_response_buf();
|
||||||
|
|
||||||
output->append("HTTP/1.1 ");
|
output->append("HTTP/1.1 ");
|
||||||
output->append(http2::get_status_string(resp.http_status));
|
output->append(http2::get_status_string(balloc, resp.http_status));
|
||||||
output->append("\r\n");
|
output->append("\r\n");
|
||||||
|
|
||||||
for (auto &kv : resp.fs.headers()) {
|
for (auto &kv : resp.fs.headers()) {
|
||||||
|
@ -868,7 +869,6 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpsUpstream::error_reply(unsigned int status_code) {
|
void HttpsUpstream::error_reply(unsigned int status_code) {
|
||||||
auto html = http::create_error_html(status_code);
|
|
||||||
auto downstream = get_downstream();
|
auto downstream = get_downstream();
|
||||||
|
|
||||||
if (!downstream) {
|
if (!downstream) {
|
||||||
|
@ -877,6 +877,9 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &resp = downstream->response();
|
auto &resp = downstream->response();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
|
auto html = http::create_error_html(balloc, status_code);
|
||||||
|
|
||||||
resp.http_status = status_code;
|
resp.http_status = status_code;
|
||||||
// we are going to close connection for both frontend and backend in
|
// we are going to close connection for both frontend and backend in
|
||||||
|
@ -887,7 +890,7 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
|
||||||
auto output = downstream->get_response_buf();
|
auto output = downstream->get_response_buf();
|
||||||
|
|
||||||
output->append("HTTP/1.1 ");
|
output->append("HTTP/1.1 ");
|
||||||
auto status_str = http2::get_status_string(status_code);
|
auto status_str = http2::get_status_string(balloc, status_code);
|
||||||
output->append(status_str);
|
output->append(status_str);
|
||||||
output->append("\r\nServer: ");
|
output->append("\r\nServer: ");
|
||||||
output->append(get_config()->http.server_name);
|
output->append(get_config()->http.server_name);
|
||||||
|
@ -948,6 +951,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
|
|
||||||
const auto &req = downstream->request();
|
const auto &req = downstream->request();
|
||||||
auto &resp = downstream->response();
|
auto &resp = downstream->response();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
#ifdef HAVE_MRUBY
|
#ifdef HAVE_MRUBY
|
||||||
if (!downstream->get_non_final_response()) {
|
if (!downstream->get_non_final_response()) {
|
||||||
|
@ -974,7 +978,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
buf->append(".");
|
buf->append(".");
|
||||||
buf->append(util::utos(req.http_minor));
|
buf->append(util::utos(req.http_minor));
|
||||||
buf->append(" ");
|
buf->append(" ");
|
||||||
buf->append(http2::get_status_string(resp.http_status));
|
buf->append(http2::get_status_string(balloc, resp.http_status));
|
||||||
buf->append("\r\n");
|
buf->append("\r\n");
|
||||||
|
|
||||||
auto &httpconf = get_config()->http;
|
auto &httpconf = get_config()->http;
|
||||||
|
|
|
@ -856,8 +856,9 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &resp = downstream->response();
|
const auto &resp = downstream->response();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
auto status_string = http2::get_status_string(resp.http_status);
|
auto status_string = http2::get_status_string(balloc, resp.http_status);
|
||||||
|
|
||||||
const auto &headers = resp.fs.headers();
|
const auto &headers = resp.fs.headers();
|
||||||
|
|
||||||
|
@ -921,8 +922,9 @@ int SpdyUpstream::error_reply(Downstream *downstream,
|
||||||
unsigned int status_code) {
|
unsigned int status_code) {
|
||||||
int rv;
|
int rv;
|
||||||
auto &resp = downstream->response();
|
auto &resp = downstream->response();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
auto html = http::create_error_html(status_code);
|
auto html = http::create_error_html(balloc, status_code);
|
||||||
resp.http_status = status_code;
|
resp.http_status = status_code;
|
||||||
auto body = downstream->get_response_buf();
|
auto body = downstream->get_response_buf();
|
||||||
body->append(html);
|
body->append(html);
|
||||||
|
@ -935,8 +937,9 @@ int SpdyUpstream::error_reply(Downstream *downstream,
|
||||||
auto lgconf = log_config();
|
auto lgconf = log_config();
|
||||||
lgconf->update_tstamp(std::chrono::system_clock::now());
|
lgconf->update_tstamp(std::chrono::system_clock::now());
|
||||||
|
|
||||||
std::string content_length = util::utos(html.size());
|
auto content_length = util::make_string_ref_uint(balloc, html.size());
|
||||||
std::string status_string = http2::get_status_string(status_code);
|
auto status_string = http2::get_status_string(balloc, status_code);
|
||||||
|
|
||||||
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
|
const char *nv[] = {":status", status_string.c_str(), ":version", "http/1.1",
|
||||||
"content-type", "text/html; charset=UTF-8", "server",
|
"content-type", "text/html; charset=UTF-8", "server",
|
||||||
get_config()->http.server_name.c_str(), "content-length",
|
get_config()->http.server_name.c_str(), "content-length",
|
||||||
|
@ -995,6 +998,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &req = downstream->request();
|
const auto &req = downstream->request();
|
||||||
|
auto &balloc = downstream->get_block_allocator();
|
||||||
|
|
||||||
#ifdef HAVE_MRUBY
|
#ifdef HAVE_MRUBY
|
||||||
auto worker = handler_->get_worker();
|
auto worker = handler_->get_worker();
|
||||||
|
@ -1030,7 +1034,7 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||||
|
|
||||||
size_t hdidx = 0;
|
size_t hdidx = 0;
|
||||||
std::string via_value;
|
std::string via_value;
|
||||||
auto status_string = http2::get_status_string(resp.http_status);
|
auto status_string = http2::get_status_string(balloc, resp.http_status);
|
||||||
nv[hdidx++] = ":status";
|
nv[hdidx++] = ":status";
|
||||||
nv[hdidx++] = status_string.c_str();
|
nv[hdidx++] = status_string.c_str();
|
||||||
nv[hdidx++] = ":version";
|
nv[hdidx++] = ":version";
|
||||||
|
|
|
@ -419,7 +419,8 @@ public:
|
||||||
: base(reinterpret_cast<const char *>(s)), len(n) {}
|
: base(reinterpret_cast<const char *>(s)), len(n) {}
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
StringRef(InputIt first, InputIt last)
|
StringRef(InputIt first, InputIt last)
|
||||||
: base(&*first), len(std::distance(first, last)) {}
|
: base(reinterpret_cast<const char *>(&*first)),
|
||||||
|
len(std::distance(first, last)) {}
|
||||||
template <typename InputIt>
|
template <typename InputIt>
|
||||||
StringRef(InputIt *first, InputIt *last)
|
StringRef(InputIt *first, InputIt *last)
|
||||||
: base(reinterpret_cast<const char *>(first)),
|
: base(reinterpret_cast<const char *>(first)),
|
||||||
|
|
Loading…
Reference in New Issue