Slide 1

Slide 1 text

PROXYGEN NAOMASA MATSUBAYASHI

Slide 2

Slide 2 text

@fadis_ Twitter Github Speakerdeck https://speakerdeck.com/fadis https://github.com/Fadis/ NAOMASA MATSUBAYASHI ීஈ͸େࡕͰήʔϜ࡞ͬͯ·͢

Slide 3

Slide 3 text

C++Ͱ WebΞϓϦέʔγϣϯͷαʔό Λॻ͖ͨ͘ͳͬͨΒ

Slide 4

Slide 4 text

ࣗྗͰHTTPΛ஻Δ? ΫϥΠΞϯτ αʔό HTTP/1.0 200 OK! Date: Mon, 21 Sep 2015 11:40:04 GMT! Content-Length: 14! ! Hello, World! GET / HTTP/1.0

Slide 5

Slide 5 text

ΞοϋΠɺεϛϚηϯʜ ΫϥΠΞϯτ αʔό GET / HTTP/1.1! Host: example.com! Connection: Upgrade, HTTP2-Settings! Upgrade: h2c 1! HTTP2-Settings: … ਖ਼͘͠HTTPͰձ࿩͢Δͷ͸೉͍͠

Slide 6

Slide 6 text

ਖ਼͍͠HTTPΛ஻Δ෦෼ͱ ΞϓϦέʔγϣϯຊମΛ෼཭͠Α͏ WebϑϨʔϜϫʔΫ

Slide 7

Slide 7 text

C++Ͱ࢖͑ΔWebϑϨʔϜϫʔΫ CppCMS cpp-netlib IUUQDQQDNTDPN IUUQDQQOFUMJCPSH Proxygen IUUQTHJUIVCDPNGBDFCPPLQSPYZHFO QHttpServer IUUQTHJUIVCDPNOJLIJMNRIUUQTFSWFS

Slide 8

Slide 8 text

IUUQTDPEFGBDFCPPLDPNQPTUT

Slide 9

Slide 9 text

Facebook͕ ಉࣾͷαʔϏεΛ࣮૷͢Δҝʹ࡞ͬͨWebϑϨʔϜϫʔΫ 2014೥11݄ʹ3৚߲BSDϥΠηϯεͰ ΦʔϓϯιʔεԽ͞Εͨ HTTP/1.x SPDY/2 SPDY/3.x HPACK TLS౳ʹରԠ HTTP/2ͷαϙʔτ͸ݱࡏਐߦத

Slide 10

Slide 10 text

Hello, World!Λฦ͢ WebαʔόΛॻ͍ͯΈΑ͏

Slide 11

Slide 11 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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;! }

Slide 12

Slide 12 text

};! 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Λࢦఆ ໊લղܾΛڐՄ

Slide 13

Slide 13 text

};! 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ͷΠϯελϯεΛ࡞Δ

Slide 14

Slide 14 text

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()͸αʔό͕ఀࢭ͢Δ·ͰฦΒͳ͍

Slide 15

Slide 15 text

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Λܧঝ ϦΫΤετ͕དྷͨ࣌ʹߦ͏ॲཧ ϦΫΤετϋϯυϥϑΝΫτϦ

Slide 16

Slide 16 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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Λܧঝ

Slide 17

Slide 17 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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ϦΫΤετͷ ϔομ͕ಧ͍ͨ࣌఺Ͱݺ͹ΕΔ

Slide 18

Slide 18 text

HTTPϦΫΤετͷߏ଄ ϔομ ຊจ &OEPG.FTTBHF ϦΫΤετͷछྨ΍ ෇ਵ͢Δύϥϝλ POSTͰαʔόʹૹΔ σʔλ౳ ຊจͷऴྃΛදۭ͢ߦ

Slide 19

Slide 19 text

ϔομ ຊจ &OEPG.FTTBHF ͜͜·Ͱड৴ͨ͠Β onRequest

Slide 20

Slide 20 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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ϦΫΤετΛ શͯड৴ͨ࣌͠఺Ͱݺ͹ΕΔ

Slide 21

Slide 21 text

