• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mbits-os / quick_dra / 22041537858

15 Feb 2026 07:18PM UTC coverage: 95.231% (+8.2%) from 87.008%
22041537858

Pull #39

github

web-flow
Merge 78efb5eb1 into 7d773e4d9
Pull Request #39: testing

16 of 18 new or added lines in 8 files covered. (88.89%)

35 existing lines in 6 files now uncovered.

4193 of 4403 relevant lines covered (95.23%)

1610.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.12
/libs/libforms/src/io/http.cpp
1
// Copyright (c) 2026 midnightBITS
2
// This code is licensed under MIT license (see LICENSE for details)
3

4
#define NOMINMAX
5

6
#include <curl/curl.h>
7
#include <fmt/format.h>
8
#include <memory>
9
#include <quick_dra/base/str.hpp>
10
#include <quick_dra/io/http.hpp>
11
#include <quick_dra/version.hpp>
12
#include <span>
13
#include <stdexcept>
14

15
namespace quick_dra {
16
        namespace {
17
                struct curl_global_initer {
18
                        curl_global_initer() {
31✔
19
                                if (::curl_global_init(CURL_GLOBAL_DEFAULT) != 0)
31✔
20
                                        throw std::runtime_error(
21
                                            "CURL global initialization failed");
22
                        }
91✔
23
                        ~curl_global_initer() { ::curl_global_cleanup(); }
31✔
24
                };
25

26
                struct curl_cleanup {
27
                        void operator()(CURL* p) const { ::curl_easy_cleanup(p); }
31✔
28
                };
29

30
                using curl_ptr = std::unique_ptr<CURL, curl_cleanup>;
31

32
                curl_ptr curl_easy_init() {
31✔
33
                        static const curl_global_initer init{};
91✔
34
                        return curl_ptr{::curl_easy_init()};
91✔
35
                }
61✔
36

37
                CURLcode curl_easy_setopt(curl_ptr const& curl,
180✔
38
                                          CURLoption option,
39
                                          auto arg) {
1✔
40
                        return ::curl_easy_setopt(curl.get(), option, arg);
541✔
41
                }
361✔
42

43
                CURLcode curl_easy_perform(curl_ptr const& curl) {
31✔
44
                        return ::curl_easy_perform(curl.get());
91✔
45
                }
61✔
46

47
                auto ua_version() noexcept {
31✔
48
                        if constexpr (version::major < 1) {
60✔
49
                                return version::string;
91✔
50
                        } else {
60✔
51
                                return version::string_short;
52
                        }
53
                }
61✔
54
        }  // namespace
55

56
        http_response http_get(std::string const& url) try {
31✔
57
                http_response response{};
90✔
58

60✔
59
                auto curl = curl_easy_init();
91✔
60
                if (!curl) return response;
31✔
61

60✔
62
                auto const ua = fmt::format("{}/{}", version::program, ua_version());
41✔
63

60✔
64
                curl_easy_setopt(curl, CURLOPT_USERAGENT, ua.c_str());
91✔
65
                curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
91✔
66
                curl_write_callback write_cb = [](char* contents, std::size_t size,
121✔
67
                                                  std::size_t nmemb,
60✔
68
                                                  void* userp) -> std::size_t {
1✔
69
                        auto& resp = *static_cast<http_response*>(userp);
91✔
70
                        auto realsize = size * nmemb;
91✔
71
                        auto bytes = reinterpret_cast<std::byte*>(contents);
91✔
72
                        resp.content.insert(resp.content.end(), bytes, bytes + realsize);
91✔
73
                        return realsize;
91✔
74
                };
61✔
75
                curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
91✔
76
                curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb);
91✔
77
                curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
91✔
78
                curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
91✔
79
                if (curl_easy_perform(curl) != CURLE_OK) {
31✔
UNCOV
80
                        return response.cleaned();
×
81
                }
82

60✔
83
                long code;
10✔
84
                if (curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, &code) !=
31✔
85
                    CURLE_OK) {
60✔
86
                        return response.cleaned();
×
87
                }
88
                response.status = static_cast<unsigned>(std::max(code, 0l));
31✔
89

60✔
90
                curl_header* header{};
91✔
91
                if (curl_easy_header(curl.get(), "Content-Type", 0, CURLH_HEADER, -1,
30✔
92
                                     &header) != CURLHE_OK) {
91✔
93
                        return response.cleaned();
×
94
                }
95
                auto const view = std::string_view{header->value};
31✔
96
                auto const split_view = split_sv(view, ';'_sep);
91✔
97

60✔
98
                auto const type_subtype = split_sv(split_view[0], '/'_sep, 1);
91✔
99
                if (type_subtype.size() == 2) {
31✔
100
                        response.content_type.type = strip_sv(type_subtype[0]);
91✔
101
                        response.content_type.subtype = strip_sv(type_subtype[1]);
91✔
102
                }
60✔
103

60✔
104
                auto const params = std::span{split_view}.subspan(1);
91✔
105
                for (auto const& param_view : params) {
61✔
106
                        auto const name_value = split_sv(param_view, '='_sep, 1);
91✔
107
                        if (name_value.size() != 2) {
31✔
UNCOV
108
                                continue;
×
109
                        }
110
                        if (strip_sv(name_value[0]) != "charset"sv) {
31✔
UNCOV
111
                                continue;
×
112
                        }
113
                        response.charset = strip_sv(name_value[1]);
31✔
114
                }
91✔
115

60✔
116
                return response;
91✔
117
        } catch (std::exception& error) {
31✔
UNCOV
118
                fmt::print(stderr,
×
119
                           "Quick-DRA: error: {}\n"
120
                           "           while downloading {}\n",
121
                           error.what(), url);
UNCOV
122
                return http_response{};
×
123
        }
×
124
}  // namespace quick_dra
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc