Skip to content

Commit 0e6bf15

Browse files
authored
Merge pull request #1125 from gregory-shklover/gshklove_noproxy
Added handling no_proxy override through Proxies
2 parents c44f8d5 + c8fb3e8 commit 0e6bf15

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

cpr/session.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "cpr/session.h"
22

3+
#include <array>
34
#include <atomic>
45
#include <cassert>
56
#include <cstdint>
@@ -180,6 +181,15 @@ void Session::prepareCommonShared() {
180181
curl_easy_setopt(curl_->handle, CURLOPT_PROXYPASSWORD, proxyAuth_.GetPassword(protocol));
181182
}
182183
}
184+
// handle NO_PROXY override passed through Proxies object
185+
// Example: Proxies{"no_proxy": ""} will override environment variable definition with an empty list
186+
const std::array<std::string, 2> no_proxy{"no_proxy", "NO_PROXY"};
187+
for (const auto& item : no_proxy) {
188+
if (proxies_.has(item)) {
189+
curl_easy_setopt(curl_->handle, CURLOPT_NOPROXY, proxies_[item].c_str());
190+
break;
191+
}
192+
}
183193

184194
#if LIBCURL_VERSION_NUM >= 0x071506 // 7.21.6
185195
if (acceptEncoding_.empty()) {

test/proxy_tests.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
#include <gtest/gtest.h>
22

3+
#include <chrono>
4+
#include <stdlib.h>
35
#include <string>
6+
#include <sstream>
47

58
#include "cpr/cpr.h"
69

710
// TODO: This uses public servers for proxies and endpoints. This should be replaced with a source
811
// code implementation inside server.cpp
912

13+
// NOTES:
14+
// * For no-proxy testing need to run the tests with direct connection to the internet
15+
// * List of free proxies for testing can be found at https://proxy-list.org/english/index.php
16+
// Example: #define HTTP_PROXY "http://162.223.90.130:80"
1017
#define HTTP_PROXY "51.159.4.98:80"
1118
#define HTTPS_PROXY "51.104.53.182:8000"
1219

20+
1321
using namespace cpr;
1422

1523
TEST(ProxyTests, SingleProxyTest) {
@@ -79,13 +87,57 @@ TEST(ProxyTests, ReferenceProxySessionTest) {
7987
Session session;
8088
session.SetUrl(url);
8189
session.SetProxies(proxies);
90+
session.SetTimeout(std::chrono::seconds(10));
8291
Response response = session.Get();
8392
EXPECT_EQ(url, response.url);
8493
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
8594
EXPECT_EQ(200, response.status_code);
8695
EXPECT_EQ(ErrorCode::OK, response.error.code);
8796
}
8897

98+
TEST(ProxyTests, NoProxyTest) {
99+
setenv("NO_PROXY", "httpbin.org", 1);
100+
try {
101+
Url url{"http://www.httpbin.org/get"};
102+
Proxies proxies{{"http", HTTP_PROXY}, {"no_proxy", ""}};
103+
Session session;
104+
session.SetUrl(url);
105+
session.SetProxies(proxies);
106+
session.SetTimeout(std::chrono::seconds(10));
107+
Response response = session.Get();
108+
EXPECT_EQ(url, response.url);
109+
EXPECT_EQ(std::string{"application/json"}, response.header["content-type"]);
110+
EXPECT_EQ(200, response.status_code);
111+
EXPECT_EQ(ErrorCode::OK, response.error.code);
112+
113+
// check that access was performed through the proxy
114+
std::string proxy_ip = HTTP_PROXY;
115+
if (proxy_ip[0] == 'h') {
116+
// drop protocol:
117+
proxy_ip = proxy_ip.substr(proxy_ip.find(':') + 3);
118+
}
119+
// drop port:
120+
proxy_ip = proxy_ip.substr(0, proxy_ip.find(':'));
121+
122+
// find "origin": "ip" in response:
123+
bool found = false;
124+
std::istringstream body(response.text);
125+
std::string line;
126+
while (std::getline(body, line)) {
127+
// example: "origin": "123.456.789.123"
128+
if (line.find("\"origin\":") != std::string::npos) {
129+
found = line.find(proxy_ip) != std::string::npos;
130+
break;
131+
}
132+
}
133+
EXPECT_TRUE(found);
134+
} catch (...) {
135+
unsetenv("NO_PROXY");
136+
throw;
137+
}
138+
unsetenv("NO_PROXY");
139+
}
140+
89141
int main(int argc, char** argv) {
90142
::testing::InitGoogleTest(&argc, argv);
91143
return RUN_ALL_TESTS();

0 commit comments

Comments
 (0)