Unverified Commit 2f049813 authored by Dennis Jenkins's avatar Dennis Jenkins Committed by GitHub

ResponseWriter caputres response size (bytes) for use after send(). (#709)

* Add a debug build with SSL disabled.

* Expose response stats in ResponseWriter.

* Add formal tracking of HTTP server repsonse size and response code so that they are available in the ResponseWriter AFTER send() is called.

* Trigger travis-ci rebuild.
parent 2d222394
......@@ -402,6 +402,13 @@ public:
std::shared_ptr<Tcp::Peer> peer() const;
// Returns total count of HTTP bytes (headers, cookies, body) written when
// sending the response. Result valid AFTER ResponseWriter.send() is called.
ssize_t getResponseSize() const { return sent_bytes_; }
// Returns HTTP result code that was sent with the response.
Code getResponseCode() const { return response_.code(); }
// Unsafe API
DynamicStreamBuf *rdbuf();
......@@ -427,6 +434,7 @@ private:
DynamicStreamBuf buf_;
Tcp::Transport *transport_;
Timeout timeout_;
ssize_t sent_bytes_;
};
Async::Promise<ssize_t>
......
......@@ -653,17 +653,17 @@ void ResponseStream::ends() {
ResponseWriter::ResponseWriter(ResponseWriter &&other)
: response_(std::move(other.response_)), peer_(other.peer_),
buf_(std::move(other.buf_)), transport_(other.transport_),
timeout_(std::move(other.timeout_)) {}
timeout_(std::move(other.timeout_)), sent_bytes_(0) {}
ResponseWriter::ResponseWriter(Tcp::Transport *transport, Request request,
Handler *handler, std::weak_ptr<Tcp::Peer> peer)
: response_(request.version()), peer_(peer), buf_(DefaultStreamSize),
transport_(transport),
timeout_(transport, handler, std::move(request), peer) {}
timeout_(transport, handler, std::move(request), peer), sent_bytes_(0) {}
ResponseWriter::ResponseWriter(const ResponseWriter &other)
: response_(other.response_), peer_(other.peer_), buf_(DefaultStreamSize),
transport_(other.transport_), timeout_(other.timeout_) {}
transport_(other.transport_), timeout_(other.timeout_), sent_bytes_(0) {}
void ResponseWriter::setMime(const Mime::MediaType &mime) {
auto ct = response_.headers().tryGet<Header::ContentType>();
......@@ -781,6 +781,7 @@ Async::Promise<ssize_t> ResponseWriter::putOnWire(const char *data,
}
auto buffer = buf_.buffer();
sent_bytes_ += buffer.size();
timeout_.disarm();
......@@ -940,11 +941,10 @@ void Handler::onConnection(const std::shared_ptr<Tcp::Peer> &peer) {
void Handler::onDisconnection(const std::shared_ptr<Tcp::Peer> & /*peer*/) {}
void Handler::onTimeout(const Request& /*request*/, ResponseWriter /*response*/) {}
void Handler::onTimeout(const Request & /*request*/,
ResponseWriter /*response*/) {}
Timeout::~Timeout() {
disarm();
}
Timeout::~Timeout() { disarm(); }
void Timeout::disarm() {
if (transport && armed) {
......
......@@ -340,3 +340,71 @@ TEST(http_server_test, server_request_copies_address) {
ASSERT_EQ("127.0.0.1", resultData);
}
struct ResponseSizeHandler : public Http::Handler {
HTTP_PROTOTYPE(ResponseSizeHandler)
explicit ResponseSizeHandler(size_t &rsize, Http::Code &rcode)
: rsize_(rsize), rcode_(rcode) {}
void onRequest(const Http::Request &request,
Http::ResponseWriter writer) override {
std::string requestAddress = request.address().host();
writer.send(Http::Code::Ok, requestAddress);
std::cout << "[server] Sent: " << requestAddress << std::endl;
rsize_ = writer.getResponseSize();
rcode_ = writer.getResponseCode();
}
size_t &rsize_;
Http::Code &rcode_;
};
TEST(http_server_test, response_size_captured) {
const Pistache::Address address("localhost", Pistache::Port(0));
size_t rsize = 0;
Http::Code rcode;
Http::Endpoint server(address);
auto flags = Tcp::Options::ReuseAddr;
auto server_opts = Http::Endpoint::options().flags(flags);
server.init(server_opts);
server.setHandler(Http::make_handler<ResponseSizeHandler>(rsize, rcode));
server.serveThreaded();
const std::string server_address = "localhost:" + server.getPort().toString();
std::cout << "Server address: " << server_address << "\n";
// Use the built-in http client, but this test is interested in testing
// that the ResponseWriter in the server stashed the correct size and code
// values.
Http::Client client;
client.init();
auto rb = client.get(server_address);
auto response = rb.send();
std::string resultData;
response.then(
[&resultData](Http::Response resp) {
std::cout << "Response code is " << resp.code() << std::endl;
if (resp.code() == Http::Code::Ok) {
resultData = resp.body();
}
},
Async::Throw);
const int WAIT_TIME = 2;
Async::Barrier<Http::Response> barrier(response);
barrier.wait_for(std::chrono::seconds(WAIT_TIME));
client.shutdown();
server.shutdown();
// Sanity check (stolen from AddressEchoHandler test).
ASSERT_EQ("127.0.0.1", resultData);
std::cout << "Response size is " << rsize << "\n";
ASSERT_GT(rsize, 1);
ASSERT_LT(rsize, 300);
ASSERT_EQ(rcode, Http::Code::Ok);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment