22#include < cstddef>
33#include < cstdint>
44#include < filesystem>
5+ #include < map>
56#include < memory>
67#include < string>
78#include < string_view>
@@ -188,3 +189,54 @@ TEST_CASE("network_reader_illegal_offset", "[NetworkReader]") {
188189 size_t pos{};
189190 REQUIRE ((clp::ErrorCode_Failure == reader.try_get_pos (pos)));
190191}
192+
193+ TEST_CASE (" network_reader_with_custom_headers" , " [NetworkReader]" ) {
194+ std::map<std::string, std::string> custom_headers = std::map<std::string, std::string>();
195+ // We use httpbin (https://httpbin.org/) to test the custom headers. This request will return a
196+ // JSON object that contains the custom headers. We check if the headers are in the response.
197+ const int NR_HEADERS = 10 ;
198+ for (int i = 0 ; i < NR_HEADERS; i++) {
199+ std::string key = " Unit-Test-Key" + std::to_string (i);
200+ std::string value = " Unit-Test-Value" + std::to_string (i);
201+ custom_headers[key] = value;
202+ }
203+ // The following three headers are determined by offset and disable_cache, which should not be
204+ // overrided by custom headers.
205+ custom_headers[" Range" ] = " bytes=100-" ;
206+ custom_headers[" Cache-Control" ] = " no-cache" ;
207+ custom_headers[" Pragma" ] = " no-cache" ;
208+ // Some illegal custom header names and values, which should not be added into headers
209+ custom_headers[" A Space" ] = " xx" ;
210+ custom_headers[" A\n Newline" ] = " xx" ;
211+ custom_headers[" An@At" ] = " xx" ;
212+ custom_headers[" -Start-with-Non-Alphanumeric" ] = " xx" ;
213+ custom_headers[" Legal-Name1" ] = " newline\n " ;
214+ custom_headers[" Legal-Name2" ] = " control-char\x01 " ;
215+ clp::NetworkReader reader{
216+ " https://httpbin.org/headers" ,
217+ 0 ,
218+ false ,
219+ clp::CurlDownloadHandler::cDefaultOverallTimeout,
220+ clp::CurlDownloadHandler::cDefaultConnectionTimeout,
221+ clp::NetworkReader::cDefaultBufferPoolSize,
222+ clp::NetworkReader::cDefaultBufferSize,
223+ custom_headers
224+ };
225+ auto const actual{get_content (reader)};
226+ std::string actual_string (actual.begin (), actual.end ());
227+ REQUIRE (assert_curl_error_code (CURLE_OK, reader));
228+ for (int i = 0 ; i < NR_HEADERS; i++) {
229+ std::string field = " \" Unit-Test-Key" + std::to_string (i) + " \" : \" Unit-Test-Value"
230+ + std::to_string (i) + " \" " ;
231+ REQUIRE (std::string::npos != actual_string.find (field));
232+ }
233+ REQUIRE (std::string::npos == actual_string.find (" Range: bytes=100-" ));
234+ REQUIRE (std::string::npos == actual_string.find (" Cache-Control: no-cache" ));
235+ REQUIRE (std::string::npos == actual_string.find (" Pragma: no-cache" ));
236+ REQUIRE (std::string::npos == actual_string.find (" A Space:" ));
237+ REQUIRE (std::string::npos == actual_string.find (" A\n Newline:" ));
238+ REQUIRE (std::string::npos == actual_string.find (" An@At:" ));
239+ REQUIRE (std::string::npos == actual_string.find (" -Start-with-Non-Alphanumeric:" ));
240+ REQUIRE (std::string::npos == actual_string.find (" Legal-Name1:" ));
241+ REQUIRE (std::string::npos == actual_string.find (" Legal-Name2:" ));
242+ }
0 commit comments