Add "dnf" (= "do not forward") parameter to backend option
This commit is contained in:
parent
29cbf8b83f
commit
138419d232
|
@ -104,6 +104,7 @@ if(ENABLE_APP)
|
|||
shrpx_router.cc
|
||||
shrpx_api_downstream_connection.cc
|
||||
shrpx_health_monitor_downstream_connection.cc
|
||||
shrpx_null_downstream_connection.cc
|
||||
shrpx_exec.cc
|
||||
shrpx_dns_resolver.cc
|
||||
shrpx_dual_dns_resolver.cc
|
||||
|
|
|
@ -139,6 +139,7 @@ NGHTTPX_SRCS = \
|
|||
shrpx_api_downstream_connection.cc shrpx_api_downstream_connection.h \
|
||||
shrpx_health_monitor_downstream_connection.cc \
|
||||
shrpx_health_monitor_downstream_connection.h \
|
||||
shrpx_null_downstream_connection.cc shrpx_null_downstream_connection.h \
|
||||
shrpx_exec.cc shrpx_exec.h \
|
||||
shrpx_dns_resolver.cc shrpx_dns_resolver.h \
|
||||
shrpx_dual_dns_resolver.cc shrpx_dual_dns_resolver.h \
|
||||
|
|
20
src/shrpx.cc
20
src/shrpx.cc
|
@ -1740,12 +1740,13 @@ Connections:
|
|||
"affinity=<METHOD>", "dns", "redirect-if-not-tls",
|
||||
"upgrade-scheme", "mruby=<PATH>",
|
||||
"read-timeout=<DURATION>", "write-timeout=<DURATION>",
|
||||
"group=<GROUP>", "group-weight=<N>", and "weight=<N>".
|
||||
The parameter consists of keyword, and optionally
|
||||
followed by "=" and value. For example, the parameter
|
||||
"proto=h2" consists of the keyword "proto" and value
|
||||
"h2". The parameter "tls" consists of the keyword "tls"
|
||||
without value. Each parameter is described as follows.
|
||||
"group=<GROUP>", "group-weight=<N>", "weight=<N>", and
|
||||
"dnf". The parameter consists of keyword, and
|
||||
optionally followed by "=" and value. For example, the
|
||||
parameter "proto=h2" consists of the keyword "proto" and
|
||||
value "h2". The parameter "tls" consists of the keyword
|
||||
"tls" without value. Each parameter is described as
|
||||
follows.
|
||||
|
||||
The backend application protocol can be specified using
|
||||
optional "proto" parameter, and in the form of
|
||||
|
@ -1876,6 +1877,13 @@ Connections:
|
|||
weight becomes 1. "weight" is ignored if session
|
||||
affinity is enabled.
|
||||
|
||||
If "dnf" parameter is specified, an incoming request is
|
||||
not forwarded to a backend and just consumed along with
|
||||
the request body (actually a backend server never be
|
||||
contacted). It is expected that the HTTP response is
|
||||
generated by mruby script (see "mruby=<PATH>" parameter
|
||||
above). "dnf" is an abbreviation of "do not forward".
|
||||
|
||||
Since ";" and ":" are used as delimiter, <PATTERN> must
|
||||
not contain these characters. In order to include ":"
|
||||
in <PATTERN>, one has to specify "%3A" (which is
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "shrpx_connect_blocker.h"
|
||||
#include "shrpx_api_downstream_connection.h"
|
||||
#include "shrpx_health_monitor_downstream_connection.h"
|
||||
#include "shrpx_null_downstream_connection.h"
|
||||
#include "shrpx_log.h"
|
||||
#include "util.h"
|
||||
#include "template.h"
|
||||
|
@ -973,6 +974,13 @@ ClientHandler::get_downstream_connection(int &err, Downstream *downstream) {
|
|||
}
|
||||
|
||||
auto &group = groups[group_idx];
|
||||
|
||||
if (group->shared_addr->dnf) {
|
||||
auto dconn = std::make_unique<NullDownstreamConnection>(group);
|
||||
dconn->set_client_handler(this);
|
||||
return dconn;
|
||||
}
|
||||
|
||||
auto addr = get_downstream_addr(err, group.get(), downstream);
|
||||
if (addr == nullptr) {
|
||||
return nullptr;
|
||||
|
|
|
@ -851,6 +851,7 @@ struct DownstreamParams {
|
|||
bool dns;
|
||||
bool redirect_if_not_tls;
|
||||
bool upgrade_scheme;
|
||||
bool dnf;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
@ -1025,6 +1026,8 @@ int parse_downstream_params(DownstreamParams &out,
|
|||
return -1;
|
||||
}
|
||||
out.group_weight = n;
|
||||
} else if (util::strieq_l("dnf", param)) {
|
||||
out.dnf = true;
|
||||
} else if (!param.empty()) {
|
||||
LOG(ERROR) << "backend: " << param << ": unknown keyword";
|
||||
return -1;
|
||||
|
@ -1089,6 +1092,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
|
|||
addr.sni = make_string_ref(downstreamconf.balloc, params.sni);
|
||||
addr.dns = params.dns;
|
||||
addr.upgrade_scheme = params.upgrade_scheme;
|
||||
addr.dnf = params.dnf;
|
||||
|
||||
auto &routerconf = downstreamconf.router;
|
||||
auto &router = routerconf.router;
|
||||
|
@ -1189,6 +1193,14 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
// All backends in the same group must have the same dnf
|
||||
// setting. If some backends do not specify dnf, and there is
|
||||
// at least one backend with dnf, it is used for all backends in
|
||||
// the group. In general, multiple backends are not necessary
|
||||
// for dnf because there is no need for load balancing.
|
||||
if (params.dnf) {
|
||||
g.dnf = true;
|
||||
}
|
||||
|
||||
g.addrs.push_back(addr);
|
||||
continue;
|
||||
|
@ -1213,6 +1225,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
|
|||
g.mruby_file = make_string_ref(downstreamconf.balloc, params.mruby);
|
||||
g.timeout.read = params.read_timeout;
|
||||
g.timeout.write = params.write_timeout;
|
||||
g.dnf = params.dnf;
|
||||
|
||||
if (pattern[0] == '*') {
|
||||
// wildcard pattern
|
||||
|
|
|
@ -494,6 +494,8 @@ struct DownstreamAddrConfig {
|
|||
// variant (e.g., "https") when forwarding request to a backend
|
||||
// connected by TLS connection.
|
||||
bool upgrade_scheme;
|
||||
// true if a request should not be forwarded to a backend.
|
||||
bool dnf;
|
||||
};
|
||||
|
||||
// Mapping hash to idx which is an index into
|
||||
|
@ -523,6 +525,8 @@ struct DownstreamAddrGroupConfig {
|
|||
// true if this group requires that client connection must be TLS,
|
||||
// and the request must be redirected to https URI.
|
||||
bool redirect_if_not_tls;
|
||||
// true if a request should not be forwarded to a backend.
|
||||
bool dnf;
|
||||
// Timeouts for backend connection.
|
||||
struct {
|
||||
ev_tstamp read;
|
||||
|
|
|
@ -747,6 +747,13 @@ int HttpsUpstream::on_write() {
|
|||
handler_->repeat_read_timer();
|
||||
|
||||
return resume_read(SHRPX_NO_BUFFER, nullptr, 0);
|
||||
} else {
|
||||
// If the request is not complete, close the connection.
|
||||
delete_downstream();
|
||||
|
||||
handler_->set_should_close_after_write(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2021 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_null_downstream_connection.h"
|
||||
#include "shrpx_upstream.h"
|
||||
#include "shrpx_downstream.h"
|
||||
#include "shrpx_log.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
NullDownstreamConnection::NullDownstreamConnection(
|
||||
const std::shared_ptr<DownstreamAddrGroup> &group)
|
||||
: group_(group) {}
|
||||
|
||||
NullDownstreamConnection::~NullDownstreamConnection() {}
|
||||
|
||||
int NullDownstreamConnection::attach_downstream(Downstream *downstream) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
DCLOG(INFO, this) << "Attaching to DOWNSTREAM:" << downstream;
|
||||
}
|
||||
|
||||
downstream_ = downstream;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NullDownstreamConnection::detach_downstream(Downstream *downstream) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
DCLOG(INFO, this) << "Detaching from DOWNSTREAM:" << downstream;
|
||||
}
|
||||
downstream_ = nullptr;
|
||||
}
|
||||
|
||||
int NullDownstreamConnection::push_request_headers() { return 0; }
|
||||
|
||||
int NullDownstreamConnection::push_upload_data_chunk(const uint8_t *data,
|
||||
size_t datalen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NullDownstreamConnection::end_upload_data() { return 0; }
|
||||
|
||||
void NullDownstreamConnection::pause_read(IOCtrlReason reason) {}
|
||||
|
||||
int NullDownstreamConnection::resume_read(IOCtrlReason reason,
|
||||
size_t consumed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NullDownstreamConnection::force_resume_read() {}
|
||||
|
||||
int NullDownstreamConnection::on_read() { return 0; }
|
||||
|
||||
int NullDownstreamConnection::on_write() { return 0; }
|
||||
|
||||
void NullDownstreamConnection::on_upstream_change(Upstream *uptream) {}
|
||||
|
||||
bool NullDownstreamConnection::poolable() const { return false; }
|
||||
|
||||
const std::shared_ptr<DownstreamAddrGroup> &
|
||||
NullDownstreamConnection::get_downstream_addr_group() const {
|
||||
return group_;
|
||||
}
|
||||
|
||||
DownstreamAddr *NullDownstreamConnection::get_addr() const { return nullptr; }
|
||||
|
||||
} // namespace shrpx
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2021 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_NULL_DOWNSTREAM_CONNECTION_H
|
||||
#define SHRPX_NULL_DOWNSTREAM_CONNECTION_H
|
||||
|
||||
#include "shrpx_downstream_connection.h"
|
||||
#include "template.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
class NullDownstreamConnection : public DownstreamConnection {
|
||||
public:
|
||||
NullDownstreamConnection(const std::shared_ptr<DownstreamAddrGroup> &group);
|
||||
virtual ~NullDownstreamConnection();
|
||||
virtual int attach_downstream(Downstream *downstream);
|
||||
virtual void detach_downstream(Downstream *downstream);
|
||||
|
||||
virtual int push_request_headers();
|
||||
virtual int push_upload_data_chunk(const uint8_t *data, size_t datalen);
|
||||
virtual int end_upload_data();
|
||||
|
||||
virtual void pause_read(IOCtrlReason reason);
|
||||
virtual int resume_read(IOCtrlReason reason, size_t consumed);
|
||||
virtual void force_resume_read();
|
||||
|
||||
virtual int on_read();
|
||||
virtual int on_write();
|
||||
|
||||
virtual void on_upstream_change(Upstream *uptream);
|
||||
|
||||
// true if this object is poolable.
|
||||
virtual bool poolable() const;
|
||||
|
||||
virtual const std::shared_ptr<DownstreamAddrGroup> &
|
||||
get_downstream_addr_group() const;
|
||||
virtual DownstreamAddr *get_addr() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<DownstreamAddrGroup> group_;
|
||||
};
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
#endif // SHRPX_NULL_DOWNSTREAM_CONNECTION_H
|
|
@ -82,7 +82,7 @@ using DownstreamKey =
|
|||
size_t, Proto, uint32_t, uint32_t,
|
||||
uint32_t, bool, bool, bool, bool>>,
|
||||
bool, SessionAffinity, StringRef, StringRef,
|
||||
SessionAffinityCookieSecure, int64_t, int64_t, StringRef>;
|
||||
SessionAffinityCookieSecure, int64_t, int64_t, StringRef, bool>;
|
||||
|
||||
namespace {
|
||||
DownstreamKey
|
||||
|
@ -122,6 +122,7 @@ create_downstream_key(const std::shared_ptr<SharedDownstreamAddr> &shared_addr,
|
|||
std::get<6>(dkey) = timeout.read;
|
||||
std::get<7>(dkey) = timeout.write;
|
||||
std::get<8>(dkey) = mruby_file;
|
||||
std::get<9>(dkey) = shared_addr->dnf;
|
||||
|
||||
return dkey;
|
||||
}
|
||||
|
@ -252,6 +253,7 @@ void Worker::replace_downstream_config(
|
|||
}
|
||||
shared_addr->affinity_hash = src.affinity_hash;
|
||||
shared_addr->redirect_if_not_tls = src.redirect_if_not_tls;
|
||||
shared_addr->dnf = src.dnf;
|
||||
shared_addr->timeout.read = src.timeout.read;
|
||||
shared_addr->timeout.write = src.timeout.write;
|
||||
|
||||
|
|
|
@ -216,6 +216,8 @@ struct SharedDownstreamAddr {
|
|||
// true if this group requires that client connection must be TLS,
|
||||
// and the request must be redirected to https URI.
|
||||
bool redirect_if_not_tls;
|
||||
// true if a request should not be forwarded to a backend.
|
||||
bool dnf;
|
||||
// Timeouts for backend connection.
|
||||
struct {
|
||||
ev_tstamp read;
|
||||
|
|
Loading…
Reference in New Issue