LCOV - code coverage report
Current view: top level - extra/webserver/webserver/request - SPWebRequestHandler.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 12 24 50.0 %
Date: 2024-05-12 00:16:13 Functions: 24 34 70.6 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #ifndef EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUESTHANDLER_H_
      24             : #define EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUESTHANDLER_H_
      25             : 
      26             : #include "SPWebRequest.h"
      27             : 
      28             : namespace STAPPLER_VERSIONIZED stappler::web {
      29             : 
      30             : class InputFilter;
      31             : 
      32             : class RequestHandler : public AllocBase {
      33             : public:
      34             :         using HandlerCallback = Function<RequestHandler *()>;
      35             : 
      36             :         template <typename T, typename ... Args>
      37         175 :         static HandlerCallback Make(Args && ... args) {
      38         800 :                 return HandlerCallback([=] {
      39        1600 :                         return new T(std::forward<Args>(args)...);
      40         175 :                 });
      41             :         }
      42             : 
      43           0 :         virtual ~RequestHandler() { }
      44             : 
      45           0 :         virtual bool isRequestPermitted(Request &) { return false; }
      46             : 
      47             :         /**
      48             :          * https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
      49             :          *
      50             :      * @param rctx - new request, avoid to modify it
      51             :      * @param origin - actual value of Origin header, it's sender's domain name
      52             :      * @param isPreflight - we recieve preflight request (so, method and headers should be filled)
      53             :      * @param method - method for preflighted request
      54             :      * @param headers - extra (X-*) headers for preflighted request
      55             :      * @return for forbidden CORS requests server will return "405 Method Not Allowed"
      56             :      */
      57           0 :         virtual bool isCorsPermitted(Request &, const StringView &origin, bool isPreflight = false,
      58           0 :                 const StringView &method = "", const StringView &headers = "") { return true; }
      59             : 
      60             :         /**
      61             :          * Available method for CORS preflighted requests
      62             :      */
      63           0 :         virtual StringView getCorsAllowMethods(Request &) {
      64           0 :                 return "GET, HEAD, POST, PUT, DELETE, OPTIONS";
      65             :         }
      66             : 
      67             :         /**
      68             :          * Available extra headers for CORS preflighted requests
      69             :      */
      70           0 :         virtual StringView getCorsAllowHeaders(Request &) {
      71           0 :                 return StringView();
      72             :         }
      73             : 
      74             :         /**
      75             :          * Caching time for preflight response
      76             :      */
      77           0 :         virtual StringView getCorsMaxAge(Request &) {
      78           0 :                 return "1728000"; // 20 days
      79             :         }
      80             : 
      81             :         /** Be sure to call supermethod when overload this method! */
      82             :         virtual Status onRequestRecieved(Request &, StringView origin, StringView path, const Value &);
      83             : 
      84             :         virtual Status onPostReadRequest(Request &);
      85             :         virtual Status onTranslateName(Request &);
      86             :         virtual Status onQuickHandler(Request &, int v);
      87             :         virtual void onInsertFilter(Request &);
      88             :         virtual Status onHandler(Request &);
      89             : 
      90             :         virtual void onFilterInit(InputFilter *f);
      91             :         virtual void onFilterUpdate(InputFilter *f);
      92             :         virtual void onFilterComplete(InputFilter *f);
      93             : 
      94             :         virtual const Value &getOptions() const;
      95             : 
      96             :         void setAccessRole(db::AccessRoleId role);
      97             :         db::AccessRoleId getAccessRole() const;
      98             : 
      99             : protected:
     100             :         Request _request;
     101             :         StringView _originPath;
     102             :         StringView _subPath;
     103             :         Vector<StringView> _subPathVec;
     104             :         Value _options;
     105             :         db::AccessRoleId _accessRole = db::AccessRoleId::Nobody;
     106             :         db::Transaction _transaction = nullptr;
     107             : };
     108             : 
     109             : class DefaultHandler : public RequestHandler {
     110             : public:
     111             :         virtual bool isRequestPermitted(Request &) override { return true; }
     112             : };
     113             : 
     114             : class DataHandler : public RequestHandler {
     115             : public:
     116             :         enum class AllowMethod : uint8_t {
     117             :                 None = 0,
     118             :                 Get = 1 << 0,
     119             :                 Post = 1 << 1,
     120             :                 Put = 1 << 2,
     121             :                 Delete = 1 << 3,
     122             :                 All = 0xFF,
     123             :         };
     124             : 
     125           0 :         virtual ~DataHandler() { }
     126             : 
     127             :         // overload point
     128           0 :         virtual bool processDataHandler(Request &req, Value &result, Value &input) { return false; }
     129             : 
     130             :         virtual Status onTranslateName(Request &) override;
     131             :         virtual void onInsertFilter(Request &) override;
     132             :         virtual Status onHandler(Request &) override;
     133             : 
     134             :         virtual void onFilterComplete(InputFilter *f) override;
     135             : 
     136             : protected:
     137         150 :         virtual bool allowJsonP() { return true; }
     138             : 
     139             :         Status writeResult(Value &);
     140             : 
     141             :         AllowMethod _allow = AllowMethod::All;
     142             :         db::InputConfig _config = db::InputConfig({
     143             :                 db::InputConfig::Require::Data | db::InputConfig::Require::FilesAsData,
     144             :                 0,
     145             :                 256,
     146             :                 0
     147             :         });
     148             :         InputFilter *_filter;
     149             : };
     150             : 
     151             : SP_DEFINE_ENUM_AS_MASK(DataHandler::AllowMethod)
     152             : 
     153             : class FilesystemHandler : public RequestHandler {
     154             : public:
     155             :         FilesystemHandler(const String &path, size_t cacheTimeInSeconds = stappler::maxOf<size_t>());
     156             :         FilesystemHandler(const String &path, const String &ct, size_t cacheTimeInSeconds = stappler::maxOf<size_t>());
     157             : 
     158             :         virtual bool isRequestPermitted(Request &) override;
     159             :         virtual Status onTranslateName(Request &) override;
     160             : 
     161             : protected:
     162             :         String _path;
     163             :         String _contentType;
     164             :         size_t _cacheTime;
     165             : };
     166             : 
     167             : class RequestHandlerMap : public AllocBase {
     168             : public:
     169             :         class HandlerInfo;
     170             :         class Handler;
     171             : 
     172             :         class Handler : public RequestHandler {
     173             :         public: // simplified interface
     174             :                 template <typename T, typename ... Args>
     175         100 :                 static Function<Handler *()> Make(Args && ... args) {
     176         100 :                         return Function<Handler *()>([=] {
     177         200 :                                 return new T(std::forward<Args>(args)...);
     178         100 :                         });
     179             :                 }
     180             : 
     181             :                 virtual bool isPermitted();
     182             :                 virtual Status onRequest();
     183             :                 virtual Value onData();
     184             : 
     185             :         public:
     186             :                 Handler();
     187             :                 virtual ~Handler();
     188             : 
     189             :                 virtual void onParams(const HandlerInfo *, Value &&);
     190         100 :                 virtual bool isRequestPermitted(Request &) override { return isPermitted(); }
     191             :                 virtual Status onTranslateName(Request &) override;
     192             :                 virtual void onInsertFilter(Request &) override;
     193             :                 virtual Status onHandler(Request &) override;
     194             : 
     195             :                 virtual void onFilterComplete(InputFilter *f) override;
     196             : 
     197             :                 const Request &getRequest() const { return _request; }
     198             :                 const Value &getParams() const { return _params; }
     199             :                 const Value &getQueryFields() const { return _queryFields; }
     200             :                 const Value &getInputFields() const { return _inputFields; }
     201             : 
     202             :         protected:
     203         100 :                 virtual bool allowJsonP() { return true; }
     204             : 
     205             :                 bool processQueryFields(Value &&);
     206             :                 bool processInputFields(InputFilter *);
     207             : 
     208             :                 Status writeResult(Value &);
     209             : 
     210             :                 db::InputFile *getInputFile(const StringView &);
     211             : 
     212             :                 const HandlerInfo *_info = nullptr;
     213             :                 InputFilter *_filter = nullptr;
     214             : 
     215             :                 Value _params; // query path params
     216             :                 Value _queryFields;
     217             :                 Value _inputFields;
     218             :         };
     219             : 
     220             :         class HandlerInfo : public AllocBase {
     221             :         public:
     222             :                 HandlerInfo(const StringView &name, RequestMethod, const StringView &pattern,
     223             :                                 Function<Handler *()> &&, Value && = Value());
     224             : 
     225             :                 HandlerInfo &addQueryFields(std::initializer_list<db::Field> il);
     226             :                 HandlerInfo &addQueryFields(Vector<db::Field> &&il);
     227             : 
     228             :                 HandlerInfo &addInputFields(std::initializer_list<db::Field> il);
     229             :                 HandlerInfo &addInputFields(Vector<db::Field> &&il);
     230             :                 HandlerInfo &setInputConfig(db::InputConfig);
     231             : 
     232             :                 Value match(const StringView &path, size_t &score) const;
     233             : 
     234             :                 Handler *onHandler(Value &&) const;
     235             : 
     236             :                 RequestMethod getMethod() const;
     237             :                 const db::InputConfig &getInputConfig() const;
     238             : 
     239             :                 StringView getName() const;
     240             :                 StringView getPattern() const;
     241             :                 const Value &getOptions() const;
     242             : 
     243             :                 const db::Scheme &getQueryScheme() const;
     244             :                 const db::Scheme &getInputScheme() const;
     245             : 
     246             :         protected:
     247             :                 struct Fragment {
     248             :                         enum Type : uint16_t {
     249             :                                 Text,
     250             :                                 Pattern,
     251             :                         };
     252             : 
     253         250 :                         Fragment(Type t, StringView s) : type(t), string(s.str<Interface>()) { }
     254             : 
     255             :                         Type type;
     256             :                         String string;
     257             :                 };
     258             : 
     259             :                 String name;
     260             :                 RequestMethod method = RequestMethod::Get;
     261             :                 String pattern;
     262             :                 Function<Handler *()> handler;
     263             :                 Value options;
     264             : 
     265             :                 db::Scheme queryFields;
     266             :                 db::Scheme inputFields;
     267             :                 Vector<Fragment> fragments;
     268             :         };
     269             : 
     270             :         RequestHandlerMap();
     271             :         virtual ~RequestHandlerMap();
     272             : 
     273             :         RequestHandlerMap(RequestHandlerMap &&) = default;
     274             :         RequestHandlerMap &operator=(RequestHandlerMap &&) = default;
     275             : 
     276             :         RequestHandlerMap(const RequestHandlerMap &) = delete;
     277             :         RequestHandlerMap &operator=(const RequestHandlerMap &) = delete;
     278             : 
     279             :         Handler *onRequest(Request &req, const StringView &path) const;
     280             : 
     281             :         HandlerInfo &addHandler(const StringView &name, RequestMethod, const StringView &pattern,
     282             :                         Function<Handler *()> &&, Value && = Value());
     283             : 
     284             :         HandlerInfo &addHandler(const StringView &name, RequestMethod, const StringView &pattern,
     285             :                         Function<bool(Handler &)> &&, Function<Value(Handler &)> &&, Value && = Value());
     286             : 
     287             :         const Vector<HandlerInfo> &getHandlers() const;
     288             : 
     289             : protected:
     290             :         Vector<HandlerInfo> _handlers;
     291             : };
     292             : 
     293             : }
     294             : 
     295             : #endif /* EXTRA_WEBSERVER_WEBSERVER_REQUEST_SPWEBREQUESTHANDLER_H_ */

Generated by: LCOV version 1.14