ϔομ ຊจ &OEPG.FTTBHF ͜͜·Ͱड৴ͨ͠Β onEOM

Slide 22

Slide 22 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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ϦΫΤετͷ ຊจΛड৴ͨ࣌͠఺Ͱݺ͹ΕΔ

Slide 23

Slide 23 text

ϔομ ຊจ &OEPG.FTTBHF ͜͜·Ͱड৴ͨ͠Β onBody ͦΕͬͯ onEOMͱ ҰॹͳͷͰ͸? ͜͜·Ͱड৴ͨ͠Β onEOM

Slide 24

Slide 24 text

ϔομ &OEPG.FTTBHF શମͷ௕͕͞෼͔Βͳͯ͘΋ ຊจΛૹΓ࢝ΊΔࣄ͕Ͱ͖Δ νϟϯΫ νϟϯΫ νϟϯΫ νϟϯΫసૹ HTTPͷຊจ͸ ෳ਺ʹ෼ׂͯ͠ ૹΔ͜ͱ͕Ͱ͖Δ ϔομʹຊจͷ௕͞Λ ॻ͘୅ΘΓʹ νϟϯΫʹνϟϯΫͷ௕͞Λॻ͘

Slide 25

Slide 25 text

ϔομ &OEPG.FTTBHF νϟϯΫ νϟϯΫ νϟϯΫ ͜͜·Ͱड৴ͨ͠Β onBody ͜͜΋ ͬͪ͜΋ onBody͸ෳ਺ճݺ͹ΕΔՄೳੑ͕͋Δ

Slide 26

Slide 26 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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ͩͬͨ৔߹ʹݺ͹ΕΔ

Slide 27

Slide 27 text

UPGRADE HTTP/1.1Ͱ௥Ճ͞Εͨ ผͷϓϩτίϧʹ੾Γସ͑ΔҝͷϦΫΤετ ࠓͷͱ͜Ζ WebSocketͱHTTP/2(ฏจ൛)͕࢖͍ͬͯΔ

Slide 28

Slide 28 text

void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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 ΫϥΠΞϯτଆ͔Β੾அ͞ΕΔ౳ Ϩεϙϯεͷૹ৴׬ྃ·Ͱ౸ୡग़དྷͳ͘ͳͬͨΒ ݺ͹ΕΔ

Slide 29

Slide 29 text

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͕ੜϙΠϯλ͔͠ѲΕͳ͍ͷͰ ͜͏͢Δ͔͠ͳ͍

Slide 30

Slide 30 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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()Ͱ ϨεϙϯεΛऴྃͤ͞Δ

Slide 31

Slide 31 text

$ 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Ͱ઀ଓͯ͠ΈΑ͏ Ϩεϙϯε͕དྷͨ!

Slide 32

Slide 32 text

tx.body( "Hello, World!" ).sendWithEOM(); tx.body( "hoge" ).send();! tx.body( "fuga" ).send();! tx.body( "piyo" ).send();! tx.body( "foo" ).sendWithEOM(); send()Λ࢖͏ͱνϟϯΫసૹʹͳΔ

Slide 33

Slide 33 text

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! ! νϟϯΫ

Slide 34

Slide 34 text

public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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 Λ௥Ճ

Slide 35

Slide 35 text

$ 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

Slide 36

Slide 36 text

ѹॖ HTTP͸ϨεϙϯεͷຊจΛ deflate΍gzipͰѹॖͯ͠ૹΔࣄ͕ग़དྷΔ Proxygenʹ͸ gzipʹΑΔѹॖ͕࠷ॳ͔Β༻ҙ͞Ε͍ͯΔ

Slide 37

Slide 37 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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;! }

Slide 38

Slide 38 text

public:! void onRequest(! std::unique_ptr headers! ) noexcept override {}! void onBody(std::unique_ptr 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ͷ’[’ େ͖ͳຊจͩ!ѹॖ͠Α͏!

Slide 39

Slide 39 text

) 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

Slide 40

Slide 40 text

) 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

Slide 41

Slide 41 text

) 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Λ౉͢ͱѹॖ͕ࣦഊ͠ αʔό͕Τϥʔऴྃ͢Δ(ͭ·Γઃఆඞਢ)

