LCOV - code coverage report
Current view: top level - model - DataPart.hpp (source / functions) Coverage Total Hit
Test: final-coverage.info Lines: 100.0 % 44 44
Test Date: 2025-02-14 17:40:40 Functions: 100.0 % 16 16

            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 <string>
      41              : 
      42              : #include <nlohmann/json.hpp>
      43              : 
      44              : #include <ert/multipart/Consumer.hpp>
      45              : 
      46              : namespace h2agent
      47              : {
      48              : namespace model
      49              : {
      50              : 
      51              : class DataPart;
      52              : 
      53              : /**
      54              :  * Multipart consumer specialization for h2agent
      55              :  */
      56              : class MyMultipartConsumer : public ert::multipart::Consumer {
      57              :     DataPart *data_part_;
      58              :     std::string content_type_;
      59              :     int data_count_;
      60              : 
      61              : public:
      62            1 :     MyMultipartConsumer(const std::string &boundary, DataPart *dp) : ert::multipart::Consumer(boundary), data_part_(dp), data_count_(1) {;}
      63            1 :     ~MyMultipartConsumer() {;}
      64              : 
      65              :     void receiveHeader(const std::string &name, const std::string &value);
      66              :     void receiveData(const std::string &data);
      67              : };
      68              : 
      69              : /**
      70              :  * DataPart to store request/response body data
      71              :  * Also provides a way to represent data in json format, even for basic string values.
      72              :  *
      73              :  * So, when the body data is human-readable, the field "<request|response>Body"
      74              :  * will be the string itself as readable string:
      75              :  *
      76              :  * <pre>
      77              :  * "<request|response>Body": "this is human-readable text content"
      78              :  * </pre>
      79              :  *
      80              :  * When the body data is not human-readable, the field "<request|response>Body"
      81              :  * will be the data itself as hexadecimal string with prefix '0x':
      82              :  *
      83              :  * <pre>
      84              :  * "<request|response>Body": "0xc0a80100"
      85              :  * </pre>
      86              :  *
      87              :  * It is important to know the content-type, to understand that '0x' is not
      88              :  * part of an arbitrary string but an indicator of binary internal data which
      89              :  * could not be represented directly.
      90              :  *
      91              :  * When the body data is json content, the field "<request|response>Body"
      92              :  * will be the json object itself:
      93              :  *
      94              :  * <pre>
      95              :  * "<request|response>Body": { "foo": "bar" }
      96              :  * </pre>
      97              :  *
      98              :  * Other complex types like multipart could have an h2agent proprietary json representation
      99              :  * like this:
     100              :  *
     101              :  * <pre>
     102              :  * "<request|response>Body": {
     103              :  *   "multipart.1": {
     104              :  *     "headers": [ { "content-type": "text/html" } ]
     105              :  *     "content": "<h2 class=\"fg-white\">"
     106              :  *   },
     107              :  *   "multipart.2": {
     108              :  *     "headers": [ { "content-type": "application/octet-stream" } ]
     109              :  *     "content": "0xc0a80100"
     110              :  *   },
     111              :  *   "multipart.3": {
     112              :  *     "headers": [ { "content-type": "application/json" } ]
     113              :  *     "content": { "foo": "bar" }
     114              :  *   }
     115              :  * }
     116              :  * </pre>
     117              :  */
     118              : class DataPart {
     119              :     std::string str_; // raw data content: always filled with the original data received
     120              :     bool decoded_; // lazy decode indicator to skip multiple decode operations
     121              :     bool is_json_; // if not, we will use str_ as native source instead of json representation
     122              : 
     123              :     nlohmann::json json_; // data json representation valid for:
     124              :     // 1) parse json strings received (application/json)
     125              :     // 2) represent proprietary multipart json structure (multipart/?)
     126              :     // 3) represent human-readable strings (https://stackoverflow.com/questions/7487869/is-this-simple-string-considered-valid-json)
     127              :     // 4) represent non human-readable strings, as hex string prefixed with '0x'.
     128              : 
     129              :     // Note that 3) and 4) are using nlohmann::json to store a string, which is a shortcut for class json representation.
     130              :     // You shall cast it to string or use special library getters:
     131              :     //   std::string content = doc["example"]
     132              :     //   - or -
     133              :     //   doc["example"].get<std::string>()
     134              : 
     135              : public:
     136              :     /** Default constructor */
     137          575 :     DataPart() : decoded_(false), is_json_(false) {;}
     138              : 
     139              :     /** String constructor */
     140           12 :     DataPart(const std::string &str) : str_(str), decoded_(false), is_json_(false) {;}
     141              : 
     142              :     /** Move string constructor */
     143            2 :     DataPart(std::string &&str) : str_(std::move(str)), decoded_(false), is_json_(false) {;}
     144              : 
     145              :     /** Constructor */
     146            2 :     DataPart(const DataPart &bd) {
     147            2 :         *this = bd;
     148            2 :     }
     149              : 
     150              :     /** Move constructor */
     151            1 :     DataPart(DataPart &&bd) {
     152            1 :         *this = std::move(bd);
     153            1 :     }
     154              : 
     155              :     /** Destructor */
     156          592 :     ~DataPart() {;}
     157              : 
     158              :     /** Copy assignment */
     159            2 :     DataPart& operator=(const DataPart& other) noexcept {
     160            2 :         if (this != &other) {
     161            2 :             str_ = other.str_;
     162            2 :             decoded_ = other.decoded_;
     163            2 :             is_json_ = other.is_json_;
     164            2 :             json_ = other.json_;
     165              :         }
     166            2 :         return *this;
     167              :     }
     168              : 
     169              :     /** Move assignment */
     170            1 :     DataPart& operator=(DataPart&& other) noexcept {
     171            1 :         if (this != &other) {
     172            1 :             str_ = std::move(other.str_);
     173            1 :             json_ = std::move(other.json_);
     174            1 :             decoded_ = other.decoded_; // it has no sense to move
     175            1 :             is_json_ = other.is_json_; // it has no sense to move
     176              :         }
     177            1 :         return *this;
     178              :     }
     179              : 
     180              :     /** comparison operator */
     181            5 :     bool operator==(const DataPart &other) const {
     182            5 :         return str() == other.str();
     183              :     }
     184              : 
     185              :     /** getter for class data */
     186          296 :     const std::string &str() const {
     187          296 :         return str_;
     188              :     }
     189              : 
     190              :     /** getter to know if data was decoded as json (multipart is always representable as json) */
     191           21 :     bool isJson() const {
     192           21 :         return is_json_;
     193              :     }
     194              : 
     195              :     /** str as ascii string */
     196              :     std::string asAsciiString() const;
     197              : 
     198              :     /** getter for class data representation in json proprietary format */
     199          544 :     const nlohmann::json &getJson() const {
     200          544 :         return json_;
     201              :     }
     202              : 
     203              :     /** setters for class data */
     204          181 :     void assign(std::string &&str) {
     205          181 :         str_ = std::move(str);
     206          181 :         decoded_ = false;
     207          181 :         is_json_ = false;
     208          181 :     }
     209          373 :     void assign(const std::string &str) {
     210          373 :         str_ = str;
     211          373 :         decoded_ = false;
     212          373 :         is_json_ = false;
     213          373 :     }
     214              :     bool assignFromHex(const std::string &strAsHex);
     215              : 
     216              :     /** save json data decoded */
     217              :     void decodeContent(const std::string &content, const std::string &contentType, nlohmann::json &j);
     218              : 
     219              :     /** decode string data depending on content type */
     220              :     void decode(const nghttp2::asio_http2::header_map &headers /* to get the content-type */);
     221              : 
     222              :     friend class MyMultipartConsumer;
     223              : };
     224              : 
     225              : }
     226              : }
     227              : 
        

Generated by: LCOV version 2.0-1