LCOV - code coverage report
Current view: top level - model - AdminServerProvision.hpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 85.7 % 56 48
Test Date: 2026-03-07 03:59:50 Functions: 85.7 % 21 18

            Line data    Source code
       1              : /*
       2              :  ___________________________________________
       3              : |    _     ___                        _     |
       4              : |   | |   |__ \                      | |    |
       5              : |   | |__    ) |__ _  __ _  ___ _ __ | |_   |
       6              : |   | '_ \  / // _` |/ _` |/ _ \ '_ \| __|  |  HTTP/2 AGENT FOR MOCK TESTING
       7              : |   | | | |/ /| (_| | (_| |  __/ | | | |_   |  Version 0.0.z
       8              : |   |_| |_|____\__,_|\__, |\___|_| |_|\__|  |  https://github.com/testillano/h2agent
       9              : |                     __/ |                 |
      10              : |                    |___/                  |
      11              : |___________________________________________|
      12              : 
      13              : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
      14              : SPDX-License-Identifier: MIT
      15              : Copyright (c) 2021 Eduardo Ramos
      16              : 
      17              : Permission is hereby  granted, free of charge, to any  person obtaining a copy
      18              : of this software and associated  documentation files (the "Software"), to deal
      19              : in the Software  without restriction, including without  limitation the rights
      20              : to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
      21              : copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
      22              : furnished to do so, subject to the following conditions:
      23              : 
      24              : The above copyright notice and this permission notice shall be included in all
      25              : copies or substantial portions of the Software.
      26              : 
      27              : THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
      28              : IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
      29              : FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
      30              : AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
      31              : LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      32              : OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
      33              : SOFTWARE.
      34              : */
      35              : 
      36              : #pragma once
      37              : 
      38              : #include <nghttp2/asio_http2_server.h>
      39              : 
      40              : #include <memory>
      41              : #include <string>
      42              : #include <vector>
      43              : #include <regex>
      44              : #include <cstdint>
      45              : 
      46              : #include <nlohmann/json.hpp>
      47              : 
      48              : #include <AdminSchema.hpp>
      49              : #include <Transformation.hpp>
      50              : #include <TypeConverter.hpp>
      51              : #include <DataPart.hpp>
      52              : 
      53              : 
      54              : namespace h2agent
      55              : {
      56              : namespace model
      57              : {
      58              : 
      59              : // Provision key:
      60              : typedef std::string admin_server_provision_key_t; // <inState>#<method>#<uri>
      61              : 
      62              : class MockServerData;
      63              : class MockClientData;
      64              : class AdminData;
      65              : class Configuration;
      66              : class GlobalVariable;
      67              : class FileManager;
      68              : class SocketManager;
      69              : 
      70              : 
      71              : class AdminServerProvision
      72              : {
      73              :     bool employed_{};
      74              : 
      75              :     nlohmann::json json_{}; // provision reference
      76              : 
      77              :     admin_server_provision_key_t key_{}; // calculated in every load()
      78              :     std::regex regex_{}; // precompile key as possible regex for RegexMatching algorithm
      79              : 
      80              :     // Cached information:
      81              :     std::string in_state_{};
      82              :     std::string request_method_{};
      83              :     std::string request_uri_{};
      84              : 
      85              :     std::string out_state_{};
      86              :     unsigned int response_code_{};
      87              :     nghttp2::asio_http2::header_map response_headers_{};
      88              : 
      89              :     nlohmann::json response_body_{};
      90              :     std::string response_body_string_{};
      91              :     /* Tatsuhiro sends strings in response:
      92              :     int response_body_integer_{};
      93              :     double response_body_number_{};
      94              :     bool response_body_boolean_{};
      95              :     bool response_body_null_{};
      96              :     */
      97              : 
      98              :     unsigned int response_delay_ms_{};
      99              : 
     100              :     // Schemas:
     101              :     std::string request_schema_id_{};
     102              :     std::string response_schema_id_{};
     103              :     std::shared_ptr<h2agent::model::AdminSchema> request_schema_{};
     104              :     std::shared_ptr<h2agent::model::AdminSchema> response_schema_{};
     105              : 
     106              :     model::MockServerData *mock_server_events_data_{}; // just in case it is used
     107              :     model::MockClientData *mock_client_events_data_{}; // just in case it is used
     108              :     model::AdminData *admin_data_{}; // just in case it is used
     109              :     model::Configuration *configuration_{}; // just in case it is used
     110              :     model::GlobalVariable *global_variable_{}; // just in case it is used
     111              :     model::FileManager *file_manager_{}; // just in case it is used
     112              :     model::SocketManager *socket_manager_{}; // just in case it is used
     113              : 
     114              :     void loadTransformation(const nlohmann::json &j);
     115              : 
     116              :     std::vector<std::shared_ptr<Transformation>> transformations_{};
     117              : 
     118              :     // Three processing stages: get sources, apply filters and store targets:
     119              :     bool processSources(std::shared_ptr<Transformation> transformation,
     120              :                         TypeConverter& sourceVault,
     121              :                         std::map<std::string, std::string>& variables,
     122              :                         const std::string &requestUri,
     123              :                         const std::string &requestUriPath,
     124              :                         const std::map<std::string, std::string> &requestQueryParametersMap,
     125              :                         const DataPart &requestBodyDataPart,
     126              :                         const nghttp2::asio_http2::header_map &requestHeaders,
     127              :                         bool &eraser,
     128              :                         std::uint64_t generalUniqueServerSequence,
     129              :                         bool usesResponseBodyAsTransformationJsonTarget, const nlohmann::json &responseBodyJson) const; // these two last parameters are used to
     130              :     // know if original response body provision
     131              :     // or the one dynamically modified, must be
     132              :     // used as source
     133              : 
     134              :     bool processFilters(std::shared_ptr<Transformation> transformation,
     135              :                         TypeConverter& sourceVault,
     136              :                         const std::map<std::string, std::string>& variables,
     137              :                         std::smatch &matches,
     138              :                         std::string &source) const;
     139              : 
     140              :     bool processTargets(std::shared_ptr<Transformation> transformation,
     141              :                         TypeConverter& sourceVault,
     142              :                         std::map<std::string, std::string>& variables,
     143              :                         const std::smatch &matches,
     144              :                         bool eraser,
     145              :                         bool hasFilter,
     146              :                         unsigned int &responseStatusCode,
     147              :                         nlohmann::json &responseBodyJson, // to manipulate json
     148              :                         std::string &responseBodyAsString, // to set native data (readable or not)
     149              :                         nghttp2::asio_http2::header_map &responseHeaders,
     150              :                         unsigned int &responseDelayMs,
     151              :                         std::string &outState,
     152              :                         std::string &outStateMethod,
     153              :                         std::string &outStateUri,
     154              :                         std::vector<std::pair<std::string, std::string>> &clientProvisionTriggers,
     155              :                         bool &breakCondition) const;
     156              : 
     157              : 
     158              : public:
     159              : 
     160              :     AdminServerProvision();
     161              : 
     162              :     // transform logic
     163              : 
     164              :     /**
     165              :      * Applies transformations vector over request received and ongoing response built
     166              :      * Also checks optional schema validation for incoming and/or outgoing traffic
     167              :      *
     168              :      * @param requestUri Request URI
     169              :      * @param requestUriPath Request URI path part
     170              :      * @param requestQueryParametersMap Query Parameters Map (if exists)
     171              :      * @param requestBodyDataPart Request Body data received (could be decoded if needed as source)
     172              :      * @param requestHeaders Request Headers Received
     173              :      * @param generalUniqueServerSequence HTTP/2 server monotonically increased sequence for every reception (unique)
     174              :      *
     175              :      * @param responseStatusCode Response status code filled by reference (if any transformation applies)
     176              :      * @param responseHeaders Response headers filled by reference (if any transformation applies)
     177              :      * @param responseBody Response body filled by reference (if any transformation applies)
     178              :      * @param responseDelayMs Response delay milliseconds filled by reference (if any transformation applies)
     179              :      * @param outState out-state for request context created, filled by reference (if any transformation applies)
     180              :      * @param outStateMethod method inferred towards a virtual server data entry created through a foreign out-state, filled by reference (if any transformation applies)
     181              :      * @param outStateUri uri inferred towards a virtual server data entry created through a foreign out-state, filled by reference (if any transformation applies)
     182              :      */
     183              :     void transform( const std::string &requestUri,
     184              :                     const std::string &requestUriPath,
     185              :                     const std::map<std::string, std::string> &requestQueryParametersMap,
     186              :                     DataPart &requestBodyDataPart,
     187              :                     const nghttp2::asio_http2::header_map &requestHeaders,
     188              :                     std::uint64_t generalUniqueServerSequence,
     189              : 
     190              :                     unsigned int &responseStatusCode,
     191              :                     nghttp2::asio_http2::header_map &responseHeaders,
     192              :                     std::string &responseBody,
     193              :                     unsigned int &responseDelayMs,
     194              :                     std::string &outState,
     195              :                     std::string &outStateMethod,
     196              :                     std::string &outStateUri,
     197              :                     std::vector<std::pair<std::string, std::string>> &clientProvisionTriggers,
     198              :                     std::map<std::string, std::string> &variables
     199              :                   );
     200              : 
     201              :     // setters:
     202              : 
     203              :     /**
     204              :      * Load provision information
     205              :      *
     206              :      * @param j Json provision object
     207              :      * @param regexMatchingConfigured provision load depends on matching configuration (priority regexp)
     208              :      *
     209              :      * @return Operation success
     210              :      */
     211              :     bool load(const nlohmann::json &j, bool regexMatchingConfigured);
     212              : 
     213              :     /**
     214              :      * Sets the internal mock server data,
     215              :      * just in case it is used in event source
     216              :      */
     217          119 :     void setMockServerData(model::MockServerData *p) {
     218          119 :         mock_server_events_data_ = p;
     219          119 :     }
     220              : 
     221              :     /**
     222              :      * Sets the internal mock client data,
     223              :      * just in case it is used in event source
     224              :      */
     225          119 :     void setMockClientData(model::MockClientData *p) {
     226          119 :         mock_client_events_data_ = p;
     227          119 :     }
     228              : 
     229              :     /**
     230              :      * Sets the admin data reference,
     231              :      * just in case it is used in SchemaId filter
     232              :      */
     233          119 :     void setAdminData(model::AdminData *p) {
     234          119 :         admin_data_ = p;
     235          119 :     }
     236              : 
     237              :     /**
     238              :      * Sets the configuration reference,
     239              :      * just in case it is used in event target
     240              :      */
     241          119 :     void setConfiguration(model::Configuration *p) {
     242          119 :         configuration_ = p;
     243          119 :     }
     244              : 
     245              :     /**
     246              :      * Sets the global variables data reference,
     247              :      * just in case it is used in event source
     248              :      */
     249          119 :     void setGlobalVariable(model::GlobalVariable *p) {
     250          119 :         global_variable_ = p;
     251          119 :     }
     252              : 
     253              :     /**
     254              :      * Sets the file manager reference,
     255              :      * just in case it is used in event target
     256              :      */
     257          119 :     void setFileManager(model::FileManager *p) {
     258          119 :         file_manager_ = p;
     259          119 :     }
     260              : 
     261              :     /**
     262              :      * Sets the socket manager reference,
     263              :      * just in case it is used in event target
     264              :      */
     265          119 :     void setSocketManager(model::SocketManager *p) {
     266          119 :         socket_manager_ = p;
     267          119 :     }
     268              : 
     269              :     /**
     270              :      * Provision is being employed
     271              :      */
     272            0 :     void employ() {
     273            0 :         employed_ = true;
     274            0 :     }
     275              : 
     276              :     // getters:
     277              : 
     278              :     /**
     279              :      * Gets the provision request uri which could be a regular expression
     280              :      * or a full-matched URI string
     281              :      *
     282              :      * @return Provision request URI
     283              :      */
     284            0 :     const admin_server_provision_key_t &getRequestUri() const {
     285            0 :         return request_uri_;
     286              :     }
     287              : 
     288              :     /**
     289              :      * Gets the provision key as '<in-state>|<request-method>|<request-uri>'
     290              :      *
     291              :      * @return Provision key
     292              :      */
     293          119 :     const admin_server_provision_key_t &getKey() const {
     294          119 :         return key_;
     295              :     }
     296              : 
     297              :     /**
     298              :      * Json for class information
     299              :      *
     300              :      * @return Json object
     301              :      */
     302            3 :     const nlohmann::json &getJson() const {
     303            3 :         return json_;
     304              :     }
     305              : 
     306              :     /**
     307              :      * Precompiled regex for provision key
     308              :      *
     309              :      * @return regex
     310              :      */
     311            4 :     const std::regex &getRegex() const {
     312            4 :         return regex_;
     313              :     }
     314              : 
     315              :     /** Provisioned out state
     316              :      *
     317              :      * @return Out state
     318              :      */
     319          105 :     const std::string &getOutState() const {
     320          105 :         return out_state_;
     321              :     }
     322              : 
     323              :     /** Provisioned in state
     324              :      *
     325              :      * @return In state
     326              :      */
     327            3 :     const std::string &getInState() const {
     328            3 :         return in_state_;
     329              :     }
     330              : 
     331              :     /** Provisioned response code
     332              :      *
     333              :      * @return Response code
     334              :      */
     335          105 :     unsigned int getResponseCode() const {
     336          105 :         return response_code_;
     337              :     }
     338              : 
     339              :     /** Provisioned response headers
     340              :      *
     341              :      * @return Response headers
     342              :      */
     343          105 :     const nghttp2::asio_http2::header_map &getResponseHeaders() const {
     344          105 :         return response_headers_;
     345              :     }
     346              : 
     347              :     /** Provisioned response body as json representation
     348              :      *
     349              :      * @return Response body as json representation
     350              :      */
     351           33 :     const nlohmann::json &getResponseBody() const {
     352           33 :         return response_body_;
     353              :     }
     354              : 
     355              :     /** Provisioned response body as string.
     356              :      *
     357              :      * This is useful as cached response data when the provision
     358              :      * response is not modified with transformation items.
     359              :      *
     360              :      * When the object is not a valid json, the data is
     361              :      * assumed as a readable string (TODO: refactor for multipart support)
     362              :      *
     363              :      * @return Response body string
     364              :      */
     365           76 :     const std::string &getResponseBodyAsString() const {
     366           76 :         return response_body_string_;
     367              :     }
     368              : 
     369              :     /** Provisioned response delay milliseconds
     370              :      *
     371              :      * @return Response delay milliseconds
     372              :      */
     373          105 :     unsigned int getResponseDelayMilliseconds() const {
     374          105 :         return response_delay_ms_;
     375              :     }
     376              : 
     377              :     /** Provisioned request schema reference
     378              :      *
     379              :      * @return Request schema to validate incoming traffic, nullptr if missing
     380              :      */
     381              :     std::shared_ptr<h2agent::model::AdminSchema> getRequestSchema();
     382              : 
     383              :     /** Provisioned response schema reference
     384              :      *
     385              :      * @return Response schema to validate outgoing traffic, nullptr if missing
     386              :      */
     387              :     std::shared_ptr<h2agent::model::AdminSchema> getResponseSchema();
     388              : 
     389              :     /** Provision was employed
     390              :      *
     391              :      * @return Boolean about if this provision has been used
     392              :      */
     393            0 :     bool employed() const {
     394            0 :         return employed_;
     395              :     }
     396              : 
     397              :     /**
     398              :      * Checks if this provision references event-dependent transformation types
     399              :      * (serverEvent/clientEvent sources or serverEventToPurge/clientEventToPurge targets)
     400              :      *
     401              :      * @return True if any transformation requires stored events
     402              :      */
     403            8 :     bool needsStorage() const {
     404            8 :         for (const auto& t : transformations_) {
     405            3 :             auto st = t->getSourceType();
     406            3 :             auto tt = t->getTargetType();
     407            3 :             if (st == Transformation::ServerEvent || st == Transformation::ClientEvent ||
     408            0 :                 tt == Transformation::ServerEventToPurge || tt == Transformation::ClientEventToPurge)
     409            3 :                 return true;
     410              :         }
     411            5 :         return false;
     412              :     }
     413              : };
     414              : 
     415              : }
     416              : }
     417              : 
        

Generated by: LCOV version 2.0-1