Slide 42

Slide 42 text

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͕͜ΕΒʹ߹க͢Δ৔߹ͷΈ ѹॖΛߦ͏

Slide 43

Slide 43 text

$ 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

Slide 44

Slide 44 text

$ 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Ͱѹॖ͞Ε͍ͯΔ

Slide 45

Slide 45 text

ύεʹΑͬͯҧ͏ϨεϙϯεΛฦͦ͏ http://example.com/hoge/fuga ͜ͷ෦෼

Slide 46

Slide 46 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr 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;! }

Slide 47

Slide 47 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr 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()Ͱ ύεΛจࣈྻͰऔಘ

Slide 48

Slide 48 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! path = headers->getPath();! }! void onBody(std::unique_ptr 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Ͱฦ͢ίϯςϯπΛ ύεʹΑͬͯม͑Δ͚ͩ

Slide 49

Slide 49 text

$ 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. ύεʹΑͬͯ ҟͳΔ Ϩεϙϯε

Slide 50

Slide 50 text

http://example.com/hoge/fuga?piyo=1 ͜ͷ෦෼ ΫΤϦʹΑͬͯҧ͏ϨεϙϯεΛฦͦ͏

Slide 51

Slide 51 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr 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;! }

Slide 52

Slide 52 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr 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()Ͱ ஋ΛจࣈྻͰऔಘ

Slide 53

Slide 53 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! arg = headers->getDecodedQueryParam( "hoge" );! }! void onBody(std::unique_ptr 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Ͱฦ͢ίϯςϯπΛ ஋ʹΑͬͯม͑Δ͚ͩ

Slide 54

Slide 54 text

$ 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. ΫΤϦʹΑͬͯ ҟͳΔ Ϩεϙϯε

Slide 55

Slide 55 text

http://example.com/ ͜ͷ෦෼ ϗετ໊ʹΑͬͯҧ͏ϨεϙϯεΛฦͦ͏ ॴҦ໊લϕʔεόʔνϟϧϗετ

Slide 56

Slide 56 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr 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;! }

Slide 57

Slide 57 text

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;! } ෳ਺ͷϗετ໊͔Βͷ ઀ଓΛड͚෇͚ΔΑ͏ʹ͢Δ

Slide 58

Slide 58 text

#include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr 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

Slide 59

Slide 59 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! host = headers->getHeaders().getSingleOrEmpty( "Host" );! }! void onBody(std::unique_ptr 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Ͱฦ͢ίϯςϯπΛ ஋ʹΑͬͯม͑Δ͚ͩ

Slide 60

Slide 60 text

$ curl http://www41050u.sakura.ne.jp:8080/! First webpage! $ curl http://localhost:8080/ Second webpage ϗετ໊ʹΑͬͯҧ͏݁Ռ͕ฦͬͯ͘Δ

Slide 61

Slide 61 text

஫ҙ 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 ֎޲͖ΞυϨεͰΞΫηε ಺޲͖ΞυϨεΛࣗশ ಺޲͖ίϯςϯπ͕ฦͬͯ͠·ͬͨ!

Slide 62

Slide 62 text

HTTPMessage::getClientAddress() ઀ଓ͖ͯͨ͠ΫϥΠΞϯτͷΞυϨεΛಘΔ HTTPMessage::getDstAddress() ઀ଓΛड͚෇͚ͨαʔόͷΞυϨεΛಘΔ ಛఆͷϗετҎ֎͔Β ΞΫηεͤͨ͘͞ͳ͍৔߹͸ ͜ΕΒͷ৘ใΛ࢖ͬͯ·͍ͣϦΫΤετΛऽΔ

Slide 63

Slide 63 text

Cookie ΫϥΠΞϯτ αʔό ʮ͓લͷID͸hogeͳʯ ʮhogeͷਓͰ͢ʯ ʮ௨ͬͯΑ͠ʯ ΫϥΠΞϯτʹ஋Λอଘ͓ͯ͘͠࢓૊Έ IPHF

Slide 64

Slide 64 text

#include ! #include ! #include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr 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 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_ < 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;! }

Slide 65

Slide 65 text

#include ! #include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr 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 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Λऔಘ

Slide 66

Slide 66 text

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 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_ <

Slide 67

Slide 67 text

$ 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Λ࢖ͬͯ Կ౓໨ͷΞΫηε͔Λௐ΂Δ

Slide 68

Slide 68 text

TLS ΫϥΠΞϯτ αʔό ʮxxxxxxxʯ ʮxxxxxxxʯ ωΰγΤʔγϣϯ ѱҙ͋Δୈࡾऀ

Slide 69

Slide 69 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr 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;! }

Slide 70

Slide 70 text

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༻ͷϙʔτΛ։͚Δ

Slide 71

Slide 71 text

};! 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ӽ͠ʹ໊લϕʔεόʔνϟϧϗετ͕ग़དྷͳ͍

Slide 72

Slide 72 text

};! 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ʹ௥Ճ͢Δ αʔόূ໌ॻ ൿີ伴 ূ໌ॻͷύεϫʔυ

Slide 73

Slide 73 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr 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()Ͱ൑ผͰ͖Δ

Slide 74

Slide 74 text

#include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! is_tls = headers->isSecure();! }! void onBody(std::unique_ptr 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αΠτͱ͞Ε͍ͯΔ

Slide 75

Slide 75 text

$ curl -L --insecure http://www41050u.sakura.ne.jp:8080! Hello, World! ϦμΠϨΫτΛḷΔΑ͏ʹࢦࣔ ΦϨΦϨূ໌ॻ͚ͩͲ ؾʹͤͣܨ͙Α͏ࢦࣔ (ͪΌΜͱͨ͠ূ໌ॻΛ࢖͏৔߹͸ෆཁ)

Slide 76

Slide 76 text

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Ͱ؍࡯

Slide 77

Slide 77 text

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], ΫϥΠΞϯτ͔Βͷ ฏจϦΫΤετ

Slide 78

Slide 78 text

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Ͱܨ͗௚ͤʯϨεϙϯε

Slide 79

Slide 79 text

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ͷ઀ଓཁٻ

Slide 80

Slide 80 text

! 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! ϓϦϚελγʔΫϨοτ

Slide 81

Slide 81 text

[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)! ҉߸Խ͞ΕͯಡΊͳ͘ͳ͍ͬͯΔ

Slide 82

Slide 82 text

SPDY Google͕։ൃͨ͠ HTTP/1.1ʹ୅ΘΔϓϩτίϧ SPDY/3.1·Ͱ࡞ΒΕͨޙ SPDY/4͸HTTP/2ʹ౷߹͞Εͨ ͢ͽʔͰ͌ʔ

Slide 83

Slide 83 text

HTTP/1.1ͷԿ͕͍͚ͳ͔ͬͨͷ͔ )5.- ελΠϧγʔτ ը૾ +BWB4DSJQU ಈը 9.-)UUQ3FRVFTU ࠓ೔ͷWeb͸HTML͚ͩͰ׬݁͢Δࣄ͸كͰ ଓ͚͍ͯΖ͍Ζͳ෺ΛGET͢Δඞཁ͕͋Δ

Slide 84

Slide 84 text

ΫϥΠΞϯτ αʔό ͘Ε ͘Ε ͘Ε ͕࣌ؒ ͔͔Γ͗͢Δ RTT

Slide 85

Slide 85 text

ΫϥΠΞϯτ αʔό ͘Ε ͘Ε ͘Ε HTTP͸ϦΫΤετͱϨεϙϯεΛ ަޓʹ౤͛͋͏ϓϩτίϧͳҝ 1ຊͷηογϣϯͰ͜ΕΛ࣮ݱͰ͖ͳ͍ ͜͏͍ͨ͠

Slide 86

Slide 86 text

ड͚औΓ͍ͨ෺ͷ਺͚ͩηογϣϯΛுΕ͹ ϦΫΤετΛ౤͛ͳ͕Βड৴ग़དྷΔΑ ΫϥΠΞϯτ αʔό ΛૹΔ༻ηογϣϯ ΛૹΔ༻ηογϣϯ ΛૹΔ༻ηογϣϯ Ұੲલͷϒϥ΢βͰྲྀߦͬͨςΫχοΫ

