<titledata-react-helmet="true">Page Not Found | Pistache</title><metadata-react-helmet="true"property="og:title"content="Page Not Found | Pistache"><metadata-react-helmet="true"property="og:url"content="https://pistache.io/404.html"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_tag"content="default"><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/404.html"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/404.html"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/404.html"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<div><ahref="#main"class="skipToContent_1oUP shadow--md">Skip to main content</a></div><navclass="navbar navbar--fixed-top"><divclass="navbar__inner"><divclass="navbar__items"><buttonaria-label="Navigation bar toggle"class="navbar__toggle clean-btn"type="button"tabindex="0"><svgwidth="30"height="30"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a><aclass="navbar__item navbar__link"href="/docs/">Docs</a></div><divclass="navbar__items navbar__items--right"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="navbar__item navbar__link header-github-link"aria-label="GitHub repository"></a><divclass="react-toggle displayOnlyInLargeViewport_GrZ2 react-toggle--disabled"><divclass="react-toggle-track"role="button"tabindex="-1"><divclass="react-toggle-track-check"><spanclass="toggle_71bT">🌜</span></div><divclass="react-toggle-track-x"><spanclass="toggle_71bT">🌞</span></div><divclass="react-toggle-thumb"></div></div><inputtype="checkbox"class="react-toggle-screenreader-only"aria-label="Switch between dark and light mode"></div></div></div><divrole="presentation"class="navbar-sidebar__backdrop"></div><divclass="navbar-sidebar"><divclass="navbar-sidebar__brand"><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a></div><divclass="navbar-sidebar__items"><divclass="menu"><ulclass="menu__list"><liclass="menu__list-item"><aclass="menu__link"href="/docs/">Docs</a></li><liclass="menu__list-item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="menu__link header-github-link"aria-label="GitHub repository"></a></li></ul></div></div></div></nav><divclass="main-wrapper"><mainclass="container margin-vert--xl"><divclass="row"><divclass="col col--6 col--offset-3"><h1class="hero__title">Page Not Found</h1><p>We could not find what you were looking for.</p><p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</p></div></div></main></div><footerclass="footer footer--dark"><divclass="container"><divclass="row footer__links"><divclass="col footer__col"><divclass="footer__title">Docs</div><ulclass="footer__items"><liclass="footer__item"><aclass="footer__link-item"href="/docs/">Quickstart</a></li><liclass="footer__item"><aclass="footer__link-item"href="/docs/http-handler/">User guide</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">Community</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://stackoverflow.com/questions/tagged/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">Stack Overflow</a></li><liclass="footer__item"><ahref="https://web.libera.chat/#pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">#pistache on Libera.Chat</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">More</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">GitHub</a></li></ul></div></div><divclass="footer__bottom text--center"><divclass="footer__copyright">Pistache, 2015 - 2021</div></div></div></footer></div>
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[651],{7917:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returnr},contentTitle:function(){returno},metadata:function(){returnp},toc:function(){returnc},default:function(){returnu}});vara=n(2122),l=n(9756),i=(n(7294),n(3905)),s=["components"],r={title:"Getting started",slug:"/"},o=void0,p={unversionedId:"quickstart",id:"quickstart",isDocsHomePage:!1,title:"Getting started",description:"\x3c!--",source:"@site/docs/quickstart.md",sourceDirName:".",slug:"/",permalink:"/docs/",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/quickstart.md",version:"current",frontMatter:{title:"Getting started",slug:"/"},sidebar:"leftSidebar",previous:{title:"HTTP handler",permalink:"/docs/http-handler"},next:{title:"REST description",permalink:"/docs/rest-description"}},c=[{value:"Installing Pistache",id:"installing-pistache",children:[]},{value:"Serving requests",id:"serving-requests",children:[{value:"Include",id:"include",children:[]},{value:"Hello world",id:"hello-world",children:[]},{value:"Final touch",id:"final-touch",children:[]}]}],d={toc:c};functionu(e){vart=e.components,n=(0,l.Z)(e,s);return(0,i.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,"Pistache is a web framework written in Modern C++ that focuses on performance and provides an elegant and asynchronous API."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"#include <pistache/pistache.h>\n")),(0,i.kt)("h2",{id:"installing-pistache"},"Installing Pistache"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://git-scm.com"},"git")," is needed to retrieve the sources. Compiling the sources will require ",(0,i.kt)("a",{parentName:"p",href:"https://cmake.org"},"CMake")," to generate build files and a recent compiler that supports C++17."),(0,i.kt)("p",null,"If you're on Ubuntu and want to skip the compilation process you can add the official PPA providing nightly builds:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"sudo add-apt-repository ppa:pistache+team/unstable\nsudo apt update\nsudo apt install libpistache-dev\n")),(0,i.kt)("p",null,"Otherwise, here's how to build and install the latest release:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"git clone https://github.com/pistacheio/pistache.git\ncd pistache\nmeson setup build\nmeson install -C build\n")),(0,i.kt)("p",null,"Also, Pistache does not support Windows yet, but should work fine under ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/windows/wsl/about"},"WSL"),"."),(0,i.kt)("h2",{id:"serving-requests"},"Serving requests"),(0,i.kt)("h3",{id:"include"},"Include"),(0,i.kt)("p",null,"First, let\u2019s start by including the right header."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"#include <pistache/endpoint.h>\n")),(0,i.kt)("h3",{id:"hello-world"},"Hello world"),(0,i.kt)("p",null,"Requests received by Pistache are handled with an ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Handler"),"."),(0,i.kt)("p",null,"Let\u2019s start by defining a simple ",(0,i.kt)("inlineCode",{parentName:"p"},"HelloHandler"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'using namespace Pistache;\n\nclass HelloHandler : public Http::Handler {\npublic:\n\n HTTP_PROTOTYPE(HelloHandler)\n\n void onRequest(const Http::Request& request, Http::ResponseWriter response) {\n response.send(Http::Code::Ok, "Hello, World\\n");\n }\n};\n')),(0,i.kt)("p",null,"Handlers must inherit the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Handler")," class and at least define the ",(0,i.kt)("inlineCode",{parentName:"p"},"onRequest")," member function. They must also define a ",(0,i.kt)("inlineCode",{parentName:"p"},"clone()")," member function. Simple handlers can use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"HTTP_PROTOTYPE")," macro, passing in the name of the class. The macro will take care of defining the ",(0,i.kt)("inlineCode",{parentName:"p"},"clone()")," member function for you."),(0,i.kt)("h3",{id:"final-touch"},"Final touch"),(0,i.kt)("p",null,"After defining the handler, the server can now be started:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"int main() {\n Address addr(Ipv4::any(), Port(9080));\n\n auto opts = Http::Endpoint::options().threads(1);\n Http::Endpoint server(addr);\n server.init(opts);\n server.setHandler(Http::make_handler<HelloHandler>());\n server.serve();\n}\n")),(0,i.kt)("p",null,"For simplicity, you can also use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"listenAndServe")," function that will automatically create an endpoint and instantiate your handler:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'int main() {\n Http::listenAndServe<HelloHandler>("*:9080");\n}\n')),(0,i.kt)("p",null,"And that\u2019s it, now you can fire up your favorite curl request and observe the final result:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"curl http://localhost:9080/\nHello, World\n")),(0,i.kt)("p",null,"Complete code for this example can be found on GitHub: ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/pistacheio/pistache/blob/master/examples/hello_server.cc"},"examples/hello_server.cc")))}u.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[651],{7917:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returnr},contentTitle:function(){returno},metadata:function(){returnp},toc:function(){returnc},default:function(){returnu}});vara=n(2122),l=n(9756),i=(n(7294),n(3905)),s=["components"],r={title:"Getting started",slug:"/"},o=void0,p={unversionedId:"quickstart",id:"quickstart",isDocsHomePage:!1,title:"Getting started",description:"Pistache is a web framework written in Modern C++ that focuses on performance and provides an elegant and asynchronous API.",source:"@site/docs/quickstart.md",sourceDirName:".",slug:"/",permalink:"/docs/",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/quickstart.md",version:"current",frontMatter:{title:"Getting started",slug:"/"},sidebar:"leftSidebar",previous:{title:"HTTP handler",permalink:"/docs/http-handler"},next:{title:"REST description",permalink:"/docs/rest-description"}},c=[{value:"Installing Pistache",id:"installing-pistache",children:[]},{value:"Serving requests",id:"serving-requests",children:[{value:"Include",id:"include",children:[]},{value:"Hello world",id:"hello-world",children:[]},{value:"Final touch",id:"final-touch",children:[]}]}],d={toc:c};functionu(e){vart=e.components,n=(0,l.Z)(e,s);return(0,i.kt)("wrapper",(0,a.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("p",null,"Pistache is a web framework written in Modern C++ that focuses on performance and provides an elegant and asynchronous API."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"#include <pistache/pistache.h>\n")),(0,i.kt)("h2",{id:"installing-pistache"},"Installing Pistache"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://git-scm.com"},"git")," is needed to retrieve the sources. Compiling the sources will require ",(0,i.kt)("a",{parentName:"p",href:"https://cmake.org"},"CMake")," to generate build files and a recent compiler that supports C++17."),(0,i.kt)("p",null,"If you're on Ubuntu and want to skip the compilation process you can add the official PPA providing nightly builds:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"sudo add-apt-repository ppa:pistache+team/unstable\nsudo apt update\nsudo apt install libpistache-dev\n")),(0,i.kt)("p",null,"Otherwise, here's how to build and install the latest release:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"git clone https://github.com/pistacheio/pistache.git\ncd pistache\nmeson setup build\nmeson install -C build\n")),(0,i.kt)("p",null,"Also, Pistache does not support Windows yet, but should work fine under ",(0,i.kt)("a",{parentName:"p",href:"https://docs.microsoft.com/windows/wsl/about"},"WSL"),"."),(0,i.kt)("h2",{id:"serving-requests"},"Serving requests"),(0,i.kt)("h3",{id:"include"},"Include"),(0,i.kt)("p",null,"First, let\u2019s start by including the right header."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"#include <pistache/endpoint.h>\n")),(0,i.kt)("h3",{id:"hello-world"},"Hello world"),(0,i.kt)("p",null,"Requests received by Pistache are handled with an ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Handler"),"."),(0,i.kt)("p",null,"Let\u2019s start by defining a simple ",(0,i.kt)("inlineCode",{parentName:"p"},"HelloHandler"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'using namespace Pistache;\n\nclass HelloHandler : public Http::Handler {\npublic:\n\n HTTP_PROTOTYPE(HelloHandler)\n\n void onRequest(const Http::Request& request, Http::ResponseWriter response) {\n response.send(Http::Code::Ok, "Hello, World\\n");\n }\n};\n')),(0,i.kt)("p",null,"Handlers must inherit the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Handler")," class and at least define the ",(0,i.kt)("inlineCode",{parentName:"p"},"onRequest")," member function. They must also define a ",(0,i.kt)("inlineCode",{parentName:"p"},"clone()")," member function. Simple handlers can use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"HTTP_PROTOTYPE")," macro, passing in the name of the class. The macro will take care of defining the ",(0,i.kt)("inlineCode",{parentName:"p"},"clone()")," member function for you."),(0,i.kt)("h3",{id:"final-touch"},"Final touch"),(0,i.kt)("p",null,"After defining the handler, the server can now be started:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"int main() {\n Address addr(Ipv4::any(), Port(9080));\n\n auto opts = Http::Endpoint::options().threads(1);\n Http::Endpoint server(addr);\n server.init(opts);\n server.setHandler(Http::make_handler<HelloHandler>());\n server.serve();\n}\n")),(0,i.kt)("p",null,"For simplicity, you can also use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"listenAndServe")," function that will automatically create an endpoint and instantiate your handler:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'int main() {\n Http::listenAndServe<HelloHandler>("*:9080");\n}\n')),(0,i.kt)("p",null,"And that\u2019s it, now you can fire up your favorite curl request and observe the final result:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"curl http://localhost:9080/\nHello, World\n")),(0,i.kt)("p",null,"Complete code for this example can be found on GitHub: ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/pistacheio/pistache/blob/master/examples/hello_server.cc"},"examples/hello_server.cc")))}u.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[659],{4660:function(t,e,i){"use strict";i.r(e),i.d(e,{frontMatter:function(){returnc},contentTitle:function(){returnp},metadata:function(){returna},toc:function(){returnd},default:function(){returnl}});varr=i(2122),n=i(9756),s=(i(7294),i(3905)),o=["components"],c={title:"REST description"},p=void0,a={unversionedId:"rest-description",id:"rest-description",isDocsHomePage:!1,title:"REST description",description:"\x3c!--",source:"@site/docs/rest-description.md",sourceDirName:".",slug:"/rest-description",permalink:"/docs/rest-description",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/rest-description.md",version:"current",frontMatter:{title:"REST description"},sidebar:"leftSidebar",previous:{title:"Getting started",permalink:"/docs/"},next:{title:"Routing",permalink:"/docs/routing"}},d=[],u={toc:d};functionl(t){vare=t.components,i=(0,n.Z)(t,o);return(0,s.kt)("wrapper",(0,r.Z)({},u,i,{components:e,mdxType:"MDXLayout"}),(0,s.kt)("p",null,"Documentation writing for this part is still in progress, please refer to the ",(0,s.kt)("a",{parentName:"p",href:"https://github.com/pistacheio/pistache/blob/master/examples/rest_description.cc"},"rest_description")," example."))}l.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[659],{4660:function(t,e,i){"use strict";i.r(e),i.d(e,{frontMatter:function(){returnc},contentTitle:function(){returnp},metadata:function(){returna},toc:function(){returnd},default:function(){returnl}});varr=i(2122),s=i(9756),n=(i(7294),i(3905)),o=["components"],c={title:"REST description"},p=void0,a={unversionedId:"rest-description",id:"rest-description",isDocsHomePage:!1,title:"REST description",description:"Documentation writing for this part is still in progress, please refer to the restdescription example.",source:"@site/docs/rest-description.md",sourceDirName:".",slug:"/rest-description",permalink:"/docs/rest-description",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/rest-description.md",version:"current",frontMatter:{title:"REST description"},sidebar:"leftSidebar",previous:{title:"Getting started",permalink:"/docs/"},next:{title:"Routing",permalink:"/docs/routing"}},d=[],u={toc:d};functionl(t){vare=t.components,i=(0,s.Z)(t,o);return(0,n.kt)("wrapper",(0,r.Z)({},u,i,{components:e,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"Documentation writing for this part is still in progress, please refer to the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/pistacheio/pistache/blob/master/examples/rest_description.cc"},"rest_description")," example."))}l.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[427],{1914:function(e,t,a){"use strict";a.r(t),a.d(t,{frontMatter:function(){returns},contentTitle:function(){returnp},metadata:function(){returnd},toc:function(){returnl},default:function(){returnc}});varn=a(2122),r=a(9756),i=(a(7294),a(3905)),o=["components"],s={title:"Headers"},p=void0,d={unversionedId:"headers",id:"headers",isDocsHomePage:!1,title:"Headers",description:"Overview",source:"@site/docs/headers.md",sourceDirName:".",slug:"/headers",permalink:"/docs/headers",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/headers.md",version:"current",frontMatter:{title:"Headers"},sidebar:"leftSidebar",previous:{title:"Asynchronous HTTP programming",permalink:"/docs/asynchronous-http-programming"},next:{title:"HTTP handler",permalink:"/docs/http-handler"}},l=[{value:"Overview",id:"overview",children:[]},{value:"Defining your own header",id:"defining-your-own-header",children:[]},{value:"MIME types",id:"mime-types",children:[]}],m={toc:l};functionc(e){vart=e.components,a=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,n.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"Inspired by the ",(0,i.kt)("a",{parentName:"p",href:"https://www.rust-lang.org"},"Rust")," eco-system and ",(0,i.kt)("a",{parentName:"p",href:"https://hyper.rs"},"Hyper"),", HTTP headers are represented as ",(0,i.kt)("em",{parentName:"p"},"type-safe")," plain objects. Instead of representing headers as a pair of ",(0,i.kt)("inlineCode",{parentName:"p"},"(key: string, value: value)"),", the choice has been made to represent them as plain objects. This greatly reduces the risk of typo errors that can not catched by the compiler with plain old strings."),(0,i.kt)("p",null,"Instead, objects give the compiler the ability to catch errors directly at compile-time, as the user can not add or request a header through its name: it has to use the whole ",(0,i.kt)("strong",{parentName:"p"},"type"),". Types being enforced at compile-time, it helps reducing common typo errors."),(0,i.kt)("p",null,"With Pistache, each HTTP Header is a class that inherits from the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," base class and use the ",(0,i.kt)("inlineCode",{parentName:"p"},"NAME()")," macro to define the name of the header. List of all headers inside an HTTP request or response are stored inside an internal ",(0,i.kt)("a",{parentName:"p",href:"https://en.cppreference.com/w/cpp/container/unordered_map"},(0,i.kt)("inlineCode",{parentName:"a"},"std::unordered_map")),", wrapped in an ",(0,i.kt)("inlineCode",{parentName:"p"},"Header::Collection")," class. Invidual headers can be retrieved or added to this object through the whole type of the header:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto headers = request.headers();\nauto ct = headers.get<Http::Header::ContentType>();\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"get<H>")," will return a ",(0,i.kt)("inlineCode",{parentName:"p"},"std::shared_ptr<H>")," where ",(0,i.kt)("inlineCode",{parentName:"p"},"H: Header")," (",(0,i.kt)("inlineCode",{parentName:"p"},"H")," inherits from ",(0,i.kt)("inlineCode",{parentName:"p"},"Header"),"). If the header does not exist, ",(0,i.kt)("inlineCode",{parentName:"p"},"get<H>")," will throw an exception. ",(0,i.kt)("inlineCode",{parentName:"p"},"tryGet<H>")," provides a non-throwing alternative that, instead, returns a null pointer."),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Built-in headers")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"Headers provided by Pistache live in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," namespace"))),(0,i.kt)("h2",{id:"defining-your-own-header"},"Defining your own header"),(0,i.kt)("p",null,"Common headers defined by the HTTP RFC (",(0,i.kt)("a",{parentName:"p",href:"https://pretty-rfc.herokuapp.com/RFC2616"},"RFC2616"),") are already implemented and available. However, some APIs might define extra headers that do not exist in Pistache. To support your own header types, you can define and register your own HTTP Header by first declaring a class that inherits the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," class:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"class XProtocolVersion : public Http::Header {\n};\n")),(0,i.kt)("p",null,"Since every header has a name, the ",(0,i.kt)("inlineCode",{parentName:"p"},"NAME()")," macro must be used to name the header properly:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'class XProtocolVersion : public Http::Header {\n NAME("X-Protocol-Version")\n};\n')),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," base class provides two virtual methods that you must override in your own implementation:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void parse(const std::string& data);\n")),(0,i.kt)("p",null,"This function is used to parse the header from the string representation. Alternatively, to avoid allocating memory for the string representation, a ",(0,i.kt)("em",{parentName:"p"},"raw")," version can be used:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void parseRaw(const char* str, size_t len);\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"str")," will directly point to the header buffer from the raw http stream. The len parameter is the total length of the header's value."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void write(std::ostream& stream) const\n")),(0,i.kt)("p",null,"When writing the response back to the client, the ",(0,i.kt)("inlineCode",{parentName:"p"},"write")," function is used to serialize the header into the network buffer."),(0,i.kt)("p",null,"Let\u2019s combine these functions together to finalize the implementation of our previously declared header:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'class XProtocolVersion : public Http::Header {\npublic:\n\n NAME("X-Protocol-Version")\n\n XProtocolVersion()\n : minor(-1)\n , major(-1)\n { }\n\n void parse(const std::string& data) {\n auto pos = data.find(\'.\');\n if (pos != std::string::npos) {\n minor = std::stoi(data.substr(0, pos));\n major = std::stoi(data.substr(pos + 1));\n }\n }\n\n void write(std::ostream& os) const {\n os << minor << "." << major;\n }\nprivate:\n int minor;\n int major;\n};\n')),(0,i.kt)("p",null,"And that\u2019s it. Now all we have to do is registering the header to the registry system:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Header::Registry::registerHeader<XProtocolVersion>();\n")),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Header instantation")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"You should always provide a default constructor for your header so that it can be instantiated by the registry system"))),(0,i.kt)("p",null,"Now, the ",(0,i.kt)("inlineCode",{parentName:"p"},"XProtocolVersion")," can be retrieved and added like any other header in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Header::Collection")," class."),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Unknown headers")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"Headers that are not known to the registry system are stored as a raw pair of strings in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Collection")," class. ",(0,i.kt)("inlineCode",{parentName:"p"},"getRaw()")," can be used to retrieve a raw header:"),(0,i.kt)("pre",{parentName:"div"},(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'auto myHeader = request.headers().getRaw("x-raw-header");\nmyHeader.name() // x-raw-header\nmyHeader.value() // returns the value of the header as a string\n')))),(0,i.kt)("h2",{id:"mime-types"},"MIME types"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Media_type"},"MIME Types")," (or Media Type) are also fully typed. Such types are for example used in an HTTP request or response to describe the data contained in the body of the message (",(0,i.kt)("inlineCode",{parentName:"p"},"Content-Type")," header, \u2026) and are composed of a ",(0,i.kt)("em",{parentName:"p"},"type"),", ",(0,i.kt)("em",{parentName:"p"},"subtype"),", and optional ",(0,i.kt)("em",{parentName:"p"},"suffix")," and parameters."),(0,i.kt)("p",null,"MIME Types are represented by the ",(0,i.kt)("inlineCode",{parentName:"p"},"Mime::MediaType")," class, implemented in the ",(0,i.kt)("inlineCode",{parentName:"p"},"mime.h")," header. A MIME type can be directly constructed from a string:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'auto mime = Http::Mime::MediaType::fromString("application/json");\n')),(0,i.kt)("p",null,"However, to enforce type-safety, common types are all represented as enumerations:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Mime::MediaType m1(Http::Mime::Type::Application, Http::Mime::Subtype::Json);\n")),(0,i.kt)("p",null,"To avoid such a typing pain, a ",(0,i.kt)("inlineCode",{parentName:"p"},"MIME")," macro is also provided:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME(Application, Json);\n")),(0,i.kt)("p",null,"For suffix MIMEs, use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"MIME3")," macro:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME3(Application, Json, Zip);\n")),(0,i.kt)("p",null,"If you like typing, you can also use the long form:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Mime::MediaType m1(Http::Mime::Type::Application, Http::Mime::Subtype::Json, Http::Mime::Suffix::Zip);\n")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"toString()")," function can be used to get the string representation of a given MIME type:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME(Text, Html);\nm1.toString(); // text/html\n")))}c.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[427],{1914:function(e,t,a){"use strict";a.r(t),a.d(t,{frontMatter:function(){returns},contentTitle:function(){returnp},metadata:function(){returnd},toc:function(){returnl},default:function(){returnc}});varn=a(2122),r=a(9756),i=(a(7294),a(3905)),o=["components"],s={title:"Headers"},p=void0,d={unversionedId:"headers",id:"headers",isDocsHomePage:!1,title:"Headers",description:"\x3c!--",source:"@site/docs/headers.md",sourceDirName:".",slug:"/headers",permalink:"/docs/headers",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/headers.md",version:"current",frontMatter:{title:"Headers"},sidebar:"leftSidebar",previous:{title:"Asynchronous HTTP programming",permalink:"/docs/asynchronous-http-programming"},next:{title:"HTTP handler",permalink:"/docs/http-handler"}},l=[{value:"Overview",id:"overview",children:[]},{value:"Defining your own header",id:"defining-your-own-header",children:[]},{value:"MIME types",id:"mime-types",children:[]}],m={toc:l};functionc(e){vart=e.components,a=(0,r.Z)(e,o);return(0,i.kt)("wrapper",(0,n.Z)({},m,a,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"overview"},"Overview"),(0,i.kt)("p",null,"Inspired by the ",(0,i.kt)("a",{parentName:"p",href:"https://www.rust-lang.org"},"Rust")," eco-system and ",(0,i.kt)("a",{parentName:"p",href:"https://hyper.rs"},"Hyper"),", HTTP headers are represented as ",(0,i.kt)("em",{parentName:"p"},"type-safe")," plain objects. Instead of representing headers as a pair of ",(0,i.kt)("inlineCode",{parentName:"p"},"(key: string, value: value)"),", the choice has been made to represent them as plain objects. This greatly reduces the risk of typo errors that can not catched by the compiler with plain old strings."),(0,i.kt)("p",null,"Instead, objects give the compiler the ability to catch errors directly at compile-time, as the user can not add or request a header through its name: it has to use the whole ",(0,i.kt)("strong",{parentName:"p"},"type"),". Types being enforced at compile-time, it helps reducing common typo errors."),(0,i.kt)("p",null,"With Pistache, each HTTP Header is a class that inherits from the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," base class and use the ",(0,i.kt)("inlineCode",{parentName:"p"},"NAME()")," macro to define the name of the header. List of all headers inside an HTTP request or response are stored inside an internal ",(0,i.kt)("a",{parentName:"p",href:"https://en.cppreference.com/w/cpp/container/unordered_map"},(0,i.kt)("inlineCode",{parentName:"a"},"std::unordered_map")),", wrapped in an ",(0,i.kt)("inlineCode",{parentName:"p"},"Header::Collection")," class. Invidual headers can be retrieved or added to this object through the whole type of the header:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto headers = request.headers();\nauto ct = headers.get<Http::Header::ContentType>();\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"get<H>")," will return a ",(0,i.kt)("inlineCode",{parentName:"p"},"std::shared_ptr<H>")," where ",(0,i.kt)("inlineCode",{parentName:"p"},"H: Header")," (",(0,i.kt)("inlineCode",{parentName:"p"},"H")," inherits from ",(0,i.kt)("inlineCode",{parentName:"p"},"Header"),"). If the header does not exist, ",(0,i.kt)("inlineCode",{parentName:"p"},"get<H>")," will throw an exception. ",(0,i.kt)("inlineCode",{parentName:"p"},"tryGet<H>")," provides a non-throwing alternative that, instead, returns a null pointer."),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Built-in headers")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"Headers provided by Pistache live in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," namespace"))),(0,i.kt)("h2",{id:"defining-your-own-header"},"Defining your own header"),(0,i.kt)("p",null,"Common headers defined by the HTTP RFC (",(0,i.kt)("a",{parentName:"p",href:"https://pretty-rfc.herokuapp.com/RFC2616"},"RFC2616"),") are already implemented and available. However, some APIs might define extra headers that do not exist in Pistache. To support your own header types, you can define and register your own HTTP Header by first declaring a class that inherits the ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," class:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"class XProtocolVersion : public Http::Header {\n};\n")),(0,i.kt)("p",null,"Since every header has a name, the ",(0,i.kt)("inlineCode",{parentName:"p"},"NAME()")," macro must be used to name the header properly:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'class XProtocolVersion : public Http::Header {\n NAME("X-Protocol-Version")\n};\n')),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"Http::Header")," base class provides two virtual methods that you must override in your own implementation:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void parse(const std::string& data);\n")),(0,i.kt)("p",null,"This function is used to parse the header from the string representation. Alternatively, to avoid allocating memory for the string representation, a ",(0,i.kt)("em",{parentName:"p"},"raw")," version can be used:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void parseRaw(const char* str, size_t len);\n")),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"str")," will directly point to the header buffer from the raw http stream. The len parameter is the total length of the header's value."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"void write(std::ostream& stream) const\n")),(0,i.kt)("p",null,"When writing the response back to the client, the ",(0,i.kt)("inlineCode",{parentName:"p"},"write")," function is used to serialize the header into the network buffer."),(0,i.kt)("p",null,"Let\u2019s combine these functions together to finalize the implementation of our previously declared header:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'class XProtocolVersion : public Http::Header {\npublic:\n\n NAME("X-Protocol-Version")\n\n XProtocolVersion()\n : minor(-1)\n , major(-1)\n { }\n\n void parse(const std::string& data) {\n auto pos = data.find(\'.\');\n if (pos != std::string::npos) {\n minor = std::stoi(data.substr(0, pos));\n major = std::stoi(data.substr(pos + 1));\n }\n }\n\n void write(std::ostream& os) const {\n os << minor << "." << major;\n }\nprivate:\n int minor;\n int major;\n};\n')),(0,i.kt)("p",null,"And that\u2019s it. Now all we have to do is registering the header to the registry system:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Header::Registry::registerHeader<XProtocolVersion>();\n")),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Header instantation")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"You should always provide a default constructor for your header so that it can be instantiated by the registry system"))),(0,i.kt)("p",null,"Now, the ",(0,i.kt)("inlineCode",{parentName:"p"},"XProtocolVersion")," can be retrieved and added like any other header in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Header::Collection")," class."),(0,i.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Unknown headers")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"Headers that are not known to the registry system are stored as a raw pair of strings in the ",(0,i.kt)("inlineCode",{parentName:"p"},"Collection")," class. ",(0,i.kt)("inlineCode",{parentName:"p"},"getRaw()")," can be used to retrieve a raw header:"),(0,i.kt)("pre",{parentName:"div"},(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'auto myHeader = request.headers().getRaw("x-raw-header");\nmyHeader.name() // x-raw-header\nmyHeader.value() // returns the value of the header as a string\n')))),(0,i.kt)("h2",{id:"mime-types"},"MIME types"),(0,i.kt)("p",null,(0,i.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Media_type"},"MIME Types")," (or Media Type) are also fully typed. Such types are for example used in an HTTP request or response to describe the data contained in the body of the message (",(0,i.kt)("inlineCode",{parentName:"p"},"Content-Type")," header, \u2026) and are composed of a ",(0,i.kt)("em",{parentName:"p"},"type"),", ",(0,i.kt)("em",{parentName:"p"},"subtype"),", and optional ",(0,i.kt)("em",{parentName:"p"},"suffix")," and parameters."),(0,i.kt)("p",null,"MIME Types are represented by the ",(0,i.kt)("inlineCode",{parentName:"p"},"Mime::MediaType")," class, implemented in the ",(0,i.kt)("inlineCode",{parentName:"p"},"mime.h")," header. A MIME type can be directly constructed from a string:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},'auto mime = Http::Mime::MediaType::fromString("application/json");\n')),(0,i.kt)("p",null,"However, to enforce type-safety, common types are all represented as enumerations:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Mime::MediaType m1(Http::Mime::Type::Application, Http::Mime::Subtype::Json);\n")),(0,i.kt)("p",null,"To avoid such a typing pain, a ",(0,i.kt)("inlineCode",{parentName:"p"},"MIME")," macro is also provided:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME(Application, Json);\n")),(0,i.kt)("p",null,"For suffix MIMEs, use the special ",(0,i.kt)("inlineCode",{parentName:"p"},"MIME3")," macro:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME3(Application, Json, Zip);\n")),(0,i.kt)("p",null,"If you like typing, you can also use the long form:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Mime::MediaType m1(Http::Mime::Type::Application, Http::Mime::Subtype::Json, Http::Mime::Suffix::Zip);\n")),(0,i.kt)("p",null,"The ",(0,i.kt)("inlineCode",{parentName:"p"},"toString()")," function can be used to get the string representation of a given MIME type:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-cpp"},"auto m1 = MIME(Text, Html);\nm1.toString(); // text/html\n")))}c.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[489],{2509:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returns},contentTitle:function(){returnl},metadata:function(){returnc},toc:function(){returnp},default:function(){returnm}});vara=n(2122),r=n(9756),o=(n(7294),n(3905)),i=["components"],s={title:"Asynchronous HTTP programming"},l=void0,c={unversionedId:"asynchronous-http-programming",id:"asynchronous-http-programming",isDocsHomePage:!1,title:"Asynchronous HTTP programming",description:"Interfaces provided by Pistaches are asynchronous and non-blocking. Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to asynchronous calls.",source:"@site/docs/asynchronous-http-programming.md",sourceDirName:".",slug:"/asynchronous-http-programming",permalink:"/docs/asynchronous-http-programming",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/asynchronous-http-programming.md",version:"current",frontMatter:{title:"Asynchronous HTTP programming"},sidebar:"leftSidebar",next:{title:"Headers",permalink:"/docs/headers"}},p=[],h={toc:p};functionm(e){vart=e.components,n=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Interfaces provided by Pistaches are ",(0,o.kt)("em",{parentName:"p"},"asynchronous")," and ",(0,o.kt)("em",{parentName:"p"},"non-blocking"),". Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to ",(0,o.kt)("em",{parentName:"p"},"asynchronous calls"),"."),(0,o.kt)("p",null,"An example of such a call is the ",(0,o.kt)("inlineCode",{parentName:"p"},"send()")," function provided by the ",(0,o.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," interface. This function returns the number of bytes written to the socket file descriptor associated to the connection. However, instead of returning directly the value to the caller and thus blocking the caller, it wraps the value into a component called a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise"),"."),(0,o.kt)("p",null,"A ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," is the Pistache\u2019s implementation of the ",(0,o.kt)("a",{parentName:"p",href:"https://promisesaplus.com"},"Promises/A+")," standard available in many JavaScript implementations. Simply put, during an asynchronous call, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," separates the launch of an asynchronous operation from the retrieval of its result. While the asynchronous might still be running, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise<T>")," is directly returned to the caller to retrieve the final result when it becomes available. A so called continuation can be attach to a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," to execute a callback when the result becomes available (when the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," has been resolved or fulfilled)."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cpp"},'auto res = response.send(Http::Code::Ok, "Hello World");\nres.then(\n [](ssize_t bytes) { std::cout << bytes << " bytes have been sent\\n" },\n Async::NoExcept\n);\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"then()")," member is used to attach a callback to the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise"),". The first argument is a callable that will be called when the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," has been ",(0,o.kt)("strong",{parentName:"p"},"succesfully")," resolved. If, for some reason, an error occurs during the asynchronous operation, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," can be ",(0,o.kt)("strong",{parentName:"p"},"rejected")," and will then fail. In this case, the second callable will be called. ",(0,o.kt)("inlineCode",{parentName:"p"},"Async::NoExcept")," is a special callback that will call ",(0,o.kt)("a",{parentName:"p",href:"https://en.cppreference.com/w/cpp/error/terminate"},(0,o.kt)("inlineCode",{parentName:"a"},"std::terminate()"))," if the promise failed. This is the equivalent of the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexcept")," keyword."),(0,o.kt)("p",null,"Other generic callbacks can also be used in this case:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Async::IgnoreException")," will simply ignore the exception and let the program continue"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Async::Throw"),' will "rethrow" the exception up to an eventual promise call-chain. This has the same effect than the ',(0,o.kt)("inlineCode",{parentName:"li"},"throw")," keyword, except that it is suitable for promises")),(0,o.kt)("p",null,"Exceptions in promises callbacks are propagated through an ",(0,o.kt)("inlineCode",{parentName:"p"},"exception_ptr"),". Promises can also be chained together to create a whole asynchronous pipeline:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cpp"},'auto fetchOp = fetchDatabase();\nfetchOp\n .then(\n [](const User& user) { return fetchUserInfo(user); },\n Async::Throw)\n .then(\n [](const UserInfo& info) { std::cout << "User name = " << info.name << \'\\n\'; },\n [](exception_ptr ptr) { std::cerr << "An exception occured during user retrieval\\n";}\n);\n')),(0,o.kt)("p",null,"Line 5 will propagate the exception if ",(0,o.kt)("inlineCode",{parentName:"p"},"fetchDatabase()")," failed and rejected the promise."))}m.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[489],{2509:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returns},contentTitle:function(){returnl},metadata:function(){returnc},toc:function(){returnp},default:function(){returnm}});vara=n(2122),r=n(9756),o=(n(7294),n(3905)),i=["components"],s={title:"Asynchronous HTTP programming"},l=void0,c={unversionedId:"asynchronous-http-programming",id:"asynchronous-http-programming",isDocsHomePage:!1,title:"Asynchronous HTTP programming",description:"\x3c!--",source:"@site/docs/asynchronous-http-programming.md",sourceDirName:".",slug:"/asynchronous-http-programming",permalink:"/docs/asynchronous-http-programming",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/asynchronous-http-programming.md",version:"current",frontMatter:{title:"Asynchronous HTTP programming"},sidebar:"leftSidebar",next:{title:"Headers",permalink:"/docs/headers"}},p=[],h={toc:p};functionm(e){vart=e.components,n=(0,r.Z)(e,i);return(0,o.kt)("wrapper",(0,a.Z)({},h,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Interfaces provided by Pistaches are ",(0,o.kt)("em",{parentName:"p"},"asynchronous")," and ",(0,o.kt)("em",{parentName:"p"},"non-blocking"),". Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to ",(0,o.kt)("em",{parentName:"p"},"asynchronous calls"),"."),(0,o.kt)("p",null,"An example of such a call is the ",(0,o.kt)("inlineCode",{parentName:"p"},"send()")," function provided by the ",(0,o.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," interface. This function returns the number of bytes written to the socket file descriptor associated to the connection. However, instead of returning directly the value to the caller and thus blocking the caller, it wraps the value into a component called a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise"),"."),(0,o.kt)("p",null,"A ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," is the Pistache\u2019s implementation of the ",(0,o.kt)("a",{parentName:"p",href:"https://promisesaplus.com"},"Promises/A+")," standard available in many JavaScript implementations. Simply put, during an asynchronous call, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," separates the launch of an asynchronous operation from the retrieval of its result. While the asynchronous might still be running, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise<T>")," is directly returned to the caller to retrieve the final result when it becomes available. A so called continuation can be attach to a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," to execute a callback when the result becomes available (when the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," has been resolved or fulfilled)."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cpp"},'auto res = response.send(Http::Code::Ok, "Hello World");\nres.then(\n [](ssize_t bytes) { std::cout << bytes << " bytes have been sent\\n" },\n Async::NoExcept\n);\n')),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"then()")," member is used to attach a callback to the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise"),". The first argument is a callable that will be called when the ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," has been ",(0,o.kt)("strong",{parentName:"p"},"succesfully")," resolved. If, for some reason, an error occurs during the asynchronous operation, a ",(0,o.kt)("inlineCode",{parentName:"p"},"Promise")," can be ",(0,o.kt)("strong",{parentName:"p"},"rejected")," and will then fail. In this case, the second callable will be called. ",(0,o.kt)("inlineCode",{parentName:"p"},"Async::NoExcept")," is a special callback that will call ",(0,o.kt)("a",{parentName:"p",href:"https://en.cppreference.com/w/cpp/error/terminate"},(0,o.kt)("inlineCode",{parentName:"a"},"std::terminate()"))," if the promise failed. This is the equivalent of the ",(0,o.kt)("inlineCode",{parentName:"p"},"noexcept")," keyword."),(0,o.kt)("p",null,"Other generic callbacks can also be used in this case:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Async::IgnoreException")," will simply ignore the exception and let the program continue"),(0,o.kt)("li",{parentName:"ul"},(0,o.kt)("inlineCode",{parentName:"li"},"Async::Throw"),' will "rethrow" the exception up to an eventual promise call-chain. This has the same effect than the ',(0,o.kt)("inlineCode",{parentName:"li"},"throw")," keyword, except that it is suitable for promises")),(0,o.kt)("p",null,"Exceptions in promises callbacks are propagated through an ",(0,o.kt)("inlineCode",{parentName:"p"},"exception_ptr"),". Promises can also be chained together to create a whole asynchronous pipeline:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-cpp"},'auto fetchOp = fetchDatabase();\nfetchOp\n .then(\n [](const User& user) { return fetchUserInfo(user); },\n Async::Throw)\n .then(\n [](const UserInfo& info) { std::cout << "User name = " << info.name << \'\\n\'; },\n [](exception_ptr ptr) { std::cerr << "An exception occured during user retrieval\\n";}\n);\n')),(0,o.kt)("p",null,"Line 5 will propagate the exception if ",(0,o.kt)("inlineCode",{parentName:"p"},"fetchDatabase()")," failed and rejected the promise."))}m.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[536],{2955:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returnr},contentTitle:function(){returnp},metadata:function(){returnl},toc:function(){returnd},default:function(){returnm}});vara=n(2122),i=n(9756),s=(n(7294),n(3905)),o=["components"],r={id:"http-handler",title:"HTTP handler"},p=void0,l={unversionedId:"http-handler",id:"http-handler",isDocsHomePage:!1,title:"HTTP handler",description:"\x3c!--",source:"@site/docs/http-handler.md",sourceDirName:".",slug:"/http-handler",permalink:"/docs/http-handler",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/http-handler.md",version:"current",frontMatter:{id:"http-handler",title:"HTTP handler"},sidebar:"leftSidebar",previous:{title:"Headers",permalink:"/docs/headers"},next:{title:"Getting started",permalink:"/docs/"}},d=[{value:"Sending a response",id:"sending-a-response",children:[]},{value:"Response streaming",id:"response-streaming",children:[]},{value:"Static file serving",id:"static-file-serving",children:[]},{value:"Controlling timeout",id:"controlling-timeout",children:[]}],c={toc:d};functionm(e){vart=e.components,n=(0,i.Z)(e,o);return(0,s.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("p",null,"Requests that are received by Pistache are handled by a special class called ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Handler"),". This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection."),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," function must be overriden. This function is called whenever Pistache received data and correctly parsed it as an HTTP request."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"virtual void onRequest(const Http::Request& request, Http::ResponseWriter response);\n")),(0,s.kt)("p",null,"The first argument is an object of type ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Request")," representing the request itself. It contains a bunch of informations including:"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"The resource associated to the request"),(0,s.kt)("li",{parentName:"ul"},"The query parameters"),(0,s.kt)("li",{parentName:"ul"},"The headers"),(0,s.kt)("li",{parentName:"ul"},"The body of the request")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"Request")," object gives a read-only access to these informations. You can access them through a couple of getters but can not modify them. An HTTP request is ",(0,s.kt)("strong",{parentName:"p"},"immutable"),"."),(0,s.kt)("h2",{id:"sending-a-response"},"Sending a response"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," is an object from which the final HTTP response is sent to the client. The ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," function does not return anything (",(0,s.kt)("inlineCode",{parentName:"p"},"void"),"). Instead, the response is sent through the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," class. This class provides a bunch of ",(0,s.kt)("inlineCode",{parentName:"p"},"send()")," function overloads to send the response:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"Async::Promise<ssize_t> send(Code code);\n")),(0,s.kt)("p",null,"You can use this overload to send a response with an empty body and a given HTTP Code (e.g ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Code::Ok"),")"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"Async::Promise<ssize_t> send(\n Code code,\n const std::string& body,\n const Mime::MediaType &mime = Mime::MediaType()\n);\n")),(0,s.kt)("p",null,"This overload can be used to send a response with static, fixed-size content (body). A MIME type can also be specified, which will be sent through the ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," header."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"template<size_t N>\nAsync::Promise<ssize_t> send(\n Code code,\n const char (&arr)[N],\n const Mime::MediaType& mime = Mime::MediaType()\n);\n")),(0,s.kt)("p",null,"This version can also be used to send a fixed-size response with a body except that it does not need to construct a string (no memory is allocated). The size of the content is directly deduced by the compiler. This version only works with raw string literals."),(0,s.kt)("p",null,"These functions are asynchronous, meaning that they do not return a plain old ",(0,s.kt)("inlineCode",{parentName:"p"},"ssize_t")," value indicating the number of bytes being sent, but instead a ",(0,s.kt)("inlineCode",{parentName:"p"},"Promise")," that will be fulfilled later on. See the next section for more details on asynchronous programming with Pistache."),(0,s.kt)("h2",{id:"response-streaming"},"Response streaming"),(0,s.kt)("p",null,"Sometimes, content that is to be sent back to the user can not be known in advance, thus the length can not be determined in advance. For that matter, the HTTP specification defines a special data-transfer mechanism called ",(0,s.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc7230#section-4.1"},"chunked encoding")," where data is sent in a series of ",(0,s.kt)("em",{parentName:"p"},"chunks"),". This mechanism uses the ",(0,s.kt)("inlineCode",{parentName:"p"},"Transfer-Encoding")," HTTP header in place of the ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Length")," one."),(0,s.kt)("p",null,"To stream content, Pistache provides a special ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," class. To get a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," from a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter"),", call the ",(0,s.kt)("inlineCode",{parentName:"p"},"stream()")," member function:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"auto stream = response.stream(Http::Code::Ok);\n")),(0,s.kt)("p",null,"To initate a stream, you have to pass the HTTP status code to the stream function (here ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Code::Ok")," or ",(0,s.kt)("inlineCode",{parentName:"p"},"HTTP 200"),"). The ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," class provides an ",(0,s.kt)("inlineCode",{parentName:"p"},"iostream")," like interface that overloads the ",(0,s.kt)("inlineCode",{parentName:"p"},"<<")," operator."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'stream << "PO"\nstream << "NG"\n')),(0,s.kt)("p",null,"The first line will write a chunk of size 2 with the content ",(0,s.kt)("em",{parentName:"p"},"PO")," to the stream's buffer. The second line will write a second chunk of size 2 with the content ",(0,s.kt)("em",{parentName:"p"},"NG"),". To end the stream and flush the content, use the special ",(0,s.kt)("inlineCode",{parentName:"p"},"ends")," marker:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"stream << ends\n")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"ends")," marker will write the last chunk of size 0 and send the final data over the network. To simply flush the stream's buffer without ending the stream, you can use the ",(0,s.kt)("inlineCode",{parentName:"p"},"flush")," marker:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"stream << flush\n")),(0,s.kt)("div",{className:"admonition admonition-caution alert alert--warning"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))),"Headers writing")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},"After starting a stream, headers become immutable. They must be written to the response before creating a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream"),":"),(0,s.kt)("pre",{parentName:"div"},(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'response.headers()\n .add<Header::Server>("lys")\n .add<Header::ContentType>(MIME(Text, Plain));\n\nauto stream = response.stream();\nstream << "PO" << "NG" << ends;\n')))),(0,s.kt)("h2",{id:"static-file-serving"},"Static file serving"),(0,s.kt)("p",null,"In addition to text content serving, Pistache provides a way to serve static files through the ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::serveFile")," function:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'if (request.resource() == "/doc" && request.method == Http::Method::Get) {\n Http::serveFile(response, "README.md");\n}\n')),(0,s.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Return value")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},(0,s.kt)("inlineCode",{parentName:"p"},"serveFile")," also returns a ",(0,s.kt)("inlineCode",{parentName:"p"},"Promise")," representing the total number of bytes being sent to the wire"))),(0,s.kt)("h2",{id:"controlling-timeout"},"Controlling timeout"),(0,s.kt)("p",null,"Sometimes, you might require to timeout after a certain amount of time. For example, if you are designing an HTTP API with soft real-time constraints, you will have a time constraint to send a response back to the client. That is why Pistache provides the ability to control the timeout on a per-request basis. To arm a timeout on a response, you can use the ",(0,s.kt)("inlineCode",{parentName:"p"},"timeoutAfter()")," member function directly on the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," object:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"response.timeoutAfter(std::chrono::milliseconds(500));\n")),(0,s.kt)("p",null,"This will trigger a timeout if a response has not been sent within 500 milliseconds. ",(0,s.kt)("inlineCode",{parentName:"p"},"timeoutAfter")," accepts any kind of duration."),(0,s.kt)("p",null,"When a timeout triggers, the ",(0,s.kt)("inlineCode",{parentName:"p"},"onTimeout()")," function from your handler will be called. By default, this method does nothing. If you want to handle your timeout properly, you should then override this function inside your own handler:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"void onTimeout(const Http::Request& request, Http::ResponseWriter writer) {\n request.send(Http::Code::No_Content);\n}\n")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"Request")," object that is passed to the ",(0,s.kt)("inlineCode",{parentName:"p"},"onTimeout")," is the exact same request that triggered the timeout. The ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," is a complete new writer object."),(0,s.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"ResponseWriter state")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},"Since the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," object is a complete new object, state is not preserved with the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," from the ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," callback, which means that you will have to write the complete response again, including headers and cookies."))))}m.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[536],{2955:function(e,t,n){"use strict";n.r(t),n.d(t,{frontMatter:function(){returnr},contentTitle:function(){returnl},metadata:function(){returnp},toc:function(){returnd},default:function(){returnm}});vara=n(2122),i=n(9756),s=(n(7294),n(3905)),o=["components"],r={id:"http-handler",title:"HTTP handler"},l=void0,p={unversionedId:"http-handler",id:"http-handler",isDocsHomePage:!1,title:"HTTP handler",description:"Requests that are received by Pistache are handled by a special class called Http::Handler. This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection.",source:"@site/docs/http-handler.md",sourceDirName:".",slug:"/http-handler",permalink:"/docs/http-handler",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/http-handler.md",version:"current",frontMatter:{id:"http-handler",title:"HTTP handler"},sidebar:"leftSidebar",previous:{title:"Headers",permalink:"/docs/headers"},next:{title:"Getting started",permalink:"/docs/"}},d=[{value:"Sending a response",id:"sending-a-response",children:[]},{value:"Response streaming",id:"response-streaming",children:[]},{value:"Static file serving",id:"static-file-serving",children:[]},{value:"Controlling timeout",id:"controlling-timeout",children:[]}],c={toc:d};functionm(e){vart=e.components,n=(0,i.Z)(e,o);return(0,s.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("p",null,"Requests that are received by Pistache are handled by a special class called ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Handler"),". This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection."),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," function must be overriden. This function is called whenever Pistache received data and correctly parsed it as an HTTP request."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"virtual void onRequest(const Http::Request& request, Http::ResponseWriter response);\n")),(0,s.kt)("p",null,"The first argument is an object of type ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Request")," representing the request itself. It contains a bunch of informations including:"),(0,s.kt)("ul",null,(0,s.kt)("li",{parentName:"ul"},"The resource associated to the request"),(0,s.kt)("li",{parentName:"ul"},"The query parameters"),(0,s.kt)("li",{parentName:"ul"},"The headers"),(0,s.kt)("li",{parentName:"ul"},"The body of the request")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"Request")," object gives a read-only access to these informations. You can access them through a couple of getters but can not modify them. An HTTP request is ",(0,s.kt)("strong",{parentName:"p"},"immutable"),"."),(0,s.kt)("h2",{id:"sending-a-response"},"Sending a response"),(0,s.kt)("p",null,(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," is an object from which the final HTTP response is sent to the client. The ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," function does not return anything (",(0,s.kt)("inlineCode",{parentName:"p"},"void"),"). Instead, the response is sent through the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," class. This class provides a bunch of ",(0,s.kt)("inlineCode",{parentName:"p"},"send()")," function overloads to send the response:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"Async::Promise<ssize_t> send(Code code);\n")),(0,s.kt)("p",null,"You can use this overload to send a response with an empty body and a given HTTP Code (e.g ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Code::Ok"),")"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"Async::Promise<ssize_t> send(\n Code code,\n const std::string& body,\n const Mime::MediaType &mime = Mime::MediaType()\n);\n")),(0,s.kt)("p",null,"This overload can be used to send a response with static, fixed-size content (body). A MIME type can also be specified, which will be sent through the ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Type")," header."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"template<size_t N>\nAsync::Promise<ssize_t> send(\n Code code,\n const char (&arr)[N],\n const Mime::MediaType& mime = Mime::MediaType()\n);\n")),(0,s.kt)("p",null,"This version can also be used to send a fixed-size response with a body except that it does not need to construct a string (no memory is allocated). The size of the content is directly deduced by the compiler. This version only works with raw string literals."),(0,s.kt)("p",null,"These functions are asynchronous, meaning that they do not return a plain old ",(0,s.kt)("inlineCode",{parentName:"p"},"ssize_t")," value indicating the number of bytes being sent, but instead a ",(0,s.kt)("inlineCode",{parentName:"p"},"Promise")," that will be fulfilled later on. See the next section for more details on asynchronous programming with Pistache."),(0,s.kt)("h2",{id:"response-streaming"},"Response streaming"),(0,s.kt)("p",null,"Sometimes, content that is to be sent back to the user can not be known in advance, thus the length can not be determined in advance. For that matter, the HTTP specification defines a special data-transfer mechanism called ",(0,s.kt)("a",{parentName:"p",href:"https://tools.ietf.org/html/rfc7230#section-4.1"},"chunked encoding")," where data is sent in a series of ",(0,s.kt)("em",{parentName:"p"},"chunks"),". This mechanism uses the ",(0,s.kt)("inlineCode",{parentName:"p"},"Transfer-Encoding")," HTTP header in place of the ",(0,s.kt)("inlineCode",{parentName:"p"},"Content-Length")," one."),(0,s.kt)("p",null,"To stream content, Pistache provides a special ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," class. To get a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," from a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter"),", call the ",(0,s.kt)("inlineCode",{parentName:"p"},"stream()")," member function:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"auto stream = response.stream(Http::Code::Ok);\n")),(0,s.kt)("p",null,"To initate a stream, you have to pass the HTTP status code to the stream function (here ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::Code::Ok")," or ",(0,s.kt)("inlineCode",{parentName:"p"},"HTTP 200"),"). The ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream")," class provides an ",(0,s.kt)("inlineCode",{parentName:"p"},"iostream")," like interface that overloads the ",(0,s.kt)("inlineCode",{parentName:"p"},"<<")," operator."),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'stream << "PO"\nstream << "NG"\n')),(0,s.kt)("p",null,"The first line will write a chunk of size 2 with the content ",(0,s.kt)("em",{parentName:"p"},"PO")," to the stream's buffer. The second line will write a second chunk of size 2 with the content ",(0,s.kt)("em",{parentName:"p"},"NG"),". To end the stream and flush the content, use the special ",(0,s.kt)("inlineCode",{parentName:"p"},"ends")," marker:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"stream << ends\n")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"ends")," marker will write the last chunk of size 0 and send the final data over the network. To simply flush the stream's buffer without ending the stream, you can use the ",(0,s.kt)("inlineCode",{parentName:"p"},"flush")," marker:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"stream << flush\n")),(0,s.kt)("div",{className:"admonition admonition-caution alert alert--warning"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"16",height:"16",viewBox:"0 0 16 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"}))),"Headers writing")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},"After starting a stream, headers become immutable. They must be written to the response before creating a ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseStream"),":"),(0,s.kt)("pre",{parentName:"div"},(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'response.headers()\n .add<Header::Server>("lys")\n .add<Header::ContentType>(MIME(Text, Plain));\n\nauto stream = response.stream();\nstream << "PO" << "NG" << ends;\n')))),(0,s.kt)("h2",{id:"static-file-serving"},"Static file serving"),(0,s.kt)("p",null,"In addition to text content serving, Pistache provides a way to serve static files through the ",(0,s.kt)("inlineCode",{parentName:"p"},"Http::serveFile")," function:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},'if (request.resource() == "/doc" && request.method == Http::Method::Get) {\n Http::serveFile(response, "README.md");\n}\n')),(0,s.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Return value")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},(0,s.kt)("inlineCode",{parentName:"p"},"serveFile")," also returns a ",(0,s.kt)("inlineCode",{parentName:"p"},"Promise")," representing the total number of bytes being sent to the wire"))),(0,s.kt)("h2",{id:"controlling-timeout"},"Controlling timeout"),(0,s.kt)("p",null,"Sometimes, you might require to timeout after a certain amount of time. For example, if you are designing an HTTP API with soft real-time constraints, you will have a time constraint to send a response back to the client. That is why Pistache provides the ability to control the timeout on a per-request basis. To arm a timeout on a response, you can use the ",(0,s.kt)("inlineCode",{parentName:"p"},"timeoutAfter()")," member function directly on the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," object:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"response.timeoutAfter(std::chrono::milliseconds(500));\n")),(0,s.kt)("p",null,"This will trigger a timeout if a response has not been sent within 500 milliseconds. ",(0,s.kt)("inlineCode",{parentName:"p"},"timeoutAfter")," accepts any kind of duration."),(0,s.kt)("p",null,"When a timeout triggers, the ",(0,s.kt)("inlineCode",{parentName:"p"},"onTimeout()")," function from your handler will be called. By default, this method does nothing. If you want to handle your timeout properly, you should then override this function inside your own handler:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-cpp"},"void onTimeout(const Http::Request& request, Http::ResponseWriter writer) {\n request.send(Http::Code::No_Content);\n}\n")),(0,s.kt)("p",null,"The ",(0,s.kt)("inlineCode",{parentName:"p"},"Request")," object that is passed to the ",(0,s.kt)("inlineCode",{parentName:"p"},"onTimeout")," is the exact same request that triggered the timeout. The ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," is a complete new writer object."),(0,s.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,s.kt)("div",{parentName:"div",className:"admonition-heading"},(0,s.kt)("h5",{parentName:"div"},(0,s.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,s.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,s.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"ResponseWriter state")),(0,s.kt)("div",{parentName:"div",className:"admonition-content"},(0,s.kt)("p",{parentName:"div"},"Since the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," object is a complete new object, state is not preserved with the ",(0,s.kt)("inlineCode",{parentName:"p"},"ResponseWriter")," from the ",(0,s.kt)("inlineCode",{parentName:"p"},"onRequest()")," callback, which means that you will have to write the complete response again, including headers and cookies."))))}m.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[1],{6069:function(e,t,a){"use strict";a.r(t),a.d(t,{frontMatter:function(){returns},contentTitle:function(){returnl},metadata:function(){returnp},toc:function(){returnd},default:function(){returnc}});varn=a(2122),i=a(9756),r=(a(7294),a(3905)),o=["components"],s={title:"Routing"},l=void0,p={unversionedId:"routing",id:"routing",isDocsHomePage:!1,title:"Routing",description:"HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:",source:"@site/docs/routing.md",sourceDirName:".",slug:"/routing",permalink:"/docs/routing",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/routing.md",version:"current",frontMatter:{title:"Routing"},sidebar:"leftSidebar",previous:{title:"REST description",permalink:"/docs/rest-description"}},d=[{value:"HTTP methods",id:"http-methods",children:[]},{value:"Route patterns",id:"route-patterns",children:[{value:"Static routes",id:"static-routes",children:[]},{value:"Dynamic routes",id:"dynamic-routes",children:[]}]},{value:"Defining routes",id:"defining-routes",children:[{value:"Callbacks",id:"callbacks",children:[]},{value:"Installing the handler",id:"installing-the-handler",children:[]}]}],u={toc:d};functionc(e){vart=e.components,a=(0,i.Z)(e,o);return(0,r.kt)("wrapper",(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-javascript"},"GET /users/1\n")),(0,r.kt)("p",null,"Here, ",(0,r.kt)("inlineCode",{parentName:"p"},"GET")," is the verb and ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/1")," is the associated resource."),(0,r.kt)("h2",{id:"http-methods"},"HTTP methods"),(0,r.kt)("p",null,"A bunch of HTTP methods (verbs) are supported by Pistache:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"GET"),": The ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," method is used by the client (e.g browser) to retrieve a resource identified by an URI. For example, to retrieve an user identified by an id, a client will issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users/:id")," Request-URI."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"POST"),": the ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," method is used to post or send new information to a certain resource. The server will then read and store the data associated to the request. ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," is a common way of transmitting data from an HTML form. ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," can also be used to create a new resource or update information of an existing resource. For example, to create a new user, a client will issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users")," path with the data of the user to create in its body."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"PUT"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"PUT")," is very similar to ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," except that ",(0,r.kt)("inlineCode",{parentName:"li"},"PUT")," is idempotent, meaning that two requests to the same Request-URI with the same identical content should have the same effect and should produce the same result."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"DELETE"),": the ",(0,r.kt)("inlineCode",{parentName:"li"},"DELETE")," method is used to delete a resource associated to a given Request-URI. For example, to remove an user, a client might issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"DELETE")," call to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users/:id")," Request-URI.")),(0,r.kt)("p",null,"To sum up, ",(0,r.kt)("inlineCode",{parentName:"p"},"POST")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"PUT")," are used to Create and/or Update, ",(0,r.kt)("inlineCode",{parentName:"p"},"GET")," is used to Read and ",(0,r.kt)("inlineCode",{parentName:"p"},"DELETE")," is used to Delete information."),(0,r.kt)("h2",{id:"route-patterns"},"Route patterns"),(0,r.kt)("h3",{id:"static-routes"},"Static routes"),(0,r.kt)("p",null,"Static routes are the simplest ones as they do rely on dynamic parts of the Request-URI. For example ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/all")," is a static route that will exactly match the ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/all")," Request-URI."),(0,r.kt)("h3",{id:"dynamic-routes"},"Dynamic routes"),(0,r.kt)("p",null,"However, it is often useful to define routes that have dynamic parts. For example, to retrieve a specific user by its id, the id is needed to query the storage. Dynamic routes thus have parameters that are then matched one by one by the HTTP router. In a dynamic route, parameters are identified by a column ",(0,r.kt)("inlineCode",{parentName:"p"},":")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"/users/:id")),(0,r.kt)("p",null,"Here, ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," is a dynamic parameter. When a request comes in, the router will try to match the ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," parameter to the corresponding part of the request. For example, if the server receives a request to ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/13"),", the router will match the ",(0,r.kt)("inlineCode",{parentName:"p"},"13")," value to the ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," parameter."),(0,r.kt)("p",null,"Some parameters, like ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," are named. However, Pistache also allows ",(0,r.kt)("em",{parentName:"p"},"splat")," (wildcard) parameters, identified by a star ",(0,r.kt)("inlineCode",{parentName:"p"},"*"),":"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"/link/*/to/*")),(0,r.kt)("h2",{id:"defining-routes"},"Defining routes"),(0,r.kt)("p",null,"To define your routes, you first have to instantiate an HTTP router:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Router router;\n")),(0,r.kt)("p",null,"Then, use the ",(0,r.kt)("inlineCode",{parentName:"p"},"Routes::<Method>()")," functions to add some routes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},'Routes::Get(router, "/users/all", Routes::bind(&UsersApi::getAllUsers, this));\nRoutes::Post(router, "/users/:id", Routes::bind(&UsersApi::getUserId, this));\nRoutes::Get(router, "/link/*/to/*", Routes::bind(&UsersApi::linkUsers, this));\n')),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Routes::bind")," is a special function that will generate a corresponding C++ callback that will then be called by the router if a given route matches the Request-URI."),(0,r.kt)("h3",{id:"callbacks"},"Callbacks"),(0,r.kt)("p",null,"A C++ callback associated to a route must have the following signature:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"void(const Rest::Request&, Http::ResponseWriter);\n")),(0,r.kt)("p",null,"A callback can either be a non-static free or member function. For member functions, a pointer to the corresponding instance must be passed to the Routes::bind function so that the router knows on which instance to invoke the member function."),(0,r.kt)("p",null,"The first parameter of the callback is ",(0,r.kt)("inlineCode",{parentName:"p"},"Rest::Request")," and not an ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Request"),". A ",(0,r.kt)("inlineCode",{parentName:"p"},"Rest::Request")," is an ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Request")," with additional functions. Named and splat parameters are for example retrieved through this object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},'void UsersApi::getUserId(const Rest::Request& request, Http::ResponseWriter response) {\n auto id = request.param(":id").as<int>();\n // ...\n}\n\nvoid UsersApi::linkUsers(const Rest::Request& request, Http::ResponseWriter response) {\n auto u1 = request.splatAt(0).as<std::string>();\n auto u2 = request.splatAt(1).as<std::string>();\n // ...\n}\n')),(0,r.kt)("p",null,"As you can see, parameters are also typed. To cast a parameter to the appropriate type, use the ",(0,r.kt)("inlineCode",{parentName:"p"},"as<T>")," member template."),(0,r.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,r.kt)("div",{parentName:"div",className:"admonition-heading"},(0,r.kt)("h5",{parentName:"div"},(0,r.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,r.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,r.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Cast safety")),(0,r.kt)("div",{parentName:"div",className:"admonition-content"},(0,r.kt)("p",{parentName:"div"},"An exception will be thrown if the parameter can not be casted to the right type"))),(0,r.kt)("h3",{id:"installing-the-handler"},"Installing the handler"),(0,r.kt)("p",null,"Once the routes have been defined, the final ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Handler")," must be set to the HTTP Endpoint. To retrieve the handler, just call the ",(0,r.kt)("inlineCode",{parentName:"p"},"handler()")," member function on the router object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"endpoint.setHandler(router.handler());\n")))}c.isMDXComponent=!0}}]);
(self.webpackChunkpistache_io=self.webpackChunkpistache_io||[]).push([[1],{6069:function(e,t,a){"use strict";a.r(t),a.d(t,{frontMatter:function(){returno},contentTitle:function(){returnl},metadata:function(){returnp},toc:function(){returnd},default:function(){returnc}});varn=a(2122),i=a(9756),r=(a(7294),a(3905)),s=["components"],o={title:"Routing"},l=void0,p={unversionedId:"routing",id:"routing",isDocsHomePage:!1,title:"Routing",description:"\x3c!--",source:"@site/docs/routing.md",sourceDirName:".",slug:"/routing",permalink:"/docs/routing",editUrl:"https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/routing.md",version:"current",frontMatter:{title:"Routing"},sidebar:"leftSidebar",previous:{title:"REST description",permalink:"/docs/rest-description"}},d=[{value:"HTTP methods",id:"http-methods",children:[]},{value:"Route patterns",id:"route-patterns",children:[{value:"Static routes",id:"static-routes",children:[]},{value:"Dynamic routes",id:"dynamic-routes",children:[]}]},{value:"Defining routes",id:"defining-routes",children:[{value:"Callbacks",id:"callbacks",children:[]},{value:"Installing the handler",id:"installing-the-handler",children:[]}]}],u={toc:d};functionc(e){vart=e.components,a=(0,i.Z)(e,s);return(0,r.kt)("wrapper",(0,n.Z)({},u,a,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-javascript"},"GET /users/1\n")),(0,r.kt)("p",null,"Here, ",(0,r.kt)("inlineCode",{parentName:"p"},"GET")," is the verb and ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/1")," is the associated resource."),(0,r.kt)("h2",{id:"http-methods"},"HTTP methods"),(0,r.kt)("p",null,"A bunch of HTTP methods (verbs) are supported by Pistache:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"GET"),": The ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," method is used by the client (e.g browser) to retrieve a resource identified by an URI. For example, to retrieve an user identified by an id, a client will issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"GET")," to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users/:id")," Request-URI."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"POST"),": the ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," method is used to post or send new information to a certain resource. The server will then read and store the data associated to the request. ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," is a common way of transmitting data from an HTML form. ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," can also be used to create a new resource or update information of an existing resource. For example, to create a new user, a client will issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users")," path with the data of the user to create in its body."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"PUT"),": ",(0,r.kt)("inlineCode",{parentName:"li"},"PUT")," is very similar to ",(0,r.kt)("inlineCode",{parentName:"li"},"POST")," except that ",(0,r.kt)("inlineCode",{parentName:"li"},"PUT")," is idempotent, meaning that two requests to the same Request-URI with the same identical content should have the same effect and should produce the same result."),(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("em",{parentName:"li"},"DELETE"),": the ",(0,r.kt)("inlineCode",{parentName:"li"},"DELETE")," method is used to delete a resource associated to a given Request-URI. For example, to remove an user, a client might issue a ",(0,r.kt)("inlineCode",{parentName:"li"},"DELETE")," call to the ",(0,r.kt)("inlineCode",{parentName:"li"},"/users/:id")," Request-URI.")),(0,r.kt)("p",null,"To sum up, ",(0,r.kt)("inlineCode",{parentName:"p"},"POST")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"PUT")," are used to Create and/or Update, ",(0,r.kt)("inlineCode",{parentName:"p"},"GET")," is used to Read and ",(0,r.kt)("inlineCode",{parentName:"p"},"DELETE")," is used to Delete information."),(0,r.kt)("h2",{id:"route-patterns"},"Route patterns"),(0,r.kt)("h3",{id:"static-routes"},"Static routes"),(0,r.kt)("p",null,"Static routes are the simplest ones as they do rely on dynamic parts of the Request-URI. For example ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/all")," is a static route that will exactly match the ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/all")," Request-URI."),(0,r.kt)("h3",{id:"dynamic-routes"},"Dynamic routes"),(0,r.kt)("p",null,"However, it is often useful to define routes that have dynamic parts. For example, to retrieve a specific user by its id, the id is needed to query the storage. Dynamic routes thus have parameters that are then matched one by one by the HTTP router. In a dynamic route, parameters are identified by a column ",(0,r.kt)("inlineCode",{parentName:"p"},":")),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"/users/:id")),(0,r.kt)("p",null,"Here, ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," is a dynamic parameter. When a request comes in, the router will try to match the ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," parameter to the corresponding part of the request. For example, if the server receives a request to ",(0,r.kt)("inlineCode",{parentName:"p"},"/users/13"),", the router will match the ",(0,r.kt)("inlineCode",{parentName:"p"},"13")," value to the ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," parameter."),(0,r.kt)("p",null,"Some parameters, like ",(0,r.kt)("inlineCode",{parentName:"p"},":id")," are named. However, Pistache also allows ",(0,r.kt)("em",{parentName:"p"},"splat")," (wildcard) parameters, identified by a star ",(0,r.kt)("inlineCode",{parentName:"p"},"*"),":"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"/link/*/to/*")),(0,r.kt)("h2",{id:"defining-routes"},"Defining routes"),(0,r.kt)("p",null,"To define your routes, you first have to instantiate an HTTP router:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"Http::Router router;\n")),(0,r.kt)("p",null,"Then, use the ",(0,r.kt)("inlineCode",{parentName:"p"},"Routes::<Method>()")," functions to add some routes:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},'Routes::Get(router, "/users/all", Routes::bind(&UsersApi::getAllUsers, this));\nRoutes::Post(router, "/users/:id", Routes::bind(&UsersApi::getUserId, this));\nRoutes::Get(router, "/link/*/to/*", Routes::bind(&UsersApi::linkUsers, this));\n')),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"Routes::bind")," is a special function that will generate a corresponding C++ callback that will then be called by the router if a given route matches the Request-URI."),(0,r.kt)("h3",{id:"callbacks"},"Callbacks"),(0,r.kt)("p",null,"A C++ callback associated to a route must have the following signature:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"void(const Rest::Request&, Http::ResponseWriter);\n")),(0,r.kt)("p",null,"A callback can either be a non-static free or member function. For member functions, a pointer to the corresponding instance must be passed to the Routes::bind function so that the router knows on which instance to invoke the member function."),(0,r.kt)("p",null,"The first parameter of the callback is ",(0,r.kt)("inlineCode",{parentName:"p"},"Rest::Request")," and not an ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Request"),". A ",(0,r.kt)("inlineCode",{parentName:"p"},"Rest::Request")," is an ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Request")," with additional functions. Named and splat parameters are for example retrieved through this object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},'void UsersApi::getUserId(const Rest::Request& request, Http::ResponseWriter response) {\n auto id = request.param(":id").as<int>();\n // ...\n}\n\nvoid UsersApi::linkUsers(const Rest::Request& request, Http::ResponseWriter response) {\n auto u1 = request.splatAt(0).as<std::string>();\n auto u2 = request.splatAt(1).as<std::string>();\n // ...\n}\n')),(0,r.kt)("p",null,"As you can see, parameters are also typed. To cast a parameter to the appropriate type, use the ",(0,r.kt)("inlineCode",{parentName:"p"},"as<T>")," member template."),(0,r.kt)("div",{className:"admonition admonition-note alert alert--secondary"},(0,r.kt)("div",{parentName:"div",className:"admonition-heading"},(0,r.kt)("h5",{parentName:"div"},(0,r.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,r.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,r.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"}))),"Cast safety")),(0,r.kt)("div",{parentName:"div",className:"admonition-content"},(0,r.kt)("p",{parentName:"div"},"An exception will be thrown if the parameter can not be casted to the right type"))),(0,r.kt)("h3",{id:"installing-the-handler"},"Installing the handler"),(0,r.kt)("p",null,"Once the routes have been defined, the final ",(0,r.kt)("inlineCode",{parentName:"p"},"Http::Handler")," must be set to the HTTP Endpoint. To retrieve the handler, just call the ",(0,r.kt)("inlineCode",{parentName:"p"},"handler()")," member function on the router object:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-cpp"},"endpoint.setHandler(router.handler());\n")))}c.isMDXComponent=!0}}]);
<titledata-react-helmet="true">Asynchronous HTTP programming | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/asynchronous-http-programming"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="Asynchronous HTTP programming | Pistache"><metadata-react-helmet="true"name="description"content="Interfaces provided by Pistaches are asynchronous and non-blocking. Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to asynchronous calls."><metadata-react-helmet="true"property="og:description"content="Interfaces provided by Pistaches are asynchronous and non-blocking. Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to asynchronous calls."><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/asynchronous-http-programming"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/asynchronous-http-programming"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/asynchronous-http-programming"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<div><ahref="#main"class="skipToContent_1oUP shadow--md">Skip to main content</a></div><navclass="navbar navbar--fixed-top"><divclass="navbar__inner"><divclass="navbar__items"><buttonaria-label="Navigation bar toggle"class="navbar__toggle clean-btn"type="button"tabindex="0"><svgwidth="30"height="30"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a><aaria-current="page"class="navbar__item navbar__link navbar__link--active"href="/docs/">Docs</a></div><divclass="navbar__items navbar__items--right"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="navbar__item navbar__link header-github-link"aria-label="GitHub repository"></a><divclass="react-toggle displayOnlyInLargeViewport_GrZ2 react-toggle--disabled"><divclass="react-toggle-track"role="button"tabindex="-1"><divclass="react-toggle-track-check"><spanclass="toggle_71bT">🌜</span></div><divclass="react-toggle-track-x"><spanclass="toggle_71bT">🌞</span></div><divclass="react-toggle-thumb"></div></div><inputtype="checkbox"class="react-toggle-screenreader-only"aria-label="Switch between dark and light mode"></div></div></div><divrole="presentation"class="navbar-sidebar__backdrop"></div><divclass="navbar-sidebar"><divclass="navbar-sidebar__brand"><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a></div><divclass="navbar-sidebar__items"><divclass="menu"><ulclass="menu__list"><liclass="menu__list-item"><aaria-current="page"class="menu__link navbar__link--active"href="/docs/">Docs</a></li><liclass="menu__list-item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="menu__link header-github-link"aria-label="GitHub repository"></a></li></ul></div></div></div></nav><divclass="main-wrapper docs-wrapper doc-page"><divclass="docPage_31aa"><asideclass="docSidebarContainer_3Kbt"><divclass="sidebar_15mo"><navclass="menu menu--responsive thin-scrollbar menu_Bmed"aria-label="Sidebar navigation"><buttonaria-label="Open menu"aria-haspopup="true"class="button button--secondary button--sm menu__button"type="button"><svgclass="sidebarMenuIcon_fgN0"width="24"height="24"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ulclass="menu__list"><liclass="menu__list-item"><aaria-current="page"class="menu__link menu__link--active active"href="/docs/asynchronous-http-programming">Asynchronous HTTP programming</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/headers">Headers</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/http-handler">HTTP handler</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/">Getting started</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/rest-description">REST description</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/routing">Routing</a></li></ul></nav></div></aside><mainclass="docMainContainer_3ufF"><divclass="container padding-top--md padding-bottom--lg docItemWrapper_3FMP"><divclass="row"><divclass="col docItemCol_3FnS"><divclass="docItemContainer_33ec"><article><divclass="markdown"><header><h1class="h1Heading_27L5">Asynchronous HTTP programming</h1></header><p>Interfaces provided by Pistaches are <em>asynchronous</em> and <em>non-blocking</em>. Asynchronous programming allows for code to continue executing even if the result of a given call is not available yet. Calls that provide an asynchronous interface are referred to <em>asynchronous calls</em>.</p><p>An example of such a call is the <code>send()</code> function provided by the <code>ResponseWriter</code> interface. This function returns the number of bytes written to the socket file descriptor associated to the connection. However, instead of returning directly the value to the caller and thus blocking the caller, it wraps the value into a component called a <code>Promise</code>.</p><p>A <code>Promise</code> is the Pistache’s implementation of the <ahref="https://promisesaplus.com"target="_blank"rel="noopener noreferrer">Promises/A+</a> standard available in many JavaScript implementations. Simply put, during an asynchronous call, a <code>Promise</code> separates the launch of an asynchronous operation from the retrieval of its result. While the asynchronous might still be running, a <code>Promise<T></code> is directly returned to the caller to retrieve the final result when it becomes available. A so called continuation can be attach to a <code>Promise</code> to execute a callback when the result becomes available (when the <code>Promise</code> has been resolved or fulfilled).</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> res </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">send</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Code</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Ok</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"Hello World"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">res</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">then</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">[</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">]</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">ssize_t bytes</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"> std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">cout </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"> bytes </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">" bytes have been sent\n"</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"> Async</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">NoExcept</span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>The <code>then()</code> member is used to attach a callback to the <code>Promise</code>. The first argument is a callable that will be called when the <code>Promise</code> has been <strong>succesfully</strong> resolved. If, for some reason, an error occurs during the asynchronous operation, a <code>Promise</code> can be <strong>rejected</strong> and will then fail. In this case, the second callable will be called. <code>Async::NoExcept</code> is a special callback that will call <ahref="https://en.cppreference.com/w/cpp/error/terminate"target="_blank"rel="noopener noreferrer"><code>std::terminate()</code></a> if the promise failed. This is the equivalent of the <code>noexcept</code> keyword.</p><p>Other generic callbacks can also be used in this case:</p><ul><li><code>Async::IgnoreException</code> will simply ignore the exception and let the program continue</li><li><code>Async::Throw</code> will "rethrow" the exception up to an eventual promise call-chain. This has the same effect than the <code>throw</code> keyword, except that it is suitable for promises</li></ul><p>Exceptions in promises callbacks are propagated through an <code>exception_ptr</code>. Promises can also be chained together to create a whole asynchronous pipeline:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> fetchOp </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">fetchDatabase</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">fetchOp</span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">then</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">[</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">]</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> User</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> user</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">return</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">fetchUserInfo</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">user</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"> Async</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Throw</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">then</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">[</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">]</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> UserInfo</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> info</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"> std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">cout </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"User name = "</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"> info</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">name </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">'\n'</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">[</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">]</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">exception_ptr ptr</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"> std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">cerr </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"An exception occured during user retrieval\n"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>Line 5 will propagate the exception if <code>fetchDatabase()</code> failed and rejected the promise.</p></div><footerclass="row docusaurus-mt-lg"><divclass="col"><ahref="https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/asynchronous-http-programming.md"target="_blank"rel="noreferrer noopener"><svgfill="currentColor"height="20"width="20"viewBox="0 0 40 40"class="iconEdit_2_ui"aria-hidden="true"><g><pathd="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><divclass="col lastUpdated_3DPF"></div></footer></article><navclass="pagination-nav docusaurus-mt-lg"aria-label="Docs pages navigation"><divclass="pagination-nav__item"></div><divclass="pagination-nav__item pagination-nav__item--next"><aclass="pagination-nav__link"href="/docs/headers"><divclass="pagination-nav__sublabel">Next</div><divclass="pagination-nav__label">Headers »</div></a></div></nav></div></div><divclass="col col--3"><divclass="tableOfContents_35-E thin-scrollbar"></div></div></div></div></main></div></div><footerclass="footer footer--dark"><divclass="container"><divclass="row footer__links"><divclass="col footer__col"><divclass="footer__title">Docs</div><ulclass="footer__items"><liclass="footer__item"><aclass="footer__link-item"href="/docs/">Quickstart</a></li><liclass="footer__item"><aclass="footer__link-item"href="/docs/http-handler/">User guide</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">Community</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://stackoverflow.com/questions/tagged/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">Stack Overflow</a></li><liclass="footer__item"><ahref="https://web.libera.chat/#pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">#pistache on Libera.Chat</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">More</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">GitHub</a></li></ul></div></div><divclass="footer__bottom text--center"><divclass="footer__copyright">Pistache, 2015 - 2021</div></div></div></footer></div>
<titledata-react-helmet="true">HTTP handler | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/http-handler"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="HTTP handler | Pistache"><metadata-react-helmet="true"name="description"content="Requests that are received by Pistache are handled by a special class called Http::Handler. This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection."><metadata-react-helmet="true"property="og:description"content="Requests that are received by Pistache are handled by a special class called Http::Handler. This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection."><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/http-handler"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/http-handler"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/http-handler"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<div><ahref="#main"class="skipToContent_1oUP shadow--md">Skip to main content</a></div><navclass="navbar navbar--fixed-top"><divclass="navbar__inner"><divclass="navbar__items"><buttonaria-label="Navigation bar toggle"class="navbar__toggle clean-btn"type="button"tabindex="0"><svgwidth="30"height="30"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a><aaria-current="page"class="navbar__item navbar__link navbar__link--active"href="/docs/">Docs</a></div><divclass="navbar__items navbar__items--right"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="navbar__item navbar__link header-github-link"aria-label="GitHub repository"></a><divclass="react-toggle displayOnlyInLargeViewport_GrZ2 react-toggle--disabled"><divclass="react-toggle-track"role="button"tabindex="-1"><divclass="react-toggle-track-check"><spanclass="toggle_71bT">🌜</span></div><divclass="react-toggle-track-x"><spanclass="toggle_71bT">🌞</span></div><divclass="react-toggle-thumb"></div></div><inputtype="checkbox"class="react-toggle-screenreader-only"aria-label="Switch between dark and light mode"></div></div></div><divrole="presentation"class="navbar-sidebar__backdrop"></div><divclass="navbar-sidebar"><divclass="navbar-sidebar__brand"><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a></div><divclass="navbar-sidebar__items"><divclass="menu"><ulclass="menu__list"><liclass="menu__list-item"><aaria-current="page"class="menu__link navbar__link--active"href="/docs/">Docs</a></li><liclass="menu__list-item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="menu__link header-github-link"aria-label="GitHub repository"></a></li></ul></div></div></div></nav><divclass="main-wrapper docs-wrapper doc-page"><divclass="docPage_31aa"><asideclass="docSidebarContainer_3Kbt"><divclass="sidebar_15mo"><navclass="menu menu--responsive thin-scrollbar menu_Bmed"aria-label="Sidebar navigation"><buttonaria-label="Open menu"aria-haspopup="true"class="button button--secondary button--sm menu__button"type="button"><svgclass="sidebarMenuIcon_fgN0"width="24"height="24"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ulclass="menu__list"><liclass="menu__list-item"><aclass="menu__link"href="/docs/asynchronous-http-programming">Asynchronous HTTP programming</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/headers">Headers</a></li><liclass="menu__list-item"><aaria-current="page"class="menu__link menu__link--active active"href="/docs/http-handler">HTTP handler</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/">Getting started</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/rest-description">REST description</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/routing">Routing</a></li></ul></nav></div></aside><mainclass="docMainContainer_3ufF"><divclass="container padding-top--md padding-bottom--lg docItemWrapper_3FMP"><divclass="row"><divclass="col docItemCol_3FnS"><divclass="docItemContainer_33ec"><article><divclass="markdown"><header><h1class="h1Heading_27L5">HTTP handler</h1></header><p>Requests that are received by Pistache are handled by a special class called <code>Http::Handler</code>. This class declares a bunch of virtual methods that can be overriden to handle special events that occur on the socket and/or connection.</p><p>The <code>onRequest()</code> function must be overriden. This function is called whenever Pistache received data and correctly parsed it as an HTTP request.</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">virtual</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">void</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">onRequest</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Request</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ResponseWriter response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>The first argument is an object of type <code>Http::Request</code> representing the request itself. It contains a bunch of informations including:</p><ul><li>The resource associated to the request</li><li>The query parameters</li><li>The headers</li><li>The body of the request</li></ul><p>The <code>Request</code> object gives a read-only access to these informations. You can access them through a couple of getters but can not modify them. An HTTP request is <strong>immutable</strong>.</p><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="sending-a-response"></a>Sending a response<aclass="hash-link"href="#sending-a-response"title="Direct link to heading">#</a></h2><p><code>ResponseWriter</code> is an object from which the final HTTP response is sent to the client. The <code>onRequest()</code> function does not return anything (<code>void</code>). Instead, the response is sent through the <code>ResponseWriter</code> class. This class provides a bunch of <code>send()</code> function overloads to send the response:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">Async</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Promise</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">ssize_t</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">send</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">Code code</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>You can use this overload to send a response with an empty body and a given HTTP Code (e.g <code>Http::Code::Ok</code>)</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">Async</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Promise</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">ssize_t</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">send</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"> Code code</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">string</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> body</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Mime</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">MediaType </span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain">mime </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Mime</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">MediaType</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>This overload can be used to send a response with static, fixed-size content (body). A MIME type can also be specified, which will be sent through the <code>Content-Type</code> header.</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">template</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">size_t N</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">Async</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Promise</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">ssize_t</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">send</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"> Code code</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">char</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain">arr</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">[</span><spanclass="token plain">N</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">]</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Mime</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">MediaType</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> mime </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Mime</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">MediaType</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>This version can also be used to send a fixed-size response with a body except that it does not need to construct a string (no memory is allocated). The size of the content is directly deduced by the compiler. This version only works with raw string literals.</p><p>These functions are asynchronous, meaning that they do not return a plain old <code>ssize_t</code> value indicating the number of bytes being sent, but instead a <code>Promise</code> that will be fulfilled later on. See the next section for more details on asynchronous programming with Pistache.</p><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="response-streaming"></a>Response streaming<aclass="hash-link"href="#response-streaming"title="Direct link to heading">#</a></h2><p>Sometimes, content that is to be sent back to the user can not be known in advance, thus the length can not be determined in advance. For that matter, the HTTP specification defines a special data-transfer mechanism called <ahref="https://tools.ietf.org/html/rfc7230#section-4.1"target="_blank"rel="noopener noreferrer">chunked encoding</a> where data is sent in a series of <em>chunks</em>. This mechanism uses the <code>Transfer-Encoding</code> HTTP header in place of the <code>Content-Length</code> one.</p><p>To stream content, Pistache provides a special <code>ResponseStream</code> class. To get a <code>ResponseStream</code> from a <code>ResponseWriter</code>, call the <code>stream()</code> member function:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">stream</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Code</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Ok</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>To initate a stream, you have to pass the HTTP status code to the stream function (here <code>Http::Code::Ok</code> or <code>HTTP 200</code>). The <code>ResponseStream</code> class provides an <code>iostream</code> like interface that overloads the <code><<</code> operator.</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"PO"</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"NG"</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>The first line will write a chunk of size 2 with the content <em>PO</em> to the stream's buffer. The second line will write a second chunk of size 2 with the content <em>NG</em>. To end the stream and flush the content, use the special <code>ends</code> marker:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"> ends</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>The <code>ends</code> marker will write the last chunk of size 0 and send the final data over the network. To simply flush the stream's buffer without ending the stream, you can use the <code>flush</code> marker:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"> flush</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><divclass="admonition admonition-caution alert alert--warning"><divclass="admonition-heading"><h5><spanclass="admonition-icon"><svgxmlns="http://www.w3.org/2000/svg"width="16"height="16"viewBox="0 0 16 16"><pathfill-rule="evenodd"d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>Headers writing</h5></div><divclass="admonition-content"><p>After starting a stream, headers become immutable. They must be written to the response before creating a <code>ResponseStream</code>:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">headers</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">add</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">Header</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Server</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token string"style="color:rgb(195, 232, 141)">"lys"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">add</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">Header</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ContentType</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token function"style="color:rgb(130, 170, 255)">MIME</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">Text</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Plain</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"style="display:inline-block">
</span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">stream</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">stream </span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"PO"</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"NG"</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)"><<</span><spanclass="token plain"> ends</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div></div></div><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="static-file-serving"></a>Static file serving<aclass="hash-link"href="#static-file-serving"title="Direct link to heading">#</a></h2><p>In addition to text content serving, Pistache provides a way to serve static files through the <code>Http::serveFile</code> function:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">if</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">resource</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)">==</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"/doc"</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)">&&</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">method </span><spanclass="token operator"style="color:rgb(137, 221, 255)">==</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Method</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Get</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">serveFile</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"README.md"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><divclass="admonition admonition-note alert alert--secondary"><divclass="admonition-heading"><h5><spanclass="admonition-icon"><svgxmlns="http://www.w3.org/2000/svg"width="14"height="16"viewBox="0 0 14 16"><pathfill-rule="evenodd"d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>Return value</h5></div><divclass="admonition-content"><p><code>serveFile</code> also returns a <code>Promise</code> representing the total number of bytes being sent to the wire</p></div></div><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="controlling-timeout"></a>Controlling timeout<aclass="hash-link"href="#controlling-timeout"title="Direct link to heading">#</a></h2><p>Sometimes, you might require to timeout after a certain amount of time. For example, if you are designing an HTTP API with soft real-time constraints, you will have a time constraint to send a response back to the client. That is why Pistache provides the ability to control the timeout on a per-request basis. To arm a timeout on a response, you can use the <code>timeoutAfter()</code> member function directly on the <code>ResponseWriter</code> object:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">timeoutAfter</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">chrono</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">milliseconds</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token number"style="color:rgb(247, 140, 108)">500</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>This will trigger a timeout if a response has not been sent within 500 milliseconds. <code>timeoutAfter</code> accepts any kind of duration.</p><p>When a timeout triggers, the <code>onTimeout()</code> function from your handler will be called. By default, this method does nothing. If you want to handle your timeout properly, you should then override this function inside your own handler:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">void</span><spanclass="token plain"></span><spanclass="token function"style="color:rgb(130, 170, 255)">onTimeout</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Request</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ResponseWriter writer</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">send</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Code</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">No_Content</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>The <code>Request</code> object that is passed to the <code>onTimeout</code> is the exact same request that triggered the timeout. The <code>ResponseWriter</code> is a complete new writer object.</p><divclass="admonition admonition-note alert alert--secondary"><divclass="admonition-heading"><h5><spanclass="admonition-icon"><svgxmlns="http://www.w3.org/2000/svg"width="14"height="16"viewBox="0 0 14 16"><pathfill-rule="evenodd"d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>ResponseWriter state</h5></div><divclass="admonition-content"><p>Since the <code>ResponseWriter</code> object is a complete new object, state is not preserved with the <code>ResponseWriter</code> from the <code>onRequest()</code> callback, which means that you will have to write the complete response again, including headers and cookies.</p></div></div></div><footerclass="row docusaurus-mt-lg"><divclass="col"><ahref="https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/http-handler.md"target="_blank"rel="noreferrer noopener"><svgfill="currentColor"height="20"width="20"viewBox="0 0 40 40"class="iconEdit_2_ui"aria-hidden="true"><g><pathd="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><divclass="col lastUpdated_3DPF"></div></footer></article><navclass="pagination-nav docusaurus-mt-lg"aria-label="Docs pages navigation"><divclass="pagination-nav__item"><aclass="pagination-nav__link"href="/docs/headers"><divclass="pagination-nav__sublabel">Previous</div><divclass="pagination-nav__label">« Headers</div></a></div><divclass="pagination-nav__item pagination-nav__item--next"><aclass="pagination-nav__link"href="/docs/"><divclass="pagination-nav__sublabel">Next</div><divclass="pagination-nav__label">Getting started »</div></a></div></nav></div></div><divclass="col col--3"><divclass="tableOfContents_35-E thin-scrollbar"><ulclass="table-of-contents table-of-contents__left-border"><li><ahref="#sending-a-response"class="table-of-contents__link">Sending a response</a></li><li><ahref="#response-streaming"class="table-of-contents__link">Response streaming</a></li><li><ahref="#static-file-serving"class="table-of-contents__link">Static file serving</a></li><li><ahref="#controlling-timeout"class="table-of-contents__link">Controlling timeout</a></li></ul></div></div></div></div></main></div></div><footerclass="footer footer--dark"><divclass="container"><divclass="row footer__links"><divclass="col footer__col"><divclass="footer__title">Docs</div><ulclass="footer__items"><liclass="footer__item"><aclass="footer__link-item"href="/docs/">Quickstart</a></li><liclass="footer__item"><aclass="footer__link-item"href="/docs/http-handler/">User guide</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">Community</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://stackoverflow.com/questions/tagged/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">Stack Overflow</a></li><liclass="footer__item"><ahref="https://web.libera.chat/#pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">#pistache on Libera.Chat</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">More</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">GitHub</a></li></ul></div></div><divclass="footer__bottom text--center"><divclass="footer__copyright">Pistache, 2015 - 2021</div></div></div></footer></div>
<titledata-react-helmet="true">Getting started | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="Getting started | Pistache"><metadata-react-helmet="true"name="description"content="Pistache is a web framework written in Modern C++ that focuses on performance and provides an elegant and asynchronous API."><metadata-react-helmet="true"property="og:description"content="Pistache is a web framework written in Modern C++ that focuses on performance and provides an elegant and asynchronous API."><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<titledata-react-helmet="true">Getting started | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="Getting started | Pistache"><metadata-react-helmet="true"name="description"content="<!--"><metadata-react-helmet="true"property="og:description"content="<!--"><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<titledata-react-helmet="true">REST description | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/rest-description"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="REST description | Pistache"><metadata-react-helmet="true"name="description"content="Documentation writing for this part is still in progress, please refer to the restdescription example."><metadata-react-helmet="true"property="og:description"content="Documentation writing for this part is still in progress, please refer to the restdescription example."><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/rest-description"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/rest-description"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/rest-description"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<titledata-react-helmet="true">Routing | Pistache</title><metadata-react-helmet="true"property="og:url"content="https://pistache.io/docs/routing"><metadata-react-helmet="true"name="docusaurus_locale"content="en"><metadata-react-helmet="true"name="docusaurus_version"content="current"><metadata-react-helmet="true"name="docusaurus_tag"content="docs-default-current"><metadata-react-helmet="true"property="og:title"content="Routing | Pistache"><metadata-react-helmet="true"name="description"content="HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:"><metadata-react-helmet="true"property="og:description"content="HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:"><linkdata-react-helmet="true"rel="shortcut icon"href="/img/logo.png"><linkdata-react-helmet="true"rel="canonical"href="https://pistache.io/docs/routing"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/routing"hreflang="en"><linkdata-react-helmet="true"rel="alternate"href="https://pistache.io/docs/routing"hreflang="x-default"><linkrel="stylesheet"href="/assets/css/styles.35f9fda9.css">
<div><ahref="#main"class="skipToContent_1oUP shadow--md">Skip to main content</a></div><navclass="navbar navbar--fixed-top"><divclass="navbar__inner"><divclass="navbar__items"><buttonaria-label="Navigation bar toggle"class="navbar__toggle clean-btn"type="button"tabindex="0"><svgwidth="30"height="30"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a><aaria-current="page"class="navbar__item navbar__link navbar__link--active"href="/docs/">Docs</a></div><divclass="navbar__items navbar__items--right"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="navbar__item navbar__link header-github-link"aria-label="GitHub repository"></a><divclass="react-toggle displayOnlyInLargeViewport_GrZ2 react-toggle--disabled"><divclass="react-toggle-track"role="button"tabindex="-1"><divclass="react-toggle-track-check"><spanclass="toggle_71bT">🌜</span></div><divclass="react-toggle-track-x"><spanclass="toggle_71bT">🌞</span></div><divclass="react-toggle-thumb"></div></div><inputtype="checkbox"class="react-toggle-screenreader-only"aria-label="Switch between dark and light mode"></div></div></div><divrole="presentation"class="navbar-sidebar__backdrop"></div><divclass="navbar-sidebar"><divclass="navbar-sidebar__brand"><aclass="navbar__brand"href="/"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--light_3UqQ navbar__logo"><imgsrc="/img/logo.png"alt="Pistache logo"class="themedImage_1VuW themedImage--dark_hz6m navbar__logo"><bclass="navbar__title">Pistache</b></a></div><divclass="navbar-sidebar__items"><divclass="menu"><ulclass="menu__list"><liclass="menu__list-item"><aaria-current="page"class="menu__link navbar__link--active"href="/docs/">Docs</a></li><liclass="menu__list-item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="menu__link header-github-link"aria-label="GitHub repository"></a></li></ul></div></div></div></nav><divclass="main-wrapper docs-wrapper doc-page"><divclass="docPage_31aa"><asideclass="docSidebarContainer_3Kbt"><divclass="sidebar_15mo"><navclass="menu menu--responsive thin-scrollbar menu_Bmed"aria-label="Sidebar navigation"><buttonaria-label="Open menu"aria-haspopup="true"class="button button--secondary button--sm menu__button"type="button"><svgclass="sidebarMenuIcon_fgN0"width="24"height="24"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ulclass="menu__list"><liclass="menu__list-item"><aclass="menu__link"href="/docs/asynchronous-http-programming">Asynchronous HTTP programming</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/headers">Headers</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/http-handler">HTTP handler</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/">Getting started</a></li><liclass="menu__list-item"><aclass="menu__link"href="/docs/rest-description">REST description</a></li><liclass="menu__list-item"><aaria-current="page"class="menu__link menu__link--active active"href="/docs/routing">Routing</a></li></ul></nav></div></aside><mainclass="docMainContainer_3ufF"><divclass="container padding-top--md padding-bottom--lg docItemWrapper_3FMP"><divclass="row"><divclass="col docItemCol_3FnS"><divclass="docItemContainer_33ec"><article><divclass="markdown"><header><h1class="h1Heading_27L5">Routing</h1></header><p>HTTP routing consists of binding an HTTP route to a C++ callback. A special component called an HTTP router will be in charge of dispatching HTTP requests to the right C++ callback. A route is composed of an HTTP verb associated to a resource:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly javascript"><pretabindex="0"class="prism-code language-javascript codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token constant"style="color:rgb(130, 170, 255)">GET</span><spanclass="token plain"></span><spanclass="token operator"style="color:rgb(137, 221, 255)">/</span><spanclass="token plain">users</span><spanclass="token operator"style="color:rgb(137, 221, 255)">/</span><spanclass="token number"style="color:rgb(247, 140, 108)">1</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>Here, <code>GET</code> is the verb and <code>/users/1</code> is the associated resource.</p><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="http-methods"></a>HTTP methods<aclass="hash-link"href="#http-methods"title="Direct link to heading">#</a></h2><p>A bunch of HTTP methods (verbs) are supported by Pistache:</p><ul><li><em>GET</em>: The <code>GET</code> method is used by the client (e.g browser) to retrieve a resource identified by an URI. For example, to retrieve an user identified by an id, a client will issue a <code>GET</code> to the <code>/users/:id</code> Request-URI.</li><li><em>POST</em>: the <code>POST</code> method is used to post or send new information to a certain resource. The server will then read and store the data associated to the request. <code>POST</code> is a common way of transmitting data from an HTML form. <code>POST</code> can also be used to create a new resource or update information of an existing resource. For example, to create a new user, a client will issue a <code>POST</code> to the <code>/users</code> path with the data of the user to create in its body.</li><li><em>PUT</em>: <code>PUT</code> is very similar to <code>POST</code> except that <code>PUT</code> is idempotent, meaning that two requests to the same Request-URI with the same identical content should have the same effect and should produce the same result.</li><li><em>DELETE</em>: the <code>DELETE</code> method is used to delete a resource associated to a given Request-URI. For example, to remove an user, a client might issue a <code>DELETE</code> call to the <code>/users/:id</code> Request-URI.</li></ul><p>To sum up, <code>POST</code> and <code>PUT</code> are used to Create and/or Update, <code>GET</code> is used to Read and <code>DELETE</code> is used to Delete information.</p><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="route-patterns"></a>Route patterns<aclass="hash-link"href="#route-patterns"title="Direct link to heading">#</a></h2><h3><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="static-routes"></a>Static routes<aclass="hash-link"href="#static-routes"title="Direct link to heading">#</a></h3><p>Static routes are the simplest ones as they do rely on dynamic parts of the Request-URI. For example <code>/users/all</code> is a static route that will exactly match the <code>/users/all</code> Request-URI.</p><h3><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="dynamic-routes"></a>Dynamic routes<aclass="hash-link"href="#dynamic-routes"title="Direct link to heading">#</a></h3><p>However, it is often useful to define routes that have dynamic parts. For example, to retrieve a specific user by its id, the id is needed to query the storage. Dynamic routes thus have parameters that are then matched one by one by the HTTP router. In a dynamic route, parameters are identified by a column <code>:</code></p><p><code>/users/:id</code></p><p>Here, <code>:id</code> is a dynamic parameter. When a request comes in, the router will try to match the <code>:id</code> parameter to the corresponding part of the request. For example, if the server receives a request to <code>/users/13</code>, the router will match the <code>13</code> value to the <code>:id</code> parameter.</p><p>Some parameters, like <code>:id</code> are named. However, Pistache also allows <em>splat</em> (wildcard) parameters, identified by a star <code>*</code>:</p><p><code>/link/*/to/*</code></p><h2><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="defining-routes"></a>Defining routes<aclass="hash-link"href="#defining-routes"title="Direct link to heading">#</a></h2><p>To define your routes, you first have to instantiate an HTTP router:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Router router</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>Then, use the <code>Routes::<Method>()</code> functions to add some routes:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">Get</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">router</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"/users/all"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">bind</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain">UsersApi</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">getAllUsers</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">this</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">Post</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">router</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"/users/:id"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">bind</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain">UsersApi</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">getUserId</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">this</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">Get</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">router</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token string"style="color:rgb(195, 232, 141)">"/link/*/to/*"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">Routes</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">bind</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain">UsersApi</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">linkUsers</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">this</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p><code>Routes::bind</code> is a special function that will generate a corresponding C++ callback that will then be called by the router if a given route matches the Request-URI.</p><h3><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="callbacks"></a>Callbacks<aclass="hash-link"href="#callbacks"title="Direct link to heading">#</a></h3><p>A C++ callback associated to a route must have the following signature:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">void</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Rest</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Request</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ResponseWriter</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>A callback can either be a non-static free or member function. For member functions, a pointer to the corresponding instance must be passed to the Routes::bind function so that the router knows on which instance to invoke the member function.</p><p>The first parameter of the callback is <code>Rest::Request</code> and not an <code>Http::Request</code>. A <code>Rest::Request</code> is an <code>Http::Request</code> with additional functions. Named and splat parameters are for example retrieved through this object:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token keyword"style="font-style:italic">void</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">UsersApi</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">getUserId</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Rest</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Request</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ResponseWriter response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> id </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">param</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token string"style="color:rgb(195, 232, 141)">":id"</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">as</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token keyword"style="font-style:italic">int</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(105, 112, 152);font-style:italic">// ...</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"style="display:inline-block">
</span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">void</span><spanclass="token plain"></span><spanclass="token class-name"style="color:rgb(255, 203, 107)">UsersApi</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token function"style="color:rgb(130, 170, 255)">linkUsers</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token keyword"style="font-style:italic">const</span><spanclass="token plain"> Rest</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">Request</span><spanclass="token operator"style="color:rgb(137, 221, 255)">&</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">,</span><spanclass="token plain"> Http</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">ResponseWriter response</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">{</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> u1 </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">splatAt</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token number"style="color:rgb(247, 140, 108)">0</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">as</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">string</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token keyword"style="font-style:italic">auto</span><spanclass="token plain"> u2 </span><spanclass="token operator"style="color:rgb(137, 221, 255)">=</span><spanclass="token plain"> request</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">splatAt</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token number"style="color:rgb(247, 140, 108)">1</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token plain">as</span><spanclass="token operator"style="color:rgb(137, 221, 255)"><</span><spanclass="token plain">std</span><spanclass="token operator"style="color:rgb(137, 221, 255)">::</span><spanclass="token plain">string</span><spanclass="token operator"style="color:rgb(137, 221, 255)">></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token comment"style="color:rgb(105, 112, 152);font-style:italic">// ...</span><spanclass="token plain"></span></span><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain"></span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">}</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div><p>As you can see, parameters are also typed. To cast a parameter to the appropriate type, use the <code>as<T></code> member template.</p><divclass="admonition admonition-note alert alert--secondary"><divclass="admonition-heading"><h5><spanclass="admonition-icon"><svgxmlns="http://www.w3.org/2000/svg"width="14"height="16"viewBox="0 0 14 16"><pathfill-rule="evenodd"d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path></svg></span>Cast safety</h5></div><divclass="admonition-content"><p>An exception will be thrown if the parameter can not be casted to the right type</p></div></div><h3><aaria-hidden="true"tabindex="-1"class="anchor enhancedAnchor_2LWZ"id="installing-the-handler"></a>Installing the handler<aclass="hash-link"href="#installing-the-handler"title="Direct link to heading">#</a></h3><p>Once the routes have been defined, the final <code>Http::Handler</code> must be set to the HTTP Endpoint. To retrieve the handler, just call the <code>handler()</code> member function on the router object:</p><divclass="codeBlockContainer_K1bP"><divclass="codeBlockContent_hGly cpp"><pretabindex="0"class="prism-code language-cpp codeBlock_23N8 thin-scrollbar"style="color:#bfc7d5;background-color:#292d3e"><codeclass="codeBlockLines_39YC"><spanclass="token-line"style="color:#bfc7d5"><spanclass="token plain">endpoint</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">setHandler</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token plain">router</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">.</span><spanclass="token function"style="color:rgb(130, 170, 255)">handler</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">(</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">)</span><spanclass="token punctuation"style="color:rgb(199, 146, 234)">;</span></span></code></pre><buttontype="button"aria-label="Copy code to clipboard"class="copyButton_Ue-o clean-btn">Copy</button></div></div></div><footerclass="row docusaurus-mt-lg"><divclass="col"><ahref="https://github.com/pistacheio/pistache/edit/master/pistache.io/docs/routing.md"target="_blank"rel="noreferrer noopener"><svgfill="currentColor"height="20"width="20"viewBox="0 0 40 40"class="iconEdit_2_ui"aria-hidden="true"><g><pathd="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><divclass="col lastUpdated_3DPF"></div></footer></article><navclass="pagination-nav docusaurus-mt-lg"aria-label="Docs pages navigation"><divclass="pagination-nav__item"><aclass="pagination-nav__link"href="/docs/rest-description"><divclass="pagination-nav__sublabel">Previous</div><divclass="pagination-nav__label">« REST description</div></a></div><divclass="pagination-nav__item pagination-nav__item--next"></div></nav></div></div><divclass="col col--3"><divclass="tableOfContents_35-E thin-scrollbar"><ulclass="table-of-contents table-of-contents__left-border"><li><ahref="#http-methods"class="table-of-contents__link">HTTP methods</a></li><li><ahref="#route-patterns"class="table-of-contents__link">Route patterns</a><ul><li><ahref="#static-routes"class="table-of-contents__link">Static routes</a></li><li><ahref="#dynamic-routes"class="table-of-contents__link">Dynamic routes</a></li></ul></li><li><ahref="#defining-routes"class="table-of-contents__link">Defining routes</a><ul><li><ahref="#callbacks"class="table-of-contents__link">Callbacks</a></li><li><ahref="#installing-the-handler"class="table-of-contents__link">Installing the handler</a></li></ul></li></ul></div></div></div></div></main></div></div><footerclass="footer footer--dark"><divclass="container"><divclass="row footer__links"><divclass="col footer__col"><divclass="footer__title">Docs</div><ulclass="footer__items"><liclass="footer__item"><aclass="footer__link-item"href="/docs/">Quickstart</a></li><liclass="footer__item"><aclass="footer__link-item"href="/docs/http-handler/">User guide</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">Community</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://stackoverflow.com/questions/tagged/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">Stack Overflow</a></li><liclass="footer__item"><ahref="https://web.libera.chat/#pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">#pistache on Libera.Chat</a></li></ul></div><divclass="col footer__col"><divclass="footer__title">More</div><ulclass="footer__items"><liclass="footer__item"><ahref="https://github.com/pistacheio/pistache"target="_blank"rel="noopener noreferrer"class="footer__link-item">GitHub</a></li></ul></div></div><divclass="footer__bottom text--center"><divclass="footer__copyright">Pistache, 2015 - 2021</div></div></div></footer></div>