C++ Tunnel Proxy: libcurl and CPR Two Implementations

C++ libcurl and CPR libraries integrating 16Yun Crawler Proxy.

16Yun Engineering TeamMay 5, 20261 min read

libcurl

libcurl 是最广泛使用的 C/C++ HTTP 客户端库。通过 CURLOPT_PROXY 等选项配置代理。

#include <curl/curl.h>
#include <string>
#include <iostream>

size_t writeCallback(void* contents, size_t size, size_t nmemb, std::string* out) {
    size_t total = size * nmemb;
    out->append((char*)contents, total);
    return total;
}

int main() {
    curl_global_init(CURL_GLOBAL_DEFAULT);
    CURL* curl = curl_easy_init();

    if (curl) {
        const char* host = std::getenv("PROXY_HOST") ?: "t.16yun.cn";
        const char* port = std::getenv("PROXY_PORT") ?: "31111";
        const char* user = std::getenv("PROXY_USERNAME") ?: "user";
        const char* pass = std::getenv("PROXY_PASSWORD") ?: "password";

        curl_easy_setopt(curl, CURLOPT_URL, "https://httpbin.org/ip");
        curl_easy_setopt(curl, CURLOPT_PROXY, host);
        curl_easy_setopt(curl, CURLOPT_PROXYPORT, atoi(port));
        curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, (std::string(user) + ":" + pass).c_str());
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);

        std::string response;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        // Proxy-Tunnel header
        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Proxy-Tunnel: cpp-demo");
        curl_easy_setopt(curl, CURLOPT_PROXYHEADER, headers);

        CURLcode res = curl_easy_perform(curl);
        if (res == CURLE_OK) {
            std::cout << response << std::endl;
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    return 0;
}

CPR

CPR 是基于 libcurl 的现代 C++ HTTP 库,API 更简洁:

#include <cpr/cpr.h>
#include <iostream>

int main() {
    std::string host = std::getenv("PROXY_HOST") ?: "t.16yun.cn";
    std::string port = std::getenv("PROXY_PORT") ?: "31111";
    std::string user = std::getenv("PROXY_USERNAME") ?: "user";
    std::string pass = std::getenv("PROXY_PASSWORD") ?: "password";

    cpr::Response r = cpr::Get(
        cpr::Url{"https://httpbin.org/ip"},
        cpr::Proxies{{"https", "http://" + host + ":" + port}},
        cpr::ProxyAuthentication{{"https", cpr::EncodedAuthentication{user, pass}}},
        cpr::Header{{"Proxy-Tunnel", "cpp-cpr-demo"}},
        cpr::VerifySsl{false},
        cpr::Timeout{15000}
    );

    std::cout << r.text << std::endl;
    return 0;
}

两种方案对比

特性libcurlCPR
依赖libcurl-devlibcurl + CPR header-only
API 风格C 风格,手动管理现代 C++,链式调用
HTTPS
HTTPS TunnelCURLOPT_PROXYHEADERcpr::Header
复杂度较高

Need an enterprise proxy plan?

We can tailor architecture to your target domains, concurrency, and reliability goals.