Slide 87

Slide 87 text

͍͚ͯͳ͍఺ େྔʹுΒΕͨηογϣϯ͸ ޓ͍Λ஌Βͳ͍ҝ ద੾ͳ2P4͕࣮ݱग़དྷͳ͍ ͍͚ͯͳ͍఺ ͦ΋ͦ΋5$1ͷηογϣϯ਺͸ γεςϜͷݶΒΕͨࢿݯ ड͚औΓ͍ͨ෺ͷ਺͚ͩηογϣϯΛுΕ͹ ϦΫΤετΛ౤͛ͳ͕Βड৴ग़དྷΔΑ

Slide 88

Slide 88 text

SPDY͸1ຊͷηογϣϯͷ্ʹ ༏ઌ౓͕ઃఆ͞Εͨ ෳ਺ͷετϦʔϜΛ࡞Γ ! ͦͷ্ʹHTTPͱಉ͡৘ใΛྲྀ͢ ΫϥΠΞϯτ αʔό ηογϣϯ

Slide 89

Slide 89 text

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 =! ͳΜͱ! Proxygen͸SPDYʹରԠ͍ͯ͠Δ ͜ͷΞυϨεͰ 41%:ͷ઀ଓΛ଴ͪड͚Δ

Slide 90

Slide 90 text

͋ͱ͸SPDYରԠͷϒϥ΢βͰ ΞΫηε͢Ε͹ϓϩτίϧ͕SPDYʹ ͳͬͯͳ͍!

Slide 91

Slide 91 text

ΫϥΠΞϯτ αʔό )551 )551 ΫϥΠΞϯτ αʔό 41%: 41%: SPDYαʔό͸ΫϥΠΞϯτ͕HTTP/1.1Λ ஻ͬͨ৔߹͸HTTPαʔόͱͯ͠ৼΔ෣͏

Slide 92

Slide 92 text

ΫϥΠΞϯτ αʔό )551 )551 ૬ख͸ී௨ͷ HTTPαʔόͩͱࢥͬͯΔ ૬ख͕HTTP஻ͬͯΔ͔Β SPDY஻Εͳ͍ࢠͩͱࢥͬͯΔ αʔό͔ΒΫϥΠΞϯτʹ SPDY͕࢖͑ΔࣄΛ௨஌͢Δඞཁ͕͋Δ

Slide 93

Slide 93 text

NPN /FYU1SPUPDPM/FHPUJBUJPO TLSͷ֦ு ϋϯυγΣΠΫ࣌ʹ αʔό͕ରԠ͍ͯ͠ΔϓϩτίϧͷϦετΛ ΫϥΠΞϯτʹૹΔ

Slide 94

Slide 94 text

NPN͕ͳ͍࣌ ΫϥΠΞϯτ αʔό ͜ͷ҉߸͕࢖͑ΔΑ ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ ४උͰ͖ͨΘ ४උͰ͖ͨΘ 伴ੜ੒ 伴ੜ੒ αʔό͕ ຊ෺͔֬ೝ

Slide 95

Slide 95 text

NPN͕͋Δ࣌ ΫϥΠΞϯτ αʔό ͜ͷ҉߸͕࢖͑ΔΑ (ͱ͜ΖͰϓϩτίϧԿ͍͚Δ?) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (HTTP/1.1͔SPDY/3͕͍͚Δͥ) ४උͰ͖ͨΘ (Μ͡ΌSPDY/3ͰΑΖ) ४උͰ͖ͨΘ 伴ੜ੒ 伴ੜ੒ αʔό͕ ຊ෺͔֬ೝ ϓϩτίϧ ܾఆ

Slide 96

Slide 96 text

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͍͚ΔΑ!

Slide 97

Slide 97 text

͋ͱ͸SPDYରԠͷϒϥ΢βͰ ΞΫηε͢Ε͹ϓϩτίϧ͕SPDYʹ ͳͬͨ!

Slide 98

Slide 98 text

