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

mbits-os / quick_dra / 22038263728

15 Feb 2026 03:31PM UTC coverage: 93.378% (+6.4%) from 87.008%
22038263728

Pull #39

github

web-flow
Merge 74a89bbd4 into 7d773e4d9
Pull Request #39: testing

58 of 67 new or added lines in 23 files covered. (86.57%)

75 existing lines in 12 files now uncovered.

4033 of 4319 relevant lines covered (93.38%)

1107.01 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() {
22✔
19
                                if (::curl_global_init(CURL_GLOBAL_DEFAULT) != 0)
22✔
20
                                        throw std::runtime_error(
21
                                            "CURL global initialization failed");
22
                        }
64✔
23
                        ~curl_global_initer() { ::curl_global_cleanup(); }
22✔
24
                };
25

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

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

32
                curl_ptr curl_easy_init() {
22✔
33
                        static const curl_global_initer init{};
64✔
34
                        return curl_ptr{::curl_easy_init()};
64✔
35
                }
43✔
36

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

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

47
                auto ua_version() noexcept {
22✔
48
                        if constexpr (version::major < 1) {
42✔
49
                                return version::string;
64✔
50
                        } else {
42✔
51
                                return version::string_short;
52
                        }
53
                }
43✔
54
        }  // namespace
55

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

42✔
59
                auto curl = curl_easy_init();
64✔
60
                if (!curl) return response;
22✔
61

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

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

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

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

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

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

42✔
116
                return response;
64✔
117
        } catch (std::exception& error) {
22✔
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