LCOV - code coverage report
Current view: top level - http/client - form.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 3 3
Test Date: 2026-02-20 15:38:22 Functions: 100.0 % 3 3

            Line data    Source code
       1              : #ifndef THINGER_HTTP_CLIENT_FORM_HPP
       2              : #define THINGER_HTTP_CLIENT_FORM_HPP
       3              : 
       4              : #include <string>
       5              : #include <vector>
       6              : #include <filesystem>
       7              : #include <optional>
       8              : 
       9              : namespace thinger::http {
      10              : 
      11              : /**
      12              :  * HTTP form builder for POST requests.
      13              :  * Supports both URL-encoded and multipart form data.
      14              :  *
      15              :  * Usage:
      16              :  *   // Simple form (auto URL-encoded)
      17              :  *   http::form form;
      18              :  *   form.field("username", "john")
      19              :  *       .field("password", "secret");
      20              :  *   auto res = client.post(url, form);
      21              :  *
      22              :  *   // With files (auto multipart)
      23              :  *   http::form form;
      24              :  *   form.field("name", "John")
      25              :  *       .file("avatar", "/path/to/photo.jpg")
      26              :  *       .file("data", buffer, "data.bin", "application/octet-stream");
      27              :  *   auto res = client.post(url, form);
      28              :  */
      29              : class form {
      30              : public:
      31           24 :     form() = default;
      32              : 
      33              :     // ============================================
      34              :     // Field methods (chainable)
      35              :     // ============================================
      36              : 
      37              :     /**
      38              :      * Add a text field to the form.
      39              :      */
      40              :     form& field(std::string name, std::string value);
      41              : 
      42              :     /**
      43              :      * Add multiple fields at once.
      44              :      */
      45              :     form& fields(std::initializer_list<std::pair<std::string, std::string>> pairs);
      46              : 
      47              :     // ============================================
      48              :     // File methods (chainable)
      49              :     // ============================================
      50              : 
      51              :     /**
      52              :      * Add a file from filesystem path.
      53              :      * Content-type is auto-detected from extension.
      54              :      */
      55              :     form& file(std::string name, const std::filesystem::path& path);
      56              : 
      57              :     /**
      58              :      * Add a file from filesystem path with explicit content type.
      59              :      */
      60              :     form& file(std::string name, const std::filesystem::path& path,
      61              :                std::string content_type);
      62              : 
      63              :     /**
      64              :      * Add a file from memory buffer.
      65              :      */
      66              :     form& file(std::string name, std::string content,
      67              :                std::string filename,
      68              :                std::string content_type = "application/octet-stream");
      69              : 
      70              :     /**
      71              :      * Add a file from memory buffer (binary data).
      72              :      */
      73              :     form& file(std::string name, const void* data, size_t size,
      74              :                std::string filename,
      75              :                std::string content_type = "application/octet-stream");
      76              : 
      77              :     // ============================================
      78              :     // Query methods
      79              :     // ============================================
      80              : 
      81              :     /**
      82              :      * Returns true if form has files (will use multipart encoding).
      83              :      */
      84           34 :     bool is_multipart() const { return !files_.empty(); }
      85              : 
      86              :     /**
      87              :      * Returns true if form is empty.
      88              :      */
      89            8 :     bool empty() const { return fields_.empty() && files_.empty(); }
      90              : 
      91              :     /**
      92              :      * Get the appropriate Content-Type header value.
      93              :      */
      94              :     std::string content_type() const;
      95              : 
      96              :     /**
      97              :      * Build the request body.
      98              :      */
      99              :     std::string body() const;
     100              : 
     101              :     // ============================================
     102              :     // Static utilities
     103              :     // ============================================
     104              : 
     105              :     /**
     106              :      * URL-encode a string.
     107              :      */
     108              :     static std::string url_encode(const std::string& str);
     109              : 
     110              :     /**
     111              :      * URL-decode a string.
     112              :      */
     113              :     static std::string url_decode(const std::string& str);
     114              : 
     115              :     /**
     116              :      * Guess MIME type from file extension.
     117              :      */
     118              :     static std::string mime_type(const std::filesystem::path& path);
     119              : 
     120              : private:
     121              :     struct file_entry {
     122              :         std::string name;           // Form field name
     123              :         std::string filename;       // Original filename
     124              :         std::string content_type;   // MIME type
     125              :         std::string content;        // File content
     126              :     };
     127              : 
     128              :     std::vector<std::pair<std::string, std::string>> fields_;
     129              :     std::vector<file_entry> files_;
     130              :     mutable std::string boundary_;  // Generated on first use
     131              : 
     132              :     std::string build_urlencoded() const;
     133              :     std::string build_multipart() const;
     134              :     const std::string& get_boundary() const;
     135              :     static std::string generate_boundary();
     136              : };
     137              : 
     138              : } // namespace thinger::http
     139              : 
     140              : #endif
        

Generated by: LCOV version 2.0-1