#include ! #include ! #include ! #include ! class handler : public proxygen::RequestHandler {! public:! void onRequest(! std::unique_ptr headers! ) noexcept override {! is_tls = headers->isSecure();! std::cout << int( headers->getPriority() ) << std::endl;! }! void onBody(std::unique_ptr 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͘Εɺ஗ͯ͘΋ྑ͍

Slide 99

Slide 99 text

WebSocket

Slide 100

Slide 100 text

ΫϥΠΞϯτ αʔό ৽ண͋ΔΑ ӾཡதͷWebϖʔδʹߋ৽͕͋ͬͨΒ ௚ͪʹ൓ө͍ͨ͠

Slide 101

Slide 101 text

ݹయతͳղܾํ๏ ΫϥΠΞϯτ αʔό ϙʔϦϯάִؒΛڱΊΔͱαʔό͕ࢮ͵ ϙʔϦϯάִؒΛ৳͹͢ͱ௨஌͕஗ΕΔ ৽ண͋Δ? ৽ண͋Δ? ৽ண͋Δ? ͳ͍ ͳ͍ ͋Δ ৽ண

Slide 102

Slide 102 text

Comet ΫϥΠΞϯτ αʔό αʔό͸௨஌͢΂͖෺͕དྷΔ·Ͱ ΫϥΠΞϯτ͔ΒͷϦΫΤετʹฦ౴͠ͳ͍ ΫϥΠΞϯτ͸Ϩεϙϯε͕དྷͨΒ͙͢ʹϦΫΤετ͢Δ ৽ண͋Δ? ࠓདྷͨ ʜ ৽ண

Slide 103

Slide 103 text

Comet ΫϥΠΞϯτ αʔό αʔό͸௨஌͢΂͖෺͕དྷΔ·Ͱ ΫϥΠΞϯτ͔ΒͷϦΫΤετʹฦ౴͠ͳ͍ ΫϥΠΞϯτ͸Ϩεϙϯε͕དྷͨΒ͙͢ʹϦΫΤετ͢Δ ৽ண͋Δ? ࠓདྷͨ ʜ ৽ண ͜Ε͸΋͸΍ϦΫΤετͰ͸ͳ͍ ͜Ε͸΋͸΍ϨεϙϯεͰ͸ͳ͍

Slide 104

Slide 104 text

HTTPͷ࿮ͷதͰ ղܾ͠Α͏ͱ͢Δͷ͕ ؒҧ͍ͳͷͰ͸

Slide 105

Slide 105 text

HTTPΛ஻ΔͷΛ΍Ίͯ WebαʔόͱΫϥΠΞϯτͷؒͰ ೚ҙͷλΠϛϯάͰ೚ҙͷσʔλΛ ౤͛͋͑ΔΑ͏ʹ͢Δ WebSocket ΫϥΠΞϯτ αʔό ࠓདྷͨ(౜ಥ) ৽ண

Slide 106

Slide 106 text

Proxygenͷpull requestʹ WebSocketʹରԠͤ͞Δมߋ͕స͕͍ͬͯΔ

Slide 107

Slide 107 text

#include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! #include ! ! 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͋ͨΓʹ্͓͖͛ͯ·͢

Slide 108

Slide 108 text

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 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 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ͷΠϕϯτͰݺͼग़͞ΕΔ ίʔϧόοΫΛઃఆ͢Δ

Slide 109

Slide 109 text

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 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ͷΠϯελϯεʹ·Θ͢

Slide 110

Slide 110 text

