Share
Embed
Transcript
131 slides
-
ࣗྗͰHTTPΛΔ? ΫϥΠΞϯτ αʔό HTTP/1.0 200 OK! Date: Mon, 21 Sep
2015 11:40:04 GMT! Content-Length: 14! ! Hello, World! GET / HTTP/1.0 -
ΞοϋΠɺεϛϚηϯʜ ΫϥΠΞϯτ αʔό GET / HTTP/1.1! Host: example.com! Connection: Upgrade,
HTTP2-Settings! Upgrade: h2c 1! HTTP2-Settings: … ਖ਼͘͠HTTPͰձ͢Δͷ͍͠ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
};! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart()
noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } ΫϥΠΞϯτ͔ΒͷΞΫηεΛड͚͚Δ ΞυϨεͱϙʔτ൪߸ͷϦετ ϓϩτίϧʹHTTPΛࢦఆ ໊લղܾΛڐՄ -
};! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart()
noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } ϦΫΤετϋϯυϥͷfactoryΛొ HTTPServerଓΛड͚͚Δͱ ొ͞ΕͨfactoryͰϦΫΤετϋϯυϥΛੜ Ҏޙϔομຊจ͕ಧ͘ͱ ϦΫΤετϋϯυϥͷϝϯό͕ݺΕΔ HTTPServerͷΠϯελϯεΛ࡞Δ -
void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };!
class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } ଓΛͪड͚ΔΞυϨεΛࢦఆ start()ͰHTTPαʔόΛىಈ start()αʔό͕ఀࢭ͢Δ·ͰฦΒͳ͍ -
proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!"
).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! αʔόىಈ࣌ʹߦ͏ॲཧ ऴྃ࣌ʹߦ͏ॲཧ RequestHandlerFactoryΛܧঝ ϦΫΤετ͕དྷͨ࣌ʹߦ͏ॲཧ ϦΫΤετϋϯυϥϑΝΫτϦ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! ϦΫΤετϋϯυϥ RequestHandlerΛܧঝ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! ϦΫΤετϋϯυϥ onRequest HTTPϦΫΤετͷ ϔομ͕ಧ͍ͨ࣌ͰݺΕΔ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! ϦΫΤετϋϯυϥ onEOM HTTPϦΫΤετΛ શͯड৴ͨ࣌͠ͰݺΕΔ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! ϦΫΤετϋϯυϥ onBody HTTPϦΫΤετͷ ຊจΛड৴ͨ࣌͠ͰݺΕΔ -
ϔομ &OEPG.FTTBHF શମͷ͕͔͞Βͳͯ͘ ຊจΛૹΓ࢝ΊΔࣄ͕Ͱ͖Δ νϟϯΫ νϟϯΫ νϟϯΫ νϟϯΫసૹ HTTPͷຊจ ෳʹׂͯ͠
ૹΔ͜ͱ͕Ͱ͖Δ ϔομʹຊจͷ͞Λ ॻ͘ΘΓʹ νϟϯΫʹνϟϯΫͷ͞Λॻ͘ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! ϦΫΤετϋϯυϥ onUpgrade ϦΫΤετͷ༰͕ UPGRADEͩͬͨ߹ʹݺΕΔ -
void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf>
body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! ϦΫΤετϋϯυϥ requestComplete ΫϥΠΞϯτʹϨεϙϯεΛૹΓΔͱݺΕΔ onError ΫϥΠΞϯτଆ͔Βஅ͞ΕΔ Ϩεϙϯεͷૹ৴ྃ·Ͱ౸ୡग़དྷͳ͘ͳͬͨΒ ݺΕΔ -
void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status(
200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! ϦΫΤετϋϯυϥ ͜ΕҎ߱ϦΫΤετϋϯυϥ͕ ݺΕΔࣄແ͍ͨΊɺ͜͜ͰࣗΛdelete͢Δ ໌ࣔతͳdeleteେมΠέͯͳ͍͕ Proxygen͕ੜϙΠϯλ͔͠ѲΕͳ͍ͷͰ ͜͏͢Δ͔͠ͳ͍ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" ).body( "Hello, World!" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! Hello,World!ͷྫͰ͍ͬͯΔࣄ ΫϥΠΞϯτ͕ϦΫΤετΛૹΓͬͨΒ ResponseBuilderΛ࡞ͬͯ εςʔλείʔυʹ200 OKΛࢦఆͯ͠ ຊจʹ”Hello, World!” ࠷ޙʹsendWithEOM()Ͱ ϨεϙϯεΛऴྃͤ͞Δ -
$ telnet www41050u.sakura.ne.jp 8080 Trying xxx.xxx.xxx.xxx... Connected to www41050u.sakura.ne.jp. Escape
character is '^]'. GET / HTTP/1.1 ! HTTP/1.1 200 OK Date: Wed, 30 Sep 2015 17:11:43 GMT Connection: keep-alive Content-Length: 13 ! Hello, World! telnetͰଓͯ͠ΈΑ͏ Ϩεϙϯε͕དྷͨ! -
tx.body( "Hello, World!" ).sendWithEOM(); tx.body( "hoge" ).send();! tx.body( "fuga" ).send();!
tx.body( "piyo" ).send();! tx.body( "foo" ).sendWithEOM(); send()Λ͏ͱνϟϯΫసૹʹͳΔ -
send()Λ͏ͱνϟϯΫసૹʹͳΔ $ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xxx….! Connected to www41050u.sakura.ne.jp.!
Escape character is '^]'.! GET / HTTP/1.1! ! HTTP/1.1 200 OK! Transfer-Encoding: chunked! Date: Wed, 30 Sep 2015 16:39:34 GMT! Connection: keep-alive! ! 4! hoge! 4! fuga! 4! piyo! 3! foo! 0! ! νϟϯΫ -
public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void
onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" );! tx.header( "Content-Type", "text/plain" );! tx.body( "Hello, World!” ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! Ϩεϙϯεϔομ ResponseBuilderͷheader()Λͬͯ ϨεϙϯεϔομΛՃ͢Δ Content-Type: text/plain ΛՃ -
$ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xxx...! Connected to www41050u.sakura.ne.jp.! Escape
character is '^]'.! GET / HTTP/1.1! ! HTTP/1.1 200 OK! Content-Type: text/plain! Date: Thu, 01 Oct 2015 15:04:42 GMT! Connection: keep-alive! Content-Length: 13! ! Hello, World! Ϩεϙϯεϔομ Content-Type -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" );! tx.header( "Content-Type", "text/plain" );! tx.body( std::string( 10000, '[' ) ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.enableContentCompression = true;! options.contentCompressionMinimumSize = 5;! options.contentCompressionLevel = 4;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {}! void
onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! tx.status( 200, "OK" );! tx.header( "Content-Type", "text/plain" );! tx.body( std::string( 10000, '[' ) ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) { ! 10000bytesͷ’[’ େ͖ͳຊจͩ!ѹॖ͠Α͏! -
) noexcept override { return new handler(); }! };! int
main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.enableContentCompression = true;! options.contentCompressionMinimumSize = 5;! options.contentCompressionLevel = 4;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } HTTPServerOptionʹ ѹॖʹඞཁͳใΛઃఆ enableContentCompression ѹॖΛ༗ޮʹ͢Δ σϑΥϧτfalse -
) noexcept override { return new handler(); }! };! int
main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.enableContentCompression = true;! options.contentCompressionMinimumSize = 5;! options.contentCompressionLevel = 4;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } HTTPServerOptionʹ ѹॖʹඞཁͳใΛઃఆ contentCompressionMinimumSize ͜ͷαΠζະຬͷຊจѹॖ͠ͳ͍ σϑΥϧτ1000 -
) noexcept override { return new handler(); }! };! int
main( int argc, char* argv[] ) { ! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.enableContentCompression = true;! options.contentCompressionMinimumSize = 5;! options.contentCompressionLevel = 4;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } HTTPServerOptionʹ ѹॖʹඞཁͳใΛઃఆ contentCompressionLevel zlibͷѹॖϨϕϧ σϑΥϧτ-1 zlibʹѹॖϨϕϧ-1Λ͢ͱѹॖ͕ࣦഊ͠ αʔό͕Τϥʔऴྃ͢Δ(ͭ·Γઃఆඞਢ) -
proxygen::HTTPServer::Protocol::HTTP! }}; ! proxygen::HTTPServerOptions options;! options.enableContentCompression = true;! options.contentCompressionMinimumSize =
5;! options.contentCompressionLevel = 4;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } contentCompressionTypes ͜͜ͰσϑΥϧτͷ··ʹ͍ͯ͠ΔΦϓγϣϯ ѹॖ͢ΔContent-Type σϑΥϧτ ”application/javascript”,”application/json","application/x-javascript", “application/xhtml+xml","application/xml","application/xml+rss", “text/css","text/html","text/javascript","text/plain","text/xml" Content-Type͕͜ΕΒʹ߹க͢Δ߹ͷΈ ѹॖΛߦ͏ -
$ telnet www41050u.sakura.ne.jp 8080 Trying xxx.xxx.xxx.xxx... Connected to www41050u.sakura.ne.jp. Escape
character is '^]'. GET / HTTP/1.1 ! HTTP/1.1 200 OK Content-Type: text/plain Date: Thu, 01 Oct 2015 16:13:37 GMT Connection: keep-alive Content-Length: 10000 ! [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[(ҎԼུ) ಛʹԿࢦఆͤͣʹGET -
$ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xxx...! Connected to www41050u.sakura.ne.jp.! Escape
character is '^]'.! GET / HTTP/1.1! Accept-Encoding: gzip ! ! HTTP/1.1 200 OK! Content-Type: text/plain! Content-Encoding: gzip! Date: Thu, 01 Oct 2015 16:16:56 GMT! Connection: keep-alive! Content-Length: 46! ! ?n@???#' Accept-Encoding: gzip ͰGET ΫϥΠΞϯτʮgzipͰѹॖͯ͠ྑ͍ʯ αʔόʮgzipͰѹॖͯ͋͠ΔΑʯ ຊจ͕gzipͰѹॖ͞Ε͍ͯΔ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( path == "/" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "It's a top page." ).sendWithEOM();! } ! else if( path == "/foo.txt" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 404, "File not found" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! std::string path;! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }};! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( path == "/" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "It's a top page." ).sendWithEOM();! } ! else if( path == "/foo.txt" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 404, "File not found" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! onRequestͰͬͯ͘Δ HTTPMessageʹύε͕ೖ͍ͬͯΔ HTTPMessage::getPath()Ͱ ύεΛจࣈྻͰऔಘ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( path == "/" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "It's a top page." ).sendWithEOM();! } ! else if( path == "/foo.txt" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 404, "File not found" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! ޙonEOMͰฦ͢ίϯςϯπΛ ύεʹΑͬͯม͑Δ͚ͩ -
$ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xxx...! Connected to www41050u.sakura.ne.jp.! Escape
character is '^]'.! GET / HTTP/1.1! ! HTTP/1.1 200 OK! Content-Type: text/plain! Date: Thu, 01 Oct 2015 17:38:49 GMT! Connection: keep-alive! Content-Length: 16! ! It's a top page.! ! GET /foo.txt HTTP/1.1! ! HTTP/1.1 200 OK! Content-Type: text/plain! Date: Thu, 01 Oct 2015 17:39:03 GMT! Connection: keep-alive! Content-Length: 4! ! Foo. ύεʹΑͬͯ ҟͳΔ Ϩεϙϯε -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( arg == "fuga" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Fuga." ).sendWithEOM();! } ! else if( arg == "foo" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! std::string arg;! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }};! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( arg == "fuga" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Fuga." ).sendWithEOM();! } ! else if( arg == "foo" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! ΫΤϦHTTPMessageʹೖ͍ͬͯΔ HTTPMessage::getDecodedQueryParam()Ͱ ΛจࣈྻͰऔಘ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( arg == "fuga" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Fuga." ).sendWithEOM();! } ! else if( arg == "foo" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Foo." ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! ޙonEOMͰฦ͢ίϯςϯπΛ ʹΑͬͯม͑Δ͚ͩ -
$ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xxx...! Connected to www41050u.sakura.ne.jp.! Escape
character is '^]'.! GET / HTTP/1.1! ! HTTP/1.1 400 Bad Request! Date: Sat, 03 Oct 2015 05:46:54 GMT! Connection: keep-alive! Content-Length: 0! ! GET /?hoge=fuga HTTP/1.1! ! HTTP/1.1 200 OK! Content-Type: text/plain! Date: Sat, 03 Oct 2015 05:47:12 GMT! Connection: keep-alive! Content-Length: 5! ! Fuga. ΫΤϦʹΑͬͯ ҟͳΔ Ϩεϙϯε -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( host == "www41050u.sakura.ne.jp:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "First webpage\n" ).sendWithEOM();! } ! else if( host == "localhost:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Second webpage\n" ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! std::string host;! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "localhost", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP }! };! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
std::string host;! };! class factory : public proxygen::RequestHandlerFactory {! public:!
void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "localhost", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP }! };! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } ෳͷϗετ໊͔Βͷ ଓΛड͚͚ΔΑ͏ʹ͢Δ -
#include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler : public
proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( host == "www41050u.sakura.ne.jp:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "First webpage\n" ).sendWithEOM();! } ! else if( host == "localhost:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Second webpage\n" ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! ϦΫΤετϔομ͔ΒHostΛऔಘ HTTPMessage::getSingleOrEmpty( ϑΟʔϧυ໊ )Ͱ ϦΫΤετϔομʹઃఆ͞ΕͨΛऔಘ §14.23 Host A client MUST include a Host header field in all HTTP/1.1 request messages. http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html HTTP/1.1ͰHostඞਢͳͷͰ ۭจࣈྻ͕ฦͬͯདྷͨΒ400Ͱฦͯ͠OK -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( host == "www41050u.sakura.ne.jp:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "First webpage\n" ).sendWithEOM();! } ! else if( host == "localhost:8080" ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Second webpage\n" ).sendWithEOM();! } ! else tx.status( 400, "Bad Request" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! ޙonEOMͰฦ͢ίϯςϯπΛ ʹΑͬͯม͑Δ͚ͩ -
ҙ HostΫϥΠΞϯτͷࣗݾਃࠂ͔ͩΒ ؆୯ʹِͰ͖Δ $ telnet www41050u.sakura.ne.jp 8080! Trying xxx.xxx.xxx.xx...! Connected
to www41050u.sakura.ne.jp.! Escape character is '^]'.! GET / HTTP/1.1! Host: localhost:8080! ! HTTP/1.1 200 OK! Content-Type: text/plain! Date: Sat, 03 Oct 2015 15:35:57 GMT! Connection: keep-alive! Content-Length: 15! ! Second webpage ֎͖ΞυϨεͰΞΫηε ͖ΞυϨεΛࣗশ ͖ίϯςϯπ͕ฦͬͯ͠·ͬͨ! -
#include <boost/spirit/include/qi.hpp>! #include <boost/spirit/include/karma.hpp>! #include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>!
#include <proxygen/httpserver/ResponseBuilder.h>! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! const auto count_ = headers->getCookie( "count" );! if( count_.empty() ) count = 0;! else {! auto iter = count_.begin();! namespace qi = boost::spirit::qi;! if( !qi::parse( iter, count_.end(), qi::uint_, count ) ) ! count = 0;! } ! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! namespace karma = boost::spirit::karma;! std::string h, b;! ++count;! proxygen::ResponseBuilder tx( downstream_ );! if( ! karma::generate(! std::back_inserter( h ), "count=" << karma::uint_ <<! ";expires=Thu, 1-Jan-2030 00:00:00 GMT",! count! ) &&! karma::generate(! std::back_inserter( b ),! "You accessed " << karma::uint_ << " times" << karma::eol,! count! ) ! ) {! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.header( "Set-Cookie", h ).body( b ).sendWithEOM();! }! else tx.status( 500, "Internal Server Error" ).sendWithEOM();! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! uint32_t count;! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {{! folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP! }};! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
#include <boost/spirit/include/karma.hpp>! #include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>!
class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! const auto count_ = headers->getCookie( "count" );! if( count_.empty() ) count = 0;! else {! auto iter = count_.begin();! namespace qi = boost::spirit::qi;! if( !qi::parse( iter, count_.end(), qi::uint_, count ) ) ! count = 0;! } ! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! namespace karma = boost::spirit::karma;! std::string h, b;! ++count;! proxygen::ResponseBuilder tx( downstream_ );! if( ! karma::generate(! HTTPMessage::getCookie( ύϥϝλ໊ )Ͱ ΫϥΠΞϯτ͔Βಧ͍ͨCookieΛऔಘ -
auto iter = count_.begin();! namespace qi = boost::spirit::qi;! if( !qi::parse(
iter, count_.end(), qi::uint_, count ) ) ! count = 0;! } ! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! namespace karma = boost::spirit::karma;! std::string h, b;! ++count;! proxygen::ResponseBuilder tx( downstream_ );! if( ! karma::generate(! std::back_inserter( h ), "count=" << karma::uint_ <<! ";expires=Thu, 1-Jan-2030 00:00:00 GMT",! count! ) &&! karma::generate(! std::back_inserter( b ),! "You accessed " << karma::uint_ << " times" << karma::eol,! count! ) ! ) {! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.header( "Set-Cookie", h ).body( b ).sendWithEOM();! }! CookieΛૹΔํԿނ͔༻ҙ͞Ε͍ͯͳ͍ͷͰ ؾ߹͍ͰΈཱͯͯheader() -
$ curl -b cookie.db -c cookie.db http://www41050u.sakura.ne.jp:8080/! You accessed 1
times! $ curl -b cookie.db -c cookie.db http://www41050u.sakura.ne.jp:8080/! You accessed 2 times! $ curl -b cookie.db -c cookie.db http://www41050u.sakura.ne.jp:8080/! You accessed 3 times CookieΛͬͯ ԿͷΞΫηε͔ΛௐΔ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( is_tls ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Hello, World!\n" ).sendWithEOM();! } ! else {! tx.status( 301, "Moved Permanently" );! tx.header( "Location", "https://www41050u.sakura.ne.jp:8443/" );! tx.sendWithEOM();! } ! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! bool is_tls;! };! class factory : public proxygen::RequestHandlerFactory {! public:! void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::HTTP },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } -
void onServerStart() noexcept override {}! void onServerStop() noexcept override {}!
proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::HTTP },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! ฏจ༻ͷϙʔτͱผʹ TLS༻ͷϙʔτΛ։͚Δ -
};! int main( int argc, char* argv[] ) {! std::vector<
proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::HTTP },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } SSLContextConfigΛ࡞ͬͯ TLS༻ͷϙʔτͷํͷsslConfigsʹՃ͢Δ ͜ͷSSLͷઃఆΛ͏ϗετΛ SNIͷࢦఆ͕ແ͔ͬͨ߹ͷ σϑΥϧτʹ͢Δ SNI Server Name Indication Webαʔόʹෳͷ໊લͰΞΫηεग़དྷΔ࣌ʹ Ͳͷ໊લʹରԠ͢Δূ໌ॻ͕ཉ͍͔͠Λ αʔόʹ͑ΔΈ ͜Ε͕ແ͍ͱਖ਼͍͠ূ໌ॻ͕͑ͳͯ͘ TLSӽ͠ʹ໊લϕʔεόʔνϟϧϗετ͕ग़དྷͳ͍ -
};! int main( int argc, char* argv[] ) {! std::vector<
proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::HTTP },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! server.start();! return 0;! } SSLContextConfigΛ࡞ͬͯ TLS༻ͷϙʔτͷํͷsslConfigsʹՃ͢Δ αʔόূ໌ॻ ൿີ伴 ূ໌ॻͷύεϫʔυ -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( is_tls ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Hello, World!\n" ).sendWithEOM();! } ! else {! tx.status( 301, "Moved Permanently" );! tx.header( "Location", "https://www41050u.sakura.ne.jp:8443/" );! tx.sendWithEOM();! } ! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! ฏจ͔TLSܦ༝͔ HTTPMessage::isSecure()ͰผͰ͖Δ -
#include <proxygen/httpserver/ResponseBuilder.h>! class handler : public proxygen::RequestHandler {! public:! void
onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( is_tls ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Hello, World!\n" ).sendWithEOM();! } ! else {! tx.status( 301, "Moved Permanently" );! tx.header( "Location", "https://www41050u.sakura.ne.jp:8443/" );! tx.sendWithEOM();! } ! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! void requestComplete() noexcept override { delete this; }! void onError(proxygen::ProxygenError err) noexcept override {! delete this;! }! private:! ඞਢͰͳ͍͕ TLSͳWebαΠτʹฏจͰΞΫηε͕͋ͬͨ߹ TLSܦ༝ʹϦμΠϨΫτ͢Δͷ͕ ͓ߦّͷྑ͍WebαΠτͱ͞Ε͍ͯΔ -
13:55:02.906915 IP (tos 0x0, ttl 64, id 41559, offset 0,
flags [DF], proto TCP (6), length 60)! www41050u.sakura.ne.jp.58268 > www41050u.sakura.ne.jp.http-alt: Flags [S], cksum 0x3c87 (incorrect -> 0x684b), seq 2056417443, win 43690, options [mss 65495,sackOK,TS val 1027003124 ecr 0,nop,wscale 7], length 0! ! 0x0000: 4500 003c a257 4000 4006 5c0c 31d4 6c58! ! 0x0010: 31d4 6c58 e39c 1f90 7a92 70a3 0000 0000! ! 0x0020: a002 aaaa 3c87 0000 0204 ffd7 0402 080a! ! 0x0030: 3d36 d2f4 0000 0000 0103 0307! 13:55:02.906930 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)! www41050u.sakura.ne.jp.http-alt > www41050u.sakura.ne.jp.58268: Flags [S.], cksum 0x3c87 (incorrect -> 0x908a), seq 270579556, ack 2056417444, win 43690, options [mss 65495,sackOK,TS val 1027003124 ecr 1027003124,nop,wscale 7], length 0! ! 0x0000: 4500 003c 0000 4000 4006 fe63 31d4 6c58! ! 0x0010: 31d4 6c58 1f90 e39c 1020 b764 7a92 70a4! ! 0x0020: a012 aaaa 3c87 0000 0204 ffd7 0402 080a! ! 0x0030: 3d36 d2f4 3d36 d2f4 0103 0307! 13:55:02.906942 IP (tos 0x0, ttl 64, id 41560, offset 0, flags [DF], proto TCP (6), length 52)! www41050u.sakura.ne.jp.58268 > www41050u.sakura.ne.jp.http-alt: Flags [.], cksum 0x3c7f (incorrect -> 0x62cf), seq 1, ack 1, win 342, options [nop,nop,TS val 1027003124 ecr 1027003124], length 0! ! 0x0000: 4500 0034 a258 4000 4006 5c13 31d4 6c58! ͜ͷHello, World!͕ฦΔ·Ͱͷ௨৴Λ tcpdumpͰ؍ -
Flags [.], cksum 0x3c7f (incorrect -> 0x62cf), seq 1, ack
1, win 342, options [nop,nop,TS val 1027003124 ecr 1027003124], length 0! ! 0x0000: 4500 0034 a258 4000 4006 5c13 31d4 6c58! ! 0x0010: 31d4 6c58 e39c 1f90 7a92 70a4 1020 b765! ! 0x0020: 8010 0156 3c7f 0000 0101 080a 3d36 d2f4! ! 0x0030: 3d36 d2f4! 13:55:02.907163 IP (tos 0x0, ttl 64, id 41561, offset 0, flags [DF], proto TCP (6), length 143)! www41050u.sakura.ne.jp.58268 > www41050u.sakura.ne.jp.http-alt: Flags [P.], cksum 0x3cda (incorrect -> 0x7b94), seq 1:92, ack 1, win 342, options [nop,nop,TS val 1027003124 ecr 1027003124], length 91: HTTP, length: 91! ! GET / HTTP/1.1! ! Host: www41050u.sakura.ne.jp:8080! ! User-Agent: curl/7.43.0! ! Accept: */*! ! ! ! 0x0000: 4500 008f a259 4000 4006 5bb7 31d4 6c58! ! 0x0010: 31d4 6c58 e39c 1f90 7a92 70a4 1020 b765! ! 0x0020: 8018 0156 3cda 0000 0101 080a 3d36 d2f4! ! 0x0030: 3d36 d2f4 4745 5420 2f20 4854 5450 2f31! ! 0x0040: 2e31 0d0a 486f 7374 3a20 7777 7734 3130! ! 0x0050: 3530 752e 7361 6b75 7261 2e6e 652e 6a70! ! 0x0060: 3a38 3038 300d 0a55 7365 722d 4167 656e! ! 0x0070: 743a 2063 7572 6c2f 372e 3433 2e30 0d0a! ! 0x0080: 4163 6365 7074 3a20 2a2f 2a0d 0a0d 0a! 13:55:02.907175 IP (tos 0x0, ttl 64, id 26001, offset 0, flags [DF], ΫϥΠΞϯτ͔Βͷ ฏจϦΫΤετ -
Flags [.], cksum 0x3c7f (incorrect -> 0x6274), seq 1, ack
92, win 342, options [nop,nop,TS val 1027003124 ecr 1027003124], length 0! ! 0x0000: 4500 0034 6591 4000 4006 98da 31d4 6c58! ! 0x0010: 31d4 6c58 1f90 e39c 1020 b765 7a92 70ff! ! 0x0020: 8010 0156 3c7f 0000 0101 080a 3d36 d2f4! ! 0x0030: 3d36 d2f4! 13:55:02.907332 IP (tos 0x0, ttl 64, id 26002, offset 0, flags [DF], proto TCP (6), length 214)! www41050u.sakura.ne.jp.http-alt > www41050u.sakura.ne.jp.58268: Flags [P.], cksum 0x3d21 (incorrect -> 0xc00f), seq 1:163, ack 92, win 342, options [nop,nop,TS val 1027003124 ecr 1027003124], length 162: HTTP, length: 162! ! HTTP/1.1 301 Moved Permanently! ! Location: https://www41050u.sakura.ne.jp:8443/! ! Date: Sun, 04 Oct 2015 04:55:02 GMT! ! Connection: keep-alive! ! Content-Length: 0! ! ! ! 0x0000: 4500 00d6 6592 4000 4006 9837 31d4 6c58! ! 0x0010: 31d4 6c58 1f90 e39c 1020 b765 7a92 70ff! ! 0x0020: 8018 0156 3d21 0000 0101 080a 3d36 d2f4! ! 0x0030: 3d36 d2f4 4854 5450 2f31 2e31 2033 3031! ! 0x0040: 204d 6f76 6564 2050 6572 6d61 6e65 6e74! ! 0x0050: 6c79 0d0a 4c6f 6361 7469 6f6e 3a20 6874! ! 0x0060: 7470 733a 2f2f 7777 7734 3130 3530 752e! ! 0x0070: 7361 6b75 7261 2e6e 652e 6a70 3a38 3434! αʔό͔Βͷ ʮTLSͰܨ͗ͤʯϨεϙϯε -
Flags [.], cksum 0x3c7f (incorrect -> 0x61ca), seq 92, ack
163, win 350, options [nop,nop,TS val 1027003124 ecr 1027003124], length 0! ! 0x0000: 4500 0034 a25a 4000 4006 5c11 31d4 6c58! ! 0x0010: 31d4 6c58 e39c 1f90 7a92 70ff 1020 b807! ! 0x0020: 8010 015e 3c7f 0000 0101 080a 3d36 d2f4! ! 0x0030: 3d36 d2f4! 13:55:02.915656 IP (tos 0x0, ttl 64, id 22547, offset 0, flags [DF], proto TCP (6), length 60)! www41050u.sakura.ne.jp.50461 > www41050u.sakura.ne.jp.8443: Flags [S], cksum 0x3c87 (incorrect -> 0x04f9), seq 3768879855, win 43690, options [mss 65495,sackOK,TS val 1027003132 ecr 0,nop,wscale 7], length 0! ! 0x0000: 4500 003c 5813 4000 4006 a650 31d4 6c58! ! 0x0010: 31d4 6c58 c51d 20fb e0a4 8aef 0000 0000! ! 0x0020: a002 aaaa 3c87 0000 0204 ffd7 0402 080a! ! 0x0030: 3d36 d2fc 0000 0000 0103 0307! 13:55:02.915669 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60)! www41050u.sakura.ne.jp.8443 > www41050u.sakura.ne.jp.50461: Flags [S.], cksum 0x3c87 (incorrect -> 0xf1d1), seq 3389733079, ack 3768879856, win 43690, options [mss 65495,sackOK,TS val 1027003132 ecr 1027003132,nop,wscale 7], length 0! ! 0x0000: 4500 003c 0000 4000 4006 fe63 31d4 6c58! ! 0x0010: 31d4 6c58 20fb c51d ca0b 38d7 e0a4 8af0! ! 0x0020: a012 aaaa 3c87 0000 0204 ffd7 0402 080a! ! 0x0030: 3d36 d2fc 3d36 d2fc 0103 0307! ΫϥΠΞϯτ͔ΒͷTLSͷଓཁٻ -
! 0x0010: 31d4 6c58 c51d 20fb e0a4 8af0 ca0b 38d8!
! 0x0020: 8010 0156 3c7f 0000 0101 080a 3d36 d2fc! ! 0x0030: 3d36 d2fc! 13:55:02.927662 IP (tos 0x0, ttl 64, id 22549, offset 0, flags [DF], proto TCP (6), length 569)! www41050u.sakura.ne.jp.50461 > www41050u.sakura.ne.jp.8443: Flags [P.], cksum 0x3e84 (incorrect -> 0x4010), seq 1:518, ack 1, win 342, options [nop,nop,TS val 1027003144 ecr 1027003132], length 517! ! 0x0000: 4500 0239 5815 4000 4006 a451 31d4 6c58! ! 0x0010: 31d4 6c58 c51d 20fb e0a4 8af0 ca0b 38d8! ! 0x0020: 8018 0156 3e84 0000 0101 080a 3d36 d308! ! 0x0030: 3d36 d2fc 1603 0102 0001 0001 fc03 03ab! ! 0x0040: e5e2 86b6 2fb4 ee39 ea2b ff28 830b 307a! ! 0x0050: 807c f51a 6c3d 9012 6122 b87a b6a7 5a00! ! 0x0060: 00a0 c030 c02c c028 c024 c014 c00a 00a5! ! 0x0070: 00a3 00a1 009f 006b 006a 0069 0068 0039! ! 0x0080: 0038 0037 0036 0088 0087 0086 0085 c032! ! 0x0090: c02e c02a c026 c00f c005 009d 003d 0035! ! 0x00a0: 0084 c02f c02b c027 c023 c013 c009 00a4! ! 0x00b0: 00a2 00a0 009e 0067 0040 003f 003e 0033! ! 0x00c0: 0032 0031 0030 009a 0099 0098 0097 0045! ! 0x00d0: 0044 0043 0042 c031 c02d c029 c025 c00e! ! 0x00e0: c004 009c 003c 002f 0096 0041 0007 c012! ! 0x00f0: c008 0016 0013 0010 000d c00d c003 000a! ! 0x0100: 00ff 0100 0133 0000 001b 0019 0000 1677! ! 0x0110: 7777 3431 3035 3075 2e73 616b 7572 612e! ! 0x0120: 6e65 2e6a 7000 0b00 0403 0001 0200 0a00! ϓϦϚελγʔΫϨοτ -
[P.], cksum 0x3cb2 (incorrect -> 0x8f50), seq 929:980, ack 836,
win 359, options [nop,nop,TS val 1027003148 ecr 1027003145], length 51! ! 0x0000: 4500 0067 ea26 4000 4006 1412 31d4 6c58! ! 0x0010: 31d4 6c58 20fb c51d ca0b 3c78 e0a4 8e33! ! 0x0020: 8018 0167 3cb2 0000 0101 080a 3d36 d30c! ! 0x0030: 3d36 d309 1403 0300 0101 1603 0300 284b! ! 0x0040: 54b2 7c66 e641 15ea b1ac 4c0f 5ee4 6dad! ! 0x0050: 2c45 2228 f3d8 6acf 9b11 760c 9b53 6789! ! 0x0060: 5346 75cd d26f e0! 13:55:02.931226 IP (tos 0x0, ttl 64, id 22552, offset 0, flags [DF], proto TCP (6), length 172)! www41050u.sakura.ne.jp.50461 > www41050u.sakura.ne.jp.8443: Flags [P.], cksum 0x3cf7 (incorrect -> 0xdfd4), seq 836:956, ack 980, win 356, options [nop,nop,TS val 1027003148 ecr 1027003148], length 120! ! 0x0000: 4500 00ac 5818 4000 4006 a5db 31d4 6c58! ! 0x0010: 31d4 6c58 c51d 20fb e0a4 8e33 ca0b 3cab! ! 0x0020: 8018 0164 3cf7 0000 0101 080a 3d36 d30c! ! 0x0030: 3d36 d30c 1703 0300 739b 9377 77a5 eb88! ! 0x0040: 4cfa a634 de4e 8622 e62b 9866 c908 d0ab! ! 0x0050: d71b a211 f499 df04 359c 1e7f a782 d889! ! 0x0060: ee82 2248 1771 89dd 5b4d 9b3a 125b 18dd! ! 0x0070: 58b1 ad18 0b0a b3c1 4e19 2bcb 7a57 c007! ! 0x0080: b65d b991 fc89 33fb 61be 19cc 9904 b521! ! 0x0090: 83b1 e8c0 2807 773f 2ae6 bd8d 60e1 4442! ! 0x00a0: 2e79 b164 fa63 4955 85ce cdce! 13:55:02.931411 IP (tos 0x0, ttl 64, id 59943, offset 0, flags [DF], proto TCP (6), length 221)! ҉߸Խ͞ΕͯಡΊͳ͘ͳ͍ͬͯΔ -
bool is_tls;! };! class factory : public proxygen::RequestHandlerFactory {! public:!
void onServerStart() noexcept override {}! void onServerStop() noexcept override {}! proxygen::RequestHandler* onRequest(! proxygen::RequestHandler*, proxygen::HTTPMessage*! ) noexcept override { return new handler(); }! };! int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig > IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::SPDY },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! ͳΜͱ! ProxygenSPDYʹରԠ͍ͯ͠Δ ͜ͷΞυϨεͰ 41%:ͷଓΛͪड͚Δ -
NPN͕͋Δ࣌ ΫϥΠΞϯτ αʔό ͜ͷ҉߸͕͑ΔΑ (ͱ͜ΖͰϓϩτίϧԿ͍͚Δ?) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (HTTP/1.1͔SPDY/3͕͍͚Δͥ) ४උͰ͖ͨΘ
(Μ͡ΌSPDY/3ͰΑΖ) ४උͰ͖ͨΘ 伴ੜ 伴ੜ αʔό͕ ຊ͔֬ೝ ϓϩτίϧ ܾఆ -
int main( int argc, char* argv[] ) {! std::vector< proxygen::HTTPServer::IPConfig
> IPs = {! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8080, true ),! proxygen::HTTPServer::Protocol::HTTP },! { folly::SocketAddress( "www41050u.sakura.ne.jp", 8443, true ),! proxygen::HTTPServer::Protocol::SPDY },! };! wangle::SSLContextConfig ssl;! ssl.isDefault = true;! ssl.setCertificate(! "./server.crt",! "./server.key",! "./password"! );! std::list< std::string > nps;! nps.push_back( "spdy/3.1-hpack" );! nps.push_back( "spdy/3.1" );! nps.push_back( "spdy/3" );! nps.push_back( "http/1.1" );! ssl.setNextProtocols( nps );! IPs.back().sslConfigs.push_back( ssl );! proxygen::HTTPServerOptions options;! options.handlerFactories =! proxygen::RequestHandlerChain().addThen< factory >().build();! proxygen::HTTPServer server( std::move( options ) );! server.bind( IPs );! Proxygen͔ΒOpenSSLʹ NPNΛૹΔΑ͏ʹࢦࣔ͢Δ SPDY͍͚ΔΑ! -
#include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! class handler
: public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr<proxygen::HTTPMessage> headers! ) noexcept override {! is_tls = headers->isSecure();! std::cout << int( headers->getPriority() ) << std::endl;! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {}! void onEOM() noexcept override {! proxygen::ResponseBuilder tx( downstream_ );! if( is_tls ) { ! tx.status( 200, "OK" ).header( "Content-Type", "text/plain" );! tx.body( "Hello, World!\n" ).sendWithEOM();! } ! else {! tx.status( 301, "Moved Permanently" );! tx.header( "Location", "https://www41050u.sakura.ne.jp:8443/" );! tx.sendWithEOM();! } ! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {}! SPDYͰ௨৴தϦΫΤετͷ HTTPMessage::getPriority()Ͱ༏ઌ͕औΕΔ ./spdy_sample 0! 2 ຊମ͘Εɺࠓ͙͢ GBWJDPO͘Εɺͯ͘ྑ͍ -
Comet ΫϥΠΞϯτ αʔό αʔό௨͖͕͢དྷΔ·Ͱ ΫϥΠΞϯτ͔ΒͷϦΫΤετʹฦ͠ͳ͍ ΫϥΠΞϯτϨεϙϯε͕དྷͨΒ͙͢ʹϦΫΤετ͢Δ ৽ண͋Δ? ࠓདྷͨ ʜ ৽ண
͜ΕϦΫΤετͰͳ͍ ͜ΕϨεϙϯεͰͳ͍ -
#include <cstdio>! #include <cstdlib>! #include <iostream>! #include <unordered_map>! #include <boost/filesystem.hpp>!
#include <boost/range/iterator_range.hpp>! #include <sys/mman.h>! #include <sys/stat.h>! #include <fcntl.h>! #include <unistd.h>! #include <rapidjson/rapidjson.h>! ! #include <folly/Memory.h>! #include <folly/Portability.h>! #include <folly/io/async/EventBaseManager.h>! #include <proxygen/httpserver/HTTPServer.h>! #include <proxygen/httpserver/RequestHandlerFactory.h>! #include <proxygen/httpserver/RequestHandler.h>! #include <proxygen/httpserver/ResponseBuilder.h>! #include <proxygen/httpserver/WebSocket.h>! ! struct no_such_file {};! ! class static_files {! public:! static_files() {}! static_files( const static_files& ) = delete;! static_files( static_files&& ) = delete;! static_files &operator=( const static_files& ) = delete;! WebSocketΛ͏αʔό ͍ͷͰޙͰgithub͋ͨΓʹ্͓͖͛ͯ·͢ -
std::unordered_map< const proxygen::RequestHandler*, connection_state > sockets;! std::mutex guard;! };! class
hello : public proxygen::RequestHandler {! public:! explicit hello( const static_files &files_, broadcaster &broad_ ) : files( files_ ), broad( broad_ ), is_ws( false ) {}! void onRequest( std::unique_ptr<proxygen::HTTPMessage> headers ) noexcept override {! if(proxygen::WebSocket::isWebSocketRequest(*headers)) {! broad.open( this, std::move(proxygen::WebSocket::acceptWebSocket(downstream_, *headers, std::bind( &broadcaster::receive, &broad, this, std::placeholders::_1))) );! is_ws = true;! }! else! file = files[ headers->getPath() ];! }! void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {! if(is_ws) {! broad.processData( this, std::move(body));! }! }! void onEOM() noexcept override {! if(is_ws)! return;! proxygen::ResponseBuilder tx( downstream_ );! if( file ) {! tx.status( 200, "OK" )! onRequestͰ WebSocketͷUPGRADE͔Λௐͯ WebSocketͩͬͨΒ proxygen::WebSocket::acceptWebSocket ͜ͷ࣌WebSocketͷΠϕϯτͰݺͼग़͞ΕΔ ίʔϧόοΫΛઃఆ͢Δ -
for( auto &receiver: receivers )! receiver->sendFrame( frame->frameType, folly::IOBuf::maybeCopyBuffer( data ),
frame->endOfMessage );! return true;! }! void processData( const proxygen::RequestHandler*k, std::unique_ptr<folly::IOBuf> body ) {! auto search_result = sockets.find( k );! std::shared_ptr< proxygen::WebSocket > socket;! {! std::lock_guard< std::mutex > lock( guard );! if( search_result != sockets.end() ) {! if( search_result->second.message_revision == 0ull )! search_result->second.message_revision = ++revision;! socket = search_result->second.socket;! }! }! if( socket ) socket->processData( std::move( body ) );! }! private:! revision_t revision;! std::unordered_map< const proxygen::RequestHandler*, connection_state > sockets;! std::mutex guard;! };! class hello : public proxygen::RequestHandler {! public:! explicit hello( const static_files &files_, broadcaster &broad_ ) : files( files_ ), broad( broad_ ), is_ws( false ) {}! onBodyͰWebSocketͷσʔλ͕དྷͨΒ WebSocketͷΠϯελϯεʹ·Θ͢ -
void onBody(std::unique_ptr<folly::IOBuf> body) noexcept override {! if(is_ws) {! broad.processData( this,
std::move(body));! }! }! void onEOM() noexcept override {! if(is_ws)! return;! proxygen::ResponseBuilder tx( downstream_ );! if( file ) {! tx.status( 200, "OK" )! .header( "Hoge", "fuga" )! .header( "Content-Type", file->first )! .body( file->second )! .sendWithEOM();! }! else {! tx.status( 404, "File Not Found" )! .header( "Hoge", "fuga" )! .body( "" )! .sendWithEOM();! }! }! void onUpgrade(proxygen::UpgradeProtocol proto) noexcept override {! }! void requestComplete() noexcept override {! if(is_ws)! broad.close( this );! delete this;! WebSocketͰͬͨηογϣϯ onEOMͰԿฦ͞ͳ͍ -
std::unique_ptr<proxygen::WebSocketFrame> frame ) {! const std::string data = std::string( frame->payload->data(),
frame- >payload->tail() );! std::vector< std::shared_ptr< proxygen::WebSocket > > receivers;! if( !data.empty() ) {! std::lock_guard< std::mutex > lock( guard );! auto search_result = sockets.find( k );! if( search_result != sockets.end() ) {! revision_t highest_revision = search_result- >second.message_revision;! for( auto &socket: sockets )! if( socket.second.joined_at < highest_revision )! receivers.emplace_back( socket.second.socket );! }! if( frame->endOfMessage )! search_result->second.message_revision = 0ull;! }! for( auto &receiver: receivers )! receiver->sendFrame( frame->frameType, folly::IOBuf::maybeCopyBuffer( data ), frame->endOfMessage );! return true;! }! void processData( const proxygen::RequestHandler*k, std::unique_ptr<folly::IOBuf> body ) {! auto search_result = sockets.find( k );! std::shared_ptr< proxygen::WebSocket > socket;! {! std::lock_guard< std::mutex > lock( guard );! if( search_result != sockets.end() ) {! if( search_result->second.message_revision == 0ull )! SendFrame()ͰΫϥΠΞϯτʹσʔλΛૹΔ -
͜͜Ͱ ඞཁͳը૾͕ ͔Δ ΫϥΠΞϯτ αʔό ͘Ε ͓લ࣍ʹ ը૾ͱ$44͕ཉ͍͠ͱ ݴ͍ग़ͩ͢Ζ͏ ը૾Λ
(&5͠Α͏ͱ ࢥͬͨΒ Կނ͔͏͋Δ SPDYϦΫΤετ͞ΕΔલʹϨεϙϯεΛฦ͢ ServerPushͰ͜ͷΛղܾ͢Δ -
/**! * @return true iff this transaction can be used
to push resources to! * the remote side.! */! bool supportsPushTransactions() const {! return direction_ == TransportDirection::DOWNSTREAM &&! transport_.getCodec().supportsPushTransactions();! }! ! /** ! * Create a new pushed transaction associated with this transaction,! * and assign the given handler and priority.! *! * @return the new transaction for the push, or nullptr if a new push! * transaction is impossible right now.! */! virtual HTTPTransaction* newPushedTransaction(! HTTPPushTransactionHandler* handler, uint8_t priority) {! if (isEgressEOMSeen()) {! return nullptr;! } ! auto txn = transport_.newPushedTransaction(id_, handler, priority);! if (txn) {! pushedTransactions_.insert(txn->getID());! } ! return txn; ! }! ! /** ! * Invoked by the session (upstream only) when a new pushed transaction! Proxygenͷ෦ͷਵॴʹServer PushͷҝͱࢥΘΕΔ ͕ؔ༻ҙ͞Ε͍ͯΔ -
XBOHMF )551$PEFD 41%:$PEFD )5515SBOTBDUJPO )5514FSWFS ඇಉظ*0 ݸʑͷϓϩτίϧͰͷ )551ϝοηʔδͷૢ࡞ ϓϩτίϧඇґଘͷ )551ϝοηʔδͷૢ࡞
͜ͷลΓʹ Server Pushͷ࣮Β͖͕͋͠Δ HTTP Server͔ΒServer PushΛ ୟ͘Έ͕ݟͨΒͳ͍ ֎͖ͷ"1* -
Trailer ϔομ ຊจ &OEPG.FTTBHF τϨΠϥ HTTPϨεϙϯεͷ ϔομͷҰ෦Λ ຊจΑΓޙΖʹ ॻ͘Έ ຊจੜͯ͠Έͳ͍ͱ
͕ఆ·Βͳ͍ νΣοΫαϜʹ͏ -
void onTrailersComplete(HTTPCodec::StreamID streamID,! std::unique_ptr<HTTPHeaders> trailers) override;! void onMessageComplete(HTTPCodec::StreamID streamID, bool
upgrade) override;! void onError(HTTPCodec::StreamID streamID,! const HTTPException& error, bool newTxn) override;! void onAbort(HTTPCodec::StreamID streamID,! ErrorCode code) override;! void onGoaway(uint64_t lastGoodStreamID,! ErrorCode code) override;! void onPingRequest(uint64_t uniqueID) override;! void onPingReply(uint64_t uniqueID) override;! void onWindowUpdate(HTTPCodec::StreamID stream, uint32_t amount) override;! …! // HTTPTransaction::Transport methods! void pauseIngress(HTTPTransaction* txn) noexcept override;! void resumeIngress(HTTPTransaction* txn) noexcept override;! void transactionTimeout(HTTPTransaction* txn) noexcept override;! void sendHeaders(HTTPTransaction* txn,! const HTTPMessage& headers,! HTTPHeaderSize* size) noexcept override;! size_t sendBody(HTTPTransaction* txn, std::unique_ptr<folly::IOBuf>,! bool includeEOM) noexcept override;! size_t sendChunkHeader(HTTPTransaction* txn,! size_t length) noexcept override;! size_t sendChunkTerminator(HTTPTransaction* txn) noexcept override;! size_t sendTrailers(HTTPTransaction* txn,! const HTTPHeaders& trailers) noexcept override;! size_t sendEOM(HTTPTransaction* txn) noexcept override;! Trailerૹ৴ͷҝͷؔͱࢥ͖͕͠ HTTPSessionͷதʹ͋Δ -
XBOHMF )551$PEFD 41%:$PEFD )5514FTTJPO )5514FSWFS ඇಉظ*0 ݸʑͷϓϩτίϧͰͷ )551ϝοηʔδͷૢ࡞ ϓϩτίϧඇґଘͷ )551ϝοηʔδͷૢ࡞
֎͖ͷ"1* ͜ͷลΓʹ Trailerͷ࣮Β͖͕͋͠Δ HTTP ServerͷResponseBuilderͰ TrailerΛ࡞ΔΈ͕ݟͨΒͳ͍ -
/**! * An implementation of the framing layer for HTTP/2.
Instances of this! * class must not be used from multiple threads concurrently.! */! class HTTP2Codec: public HTTPParallelCodec, HeaderCodec::StreamingCallback {! public:! void onHeader(const std::string& name,! const std::string& value) override;! void onHeadersComplete() override;! void onDecodeError(HeaderDecodeError decodeError) override;! ! explicit HTTP2Codec(TransportDirection direction);! ~HTTP2Codec() override;! ! // HTTPCodec API! CodecProtocol getProtocol() const override {! return CodecProtocol::HTTP_2;! }! ! size_t onIngress(const folly::IOBuf& buf) override;! size_t generateConnectionPreface(folly::IOBufQueue& writeBuf) override;! void generateHeader(folly::IOBufQueue& writeBuf,! StreamID stream,! const HTTPMessage& msg,! StreamID assocStream = 0,! bool eom = false,! HTTPHeaderSize* size = nullptr) override;! size_t generateBody(folly::IOBufQueue& writeBuf,! StreamID stream,! HTTP/2ͷϦΫΤετΛύʔεͨ͠Γ ϨεϙϯεΛੜ͢Δ HTTP2Codec -
NPN ΫϥΠΞϯτ αʔό ͜ͷ҉߸͕͑ΔΑ (ͱ͜ΖͰϓϩτίϧԿ͍͚Δ?) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (HTTP/1.1͔SPDY/3͕͍͚Δͥ) ४උͰ͖ͨΘ
(Μ͡ΌSPDY/3ͰΑΖ) ४උͰ͖ͨΘ 伴ੜ 伴ੜ αʔό͕ ຊ͔֬ೝ ϓϩτίϧ ܾఆ -
ALPN ͜ͷ҉߸͕͑ΔΑ (Զ࣮HTTP/2͍͚ΔΜͩΑͶ) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (͡Ό͋HTTP/2ͰΑΖ) ४උͰ͖ͨΘ ४උͰ͖ͨΘ 伴ੜ
伴ੜ αʔό͕ ຊ͔֬ೝ ϓϩτίϧ ܾఆ ΫϥΠΞϯτ αʔό -
ALPN ͜ͷ҉߸͕͑ΔΑ (Զ࣮HTTP/2͍͚ΔΜͩΑͶ) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (͡Ό͋HTTP/2ͰΑΖ) ४උͰ͖ͨΘ ४උͰ͖ͨΘ 伴ੜ
伴ੜ αʔό͕ ຊ͔֬ೝ ϓϩτίϧ ܾఆ ΫϥΠΞϯτ αʔό ͑Δϓϩτίϧ͕ແ͔ͬͨ߹ʹ TLSͷ伴ੜʹೖΔલʹଓΛΕΔ