#ifndef ICESPIDER_IHTTPREQUEST_H #define ICESPIDER_IHTTPREQUEST_H #include #include #include #include #include #include #include #include #include "exceptions.h" namespace IceSpider { class Core; class IRouteHandler; typedef std::vector PathElements; typedef std::optional OptionalString; typedef std::pair ContentTypeSerializer; class DLL_PUBLIC IHttpRequest { public: IHttpRequest(const Core *); Ice::Context getContext() const; virtual const PathElements & getRequestPath() const = 0; virtual PathElements & getRequestPath() = 0; virtual HttpMethod getRequestMethod() const = 0; OptionalString getURLParam(const unsigned int &) const; virtual OptionalString getQueryStringParam(const std::string_view &) const = 0; virtual OptionalString getHeaderParam(const std::string_view &) const = 0; virtual OptionalString getCookieParam(const std::string_view &) const = 0; virtual OptionalString getEnv(const std::string_view &) const = 0; static Accepted parseAccept(const std::string_view &); virtual Slicer::DeserializerPtr getDeserializer() const; virtual ContentTypeSerializer getSerializer(const IRouteHandler *) const; virtual std::istream & getInputStream() const = 0; virtual std::ostream & getOutputStream() const = 0; virtual void setHeader(const std::string_view &, const std::string_view &) const = 0; virtual std::ostream & dump(std::ostream & s) const = 0; template inline std::optional getFrom(const K & key, OptionalString (IHttpRequest::*src)(const K &) const) const { if (auto v = (this->*src)(key)) { if constexpr (std::is_convertible::value) { return *v; } else if constexpr (std::is_constructible::value) { return T(*v); } else { try { return boost::lexical_cast(*v); } catch (const boost::bad_lexical_cast & e) { throw Http400_BadRequest(); } } } else { return std::nullopt; } } template T getURLParam(unsigned int n) const { return *getFrom(n, &IHttpRequest::getURLParam); } template std::optional getBody() const { return Slicer::DeserializeAnyWith(getDeserializer()); } template std::optional getBodyParam(const std::optional & map, const std::string_view & key) const { if (!map) { return {}; } auto i = map->find(key); if (i == map->end()) { return {}; } else { return boost::lexical_cast(i->second); } } void responseRedirect(const std::string_view & url, const OptionalString & = {}) const; void setCookie(const std::string_view &, const std::string_view &, const OptionalString & = {}, const OptionalString & = {}, bool = false, std::optional = {}); template void setCookie(const std::string_view & n, const T & v, const OptionalString & d, const OptionalString & p, bool s, std::optional e) { if constexpr (std::is_constructible::value) { setCookie(n, std::string_view(v), d, p, s, e); } else { auto vs = boost::lexical_cast(v); setCookie(n, std::string_view(vs), d, p, s, e); } } template std::optional getQueryStringParam(const std::string_view & key) const { return getFrom(key, &IHttpRequest::getQueryStringParam); } template std::optional getHeaderParam(const std::string_view & key) const { return getFrom(key, &IHttpRequest::getHeaderParam); } template std::optional getCookieParam(const std::string_view & key) const { return getFrom(key, &IHttpRequest::getCookieParam); } virtual void response(short, const std::string_view &) const = 0; template void response(const IRouteHandler * route, const T & t) const { modelPartResponse(route, Slicer::ModelPart::CreateRootFor(t)); } void modelPartResponse(const IRouteHandler * route, const Slicer::ModelPartForRootPtr &) const; const Core * core; }; } #endif