void onBody(std::unique_ptr 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ͰԿ΋ฦ͞ͳ͍

Slide 111

Slide 111 text

std::unique_ptr 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 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()ͰΫϥΠΞϯτʹσʔλΛૹΔ

Slide 112

Slide 112 text

WebSocketΛ࢖ͬͨνϟοτͷσϞ ΠϚυΩͷϒϥ΢β͕खݩʹ͋Δํ͸ IUUQXXXVTBLVSBOFKQ ʹΞΫηεͯ͠ΈͯԼ͍͞

Slide 113

Slide 113 text

࣮૷ͷҰ෦΍ςετ͕֬ೝग़དྷΔ͕ HTTPServer͔Β࢖͑Δঢ়ଶʹ ͳ͍ͬͯͳ͍ػೳ

Slide 114

Slide 114 text

ServerPush

Slide 115

Slide 115 text

ΫϥΠΞϯτ αʔό ͘Ε ͘Ε ͘Ε HTMLΛύʔεͯ͠ΈΔ·Ͱඞཁͳը૾౳͕෼͔Βͣ ͜ͷؒଞͷϑΝΠϧͷϩʔυΛಉ࣌ਐߦͰ͖ͳ͍ ͕͜͜ Ψϥۭ͖ʹ ͳΔ ͜͜Ͱ ඞཁͳը૾౳͕ ෼͔Δ

Slide 116

Slide 116 text

͜͜Ͱ ඞཁͳը૾౳͕ ෼͔Δ ΫϥΠΞϯτ αʔό ͘Ε ͓લ͸࣍ʹ ը૾ͱ$44͕ཉ͍͠ͱ ݴ͍ग़ͩ͢Ζ͏ ը૾౳Λ (&5͠Α͏ͱ ࢥͬͨΒ Կނ͔΋͏͋Δ SPDY͸ϦΫΤετ͞ΕΔલʹϨεϙϯεΛฦ͢ ServerPushͰ͜ͷ໰୊Λղܾ͢Δ

Slide 117

Slide 117 text

/**! * @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ͷҝͱࢥΘΕΔ ؔ਺͕༻ҙ͞Ε͍ͯΔ

Slide 118

Slide 118 text

XBOHMF )551$PEFD 41%:$PEFD )5515SBOTBDUJPO )5514FSWFS ඇಉظ*0 ݸʑͷϓϩτίϧͰͷ )551ϝοηʔδͷૢ࡞ ϓϩτίϧඇґଘͷ )551ϝοηʔδͷૢ࡞ ͜ͷลΓʹ͸ Server Pushͷ࣮૷Β͖͠෺͕͋Δ HTTP Server͔ΒServer PushΛ ୟ͘࢓૊Έ͕ݟ౰ͨΒͳ͍ ֎޲͖ͷ"1*

Slide 119

Slide 119 text

Trailer ϔομ ຊจ &OEPG.FTTBHF τϨΠϥ HTTPϨεϙϯεͷ ϔομͷҰ෦Λ ຊจΑΓޙΖʹ ॻ͘࢓૊Έ ຊจੜ੒ͯ͠Έͳ͍ͱ ஋͕ఆ·Βͳ͍ νΣοΫαϜ౳ʹ࢖͏

Slide 120

Slide 120 text

void onTrailersComplete(HTTPCodec::StreamID streamID,! std::unique_ptr 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,! 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ͷதʹ͋Δ

Slide 121

Slide 121 text

XBOHMF )551$PEFD 41%:$PEFD )5514FTTJPO )5514FSWFS ඇಉظ*0 ݸʑͷϓϩτίϧͰͷ )551ϝοηʔδͷૢ࡞ ϓϩτίϧඇґଘͷ )551ϝοηʔδͷૢ࡞ ֎޲͖ͷ"1* ͜ͷลΓʹ͸ Trailerͷ࣮૷Β͖͠෺͕͋Δ HTTP ServerͷResponseBuilderͰ TrailerΛ࡞Δ࢓૊Έ͕ݟ౰ͨΒͳ͍

Slide 122

Slide 122 text

HTTP/2 41%:ͷొ৔Λड͚ͯ ೥ͿΓʹվగ͞Εͨ)551 ຊͷηογϣϯʹෳ਺ͷετϦʔϜ ΫϥΠΞϯτ αʔό ηογϣϯ 4FSWFS1VTIʹରԠ ϔομͷѹॖͱࠩ෼ૹ৴ʹରԠ

Slide 123

Slide 123 text

SPDYऴྃͷ͓஌Βͤ ࣍ੈ୅HTTPͷ࣮ݧͱͯ͠࡞ΒΕͨSPDY͸ HTTP/2ͷඪ४ԽͰ໾໨Λऴ͑ͨͱݟ၏͞Ε͓ͯΓ Google͸2016೥ͷૣ͍͏ͪʹ ChromeͷSPDYαϙʔτΛऴྃ͢Δͱ͍ͯ͠Δ ͳΜͯͬͨ͜! ProxygenͰ࡞ͬͨWebαΠτ΋ HTTP/2ʹ͠ͳ͖Ό IUUQCMPHDISPNJVNPSHIFMMPIUUQ HPPECZFTQEZIUUQJT@IUNM

Slide 124

Slide 124 text

/**! * 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

Slide 125

Slide 125 text

XBOHMF )551$PEFD 41%:$PEFD )5515SBOTBDUJPO )5514FSWFS ΋͔ͯ͠͠ ΋͏࢖͑Δ? )551$PEFD

Slide 126

Slide 126 text

HTTP/2͸HTTP/1.1͔Βͷ੾Γସ͑ʹ NPNͰ͸ͳ͘ALPNΛ࢖͏ ALPN Application Layer Protocol Negotiation TLSͷ֦ு ϋϯυγΣΠΫ࣌ʹ ΫϥΠΞϯτ͕ରԠ͍ͯ͠ΔϓϩτίϧͷϦετΛ αʔόʹૹΔ

Slide 127

Slide 127 text

NPN ΫϥΠΞϯτ αʔό ͜ͷ҉߸͕࢖͑ΔΑ (ͱ͜ΖͰϓϩτίϧԿ͍͚Δ?) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (HTTP/1.1͔SPDY/3͕͍͚Δͥ) ४උͰ͖ͨΘ (Μ͡ΌSPDY/3ͰΑΖ) ४උͰ͖ͨΘ 伴ੜ੒ 伴ੜ੒ αʔό͕ ຊ෺͔֬ೝ ϓϩτίϧ ܾఆ

Slide 128

Slide 128 text

ALPN ͜ͷ҉߸͕࢖͑ΔΑ (Զ࣮͸HTTP/2͍͚ΔΜͩΑͶ) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (͡Ό͋HTTP/2ͰΑΖ) ४උͰ͖ͨΘ ४උͰ͖ͨΘ 伴ੜ੒ 伴ੜ੒ αʔό͕ ຊ෺͔֬ೝ ϓϩτίϧ ܾఆ ΫϥΠΞϯτ αʔό

Slide 129

Slide 129 text

ALPN ͜ͷ҉߸͕࢖͑ΔΑ (Զ࣮͸HTTP/2͍͚ΔΜͩΑͶ) ҉߸Խͨ͠ ϓϦϚελγʔΫϨοτͩΑ ͜Ε͕ূ໌ॻͩΑ (͡Ό͋HTTP/2ͰΑΖ) ४උͰ͖ͨΘ ४උͰ͖ͨΘ 伴ੜ੒ 伴ੜ੒ αʔό͕ ຊ෺͔֬ೝ ϓϩτίϧ ܾఆ ΫϥΠΞϯτ αʔό ࢖͑Δϓϩτίϧ͕ແ͔ͬͨ৔߹ʹ TLSͷ伴ੜ੒ʹೖΔલʹ઀ଓΛ੾ΕΔ

Slide 130

Slide 130 text

Proxygenʹ͸ ALPNΛૹΔҝͷ࢓૊Έ͕ݟ౰ͨΒͳ͍ ͓ͦΒ͘ProxygenͷHTTP/2ͷ࣮૷͸ ϦΫΤετͱϨεϙϯεͷύʔε͸ग़དྷΔ͕ ࣮ࡍʹΫϥΠΞϯτ͔Βͷ௨৴Λ ड͚෇͚ΒΕΔॴ·Ͱ͸࣮૷͞Ε͍ͯͳ͍ (2015೥10݄8೔࣌఺)

Slide 131

Slide 131 text

·ͱΊ C++ͳWebϑϨʔϜϫʔΫProxygen TLSͰ͖ΔΑ SPDY΋Ͱ͖ΔΑ WebSocket΋ҰԠͰ͖ΔΑ HTTP/2͸·ͩͩΑ