Ngiêm cấm sử đụng PROXY và VPS vào mục đích trái pháp luật bạn sẽ phải chịu toàn bộ trách nhiệm trước pháp luật khi sử dụng dịch vụ của chúng tôi tks!
C++ CPR proxy: Proxies, ProxyAuthentication và lỗi mật khẩu

C++ CPR proxy: Proxies, ProxyAuthentication và lỗi mật khẩu

Chuyên viên Kỹ thuật ProxyVN 08-01-2026 Đang tính... phút đọc

C++ CPR proxy là cách cho thư viện CPR, lớp bọc C++ hiện đại quanh libcurl, gửi request qua máy trung gian. CPR đặt proxy bằng đối tượng Proxies dạng map theo giao thức, tài khoản bằng ProxyAuthentication. ProxyVN đọc tài liệu và mã nguồn CPR 1.15.1, rồi mô phỏng đúng lời gọi libcurl của CPR qua cùng libcurl 8.23 để kiểm một bẫy mật khẩu dễ gặp.

C++ CPR proxy bọc libcurl theo kiểu C++

CPR là gì và khác libcurl ở đâu

CPR viết tắt của C++ Requests, lấy cảm hứng từ thư viện Requests của Python. Thay vì gọi curl_easy_setopt từng dòng, anh em gọi cpr::Get với các đối tượng như cpr::Url, cpr::Header, cpr::Proxies. Kết quả là một cpr::Response có status_code, text, header và error.

Bên dưới, mọi thứ vẫn là libcurl. Đọc tệp session.cpp trong kho libcpr/cpr trên GitHub, hàm prepareProxy gọi curl_easy_setopt với CURLOPT_PROXY, CURLOPT_PROXYUSERNAME và CURLOPT_PROXYPASSWORD. Nghĩa là hành vi mạng của CPR proxy chính là hành vi của libcurl với ba tùy chọn đó.

Hiểu CPR đặt tùy chọn libcurl nào giúp đọc lỗi đúng chỗ. Nhiều lỗi khó hiểu của CPR proxy trở nên rõ ràng khi nhìn vào lời gọi libcurl bên dưới.

Ranh giới với các bài libcurl và cURL

Bài curl proxy là gì nói về lệnh curl. Bài PHP cURL proxy nói về curl_setopt trong PHP. Bài này không lặp các tùy chọn libcurl ở mức chung, chỉ đi vào API của CPR: Proxies theo giao thức, ProxyAuthentication, Session, no_proxy, cách CPR đánh số lỗi, và một bẫy riêng của EncodedAuthentication.

Nếu dự án viết thẳng bằng C với libcurl, không qua CPR, phần tùy chọn libcurl vẫn áp dụng nhưng cách đặt khác. Với CPR, mọi thứ đi qua đối tượng C++, và đó là chỗ có thể lệch so với mong đợi.

Phạm vi kiểm thử

Máy lab hôm viết bài không có trình biên dịch C++, CMake hay vcpkg, nên mình chưa biên dịch và chạy chương trình CPR. Thay vào đó, mình đọc mã nguồn CPR nhánh master ngày 27/10/2026, bản phát hành mới nhất trên GitHub là 1.15.1. Sau đó mình mô phỏng đúng các lời gọi curl_easy_setopt mà CPR thực hiện bằng PycURL dùng libcurl 8.23.0 trên cùng proxy thử.

Cách mô phỏng này kiểm được hành vi của libcurl khi nhận đúng các giá trị mà CPR truyền vào. Nó không thay được một lần chạy CPR thật, nên mình ghi rõ chỗ nào là đọc mã, chỗ nào là mô phỏng.

Thêm CPR vào project cho C++ CPR proxy

CMake với FetchContent

README của CPR hướng dẫn thêm thư viện bằng FetchContent của CMake. Khóa đúng thẻ phiên bản thay vì nhánh master để bản dựng lặp lại được.

include(FetchContent)
FetchContent_Declare(cpr
    GIT_REPOSITORY https://github.com/libcpr/cpr.git
    GIT_TAG 1.15.1)
FetchContent_MakeAvailable(cpr)
 
add_executable(proxy_lab main.cpp)
target_link_libraries(proxy_lab PRIVATE cpr::cpr)

CPR có thể tự tải và dựng libcurl đi kèm, hoặc dùng libcurl có sẵn trên hệ thống tùy tùy chọn CMake. Hành vi proxy phụ thuộc bản libcurl thật sự được liên kết, nên in curl_version() khi chương trình khởi động để biết đúng bản.

Gói vcpkg hoặc Conan

CPR có mặt trong vcpkg và Conan. Cài qua trình quản lý gói giúp không phải dựng libcurl tay. Khi dùng trình quản lý gói sau proxy công ty, chính trình quản lý gói cũng cần cấu hình proxy để tải mã nguồn, đó là chuyện riêng của vcpkg hay Conan.

Dù cài cách nào, ghi lại bản CPR và bản libcurl vào README. Khi có máy báo lỗi proxy khác máy khác, so hai con số này trước.

Thông tin proxy trong biến môi trường

Không ghi tài khoản proxy trong mã nguồn. Đọc từ biến môi trường bằng std::getenv hoặc từ tệp cấu hình không commit. Với chương trình chạy trên CI, đưa tài khoản vào mục secret.

Cấu hình C++ CPR proxy bằng Proxies

Proxies là map theo giao thức

Proxy chọn theo giao thức URL

Proxy chọn theo giao thức URL

Tài liệu nâng cao của CPR mô tả Proxies là đối tượng dạng map, giống Parameters. Khóa là giao thức của URL đích, giá trị là địa chỉ proxy.

#include <cpr/cpr.h>
#include <iostream>
 
int main() {
    cpr::Response r = cpr::Get(cpr::Url{"http://www.httpbin.org/get"},
                               cpr::Proxies{{"http", "http://203.0.113.10:8080"}});
    std::cout << r.status_code << " " << r.url << std::endl;
}

Tài liệu ghi r.url vẫn in địa chỉ website, không in địa chỉ proxy. Đừng dùng r.url để kiểm request có qua proxy hay không, vì nó không phản ánh đường đi.

CPR chọn proxy theo tiền tố URL

Trong mã, prepareProxy lấy phần đứng trước dấu hai chấm đầu tiên của URL làm giao thức, rồi tìm khóa đó trong Proxies. URL https://api.example.com có giao thức https, nên cần khóa https. Nếu Proxies chỉ có khóa http, CPR không đặt CURLOPT_PROXY cho request https.

Khi không đặt CURLOPT_PROXY, libcurl đọc biến môi trường. Nếu môi trường không có biến proxy, request https đi thẳng mà không có lỗi nào. Đây là lỗi hay gặp nhất: chép ví dụ chỉ có khóa http, gọi API https, và tưởng đã qua proxy.

cpr::Proxies proxies{{"http", "http://203.0.113.10:8080"},
                     {"https", "http://203.0.113.10:8080"}};

Giá trị của khóa https vẫn là URL proxy bắt đầu bằng http://, vì đó là cách kết nối tới chính proxy. libcurl sẽ mở đường hầm CONNECT tới website https qua proxy HTTP này.

Session cho nhiều request

Tài liệu cho thấy Proxies hữu ích nhất với cpr::Session. SetProxies một lần, rồi đổi URL cho từng request. Request http đi proxy của khóa http, request https đi proxy của khóa https, không phải khai lại.

cpr::Session session;
session.SetProxies({{"http", "http://proxy-a.example:8080"},
                    {"https", "http://proxy-b.example:8080"}});
session.SetUrl(cpr::Url{"https://api.example.com/items"});
cpr::Response r = session.Get();

Session giữ handle libcurl, nên kết nối tới proxy có thể được dùng lại giữa các request. Với chương trình gửi nhiều request, Session nhanh hơn gọi cpr::Get rời rạc.

Tài khoản C++ CPR proxy và bẫy mã hóa

Mật khẩu bị mã hóa hai lần

Mật khẩu bị mã hóa hai lần

ProxyAuthentication theo tài liệu

Tài liệu CPR ghi tài khoản proxy phải được mã hóa URL, và đưa ví dụ ProxyAuthentication với EncodedAuthentication cho khóa http. Lớp EncodedAuthentication nhận tên và mật khẩu thô, tự mã hóa trong hàm khởi tạo.

cpr::Response r = cpr::Get(
    cpr::Url{"http://www.httpbin.org/get"},
    cpr::Proxies{{"http", "http://proxy.example:8080"}},
    cpr::ProxyAuthentication{{"http", cpr::EncodedAuthentication{"user1", "p@ss#2026"}}});

Khóa của ProxyAuthentication cũng theo giao thức như Proxies. Gọi URL https mà chỉ có khóa http trong ProxyAuthentication, CPR không gửi tài khoản cho request https.

Mã hóa rồi đưa vào tùy chọn không giải mã

Đọc mã nguồn, hàm khởi tạo EncodedAuthentication gọi util::urlEncode cho cả tên và mật khẩu rồi lưu lại. Hàm GetPasswordUnderlying trả nguyên chuỗi đã mã hóa. prepareProxy truyền chuỗi đó vào CURLOPT_PROXYUSERNAME và CURLOPT_PROXYPASSWORD.

Vấn đề là libcurl dùng giá trị của hai tùy chọn này nguyên văn, không giải mã phần trăm. Mã hóa phần trăm chỉ có ý nghĩa khi tài khoản nằm trong URL. Với mật khẩu p@ss#2026, chuỗi gửi đi theo cách này là p%40ss%232026, không phải mật khẩu thật.

Mô phỏng bằng cùng libcurl

Để kiểm, mình dùng PycURL với libcurl 8.23.0, đặt đúng hai tùy chọn mà CPR đặt. Đặt PROXYUSERNAME là user1, PROXYPASSWORD là p@ss#2026 nguyên văn, proxy trả 200. Đặt PROXYPASSWORD là p%40ss%232026, tức chuỗi mà EncodedAuthentication tạo ra, proxy trả 407.

Với mật khẩu chỉ gồm chữ và số như simple2026, mã hóa không đổi gì, proxy trả 200. Nghĩa là lỗi chỉ lộ ra khi mật khẩu có ký tự đặc biệt, rất dễ lọt qua giai đoạn thử với mật khẩu đơn giản rồi hỏng khi dùng mật khẩu thật.

Nếu mật khẩu proxy có @, #, :, /, % hay dấu cách, đừng tin ProxyAuthentication cho tới khi tự kiểm. Đây là kết luận từ đọc mã nhánh master và mô phỏng lời gọi libcurl, chưa phải từ một lần chạy CPR thật.

Cách làm an toàn

Cách thứ nhất là đưa tài khoản vào URL proxy và tự mã hóa phần trăm. libcurl giải mã phần trăm trong phần tài khoản của URL proxy, điều mình đã xác nhận trong lab PycURL với chuỗi http://user1:p%40ss%[email protected]:8942.

std::string proxy = "http://" + url_encode(user) + ":" + url_encode(pass) + "@" + host + ":" + port;
cpr::Proxies proxies{{"http", proxy}, {"https", proxy}};

Hàm url_encode ở đây là hàm mã hóa phần trăm anh em tự viết hoặc lấy từ cpr::util nếu bản đang dùng có sẵn. Cách thứ hai là xin nhà cung cấp mật khẩu chỉ có chữ và số, hoặc dùng xác thực theo IP. Bài định dạng proxy có bảng mã hóa ký tự.

Bỏ qua proxy với no_proxy trong C++ CPR proxy

Khóa no_proxy trong Proxies

Tài liệu CPR ghi có thể dùng Proxies{{"no_proxy", "myhost.com"}} hoặc Proxies{{"no_proxy", ""}} để đè biến môi trường NO_PROXY. Trong mã, prepareCommonShared tìm khóa no_proxy hoặc NO_PROXY trong Proxies rồi đặt CURLOPT_NOPROXY.

cpr::Proxies proxies{{"http", proxy}, {"https", proxy},
                     {"no_proxy", "localhost,127.0.0.1,.corp.example"}};

Giá trị rỗng nghĩa là danh sách bỏ qua rỗng, mọi host đều đi proxy kể cả khi môi trường có NO_PROXY. Dùng khi muốn chương trình không bị ảnh hưởng bởi cấu hình máy.

Biến môi trường khi không đặt Proxies

Nếu không đặt khóa giao thức tương ứng trong Proxies, CPR không gọi CURLOPT_PROXY, và libcurl đọc biến môi trường. Tài liệu CURLOPT_PROXY của libcurl ghi http_proxy chỉ đọc bản chữ thường, https_proxy và các biến khác đọc cả hai bản.

Hệ quả: cùng một chương trình CPR, chạy trên máy có biến proxy thì đi proxy, chạy trên máy không có thì đi thẳng. Với chương trình bắt buộc đi proxy, luôn đặt đủ khóa trong Proxies, đừng dựa vào môi trường.

Bài no_proxy là gì giải thích quy ước viết danh sách bỏ qua.

SOCKS5 với C++ CPR proxy

Tiền tố trong URL proxy

Vì giá trị trong Proxies đi thẳng vào CURLOPT_PROXY, mọi tiền tố mà libcurl hiểu đều dùng được: socks5://, socks5h://, socks4://. Khóa của map vẫn là giao thức của URL đích, không phải giao thức của proxy.

cpr::Proxies proxies{{"http", "socks5h://127.0.0.1:1080"},
                     {"https", "socks5h://127.0.0.1:1080"}};

socks5 và socks5h

Lab PycURL với cùng libcurl cho thấy socks5:// phân giải tên miền tại máy, socks5h:// gửi tên miền cho proxy. Với tên chỉ phân giải được trong proxy, socks5:// báo lỗi không phân giải được host, socks5h:// chạy. Với CPR, hành vi giống hệt vì cùng tùy chọn libcurl.

Dùng socks5h để tránh rò truy vấn DNS. Bài DNS leak khi dùng proxy giải thích rủi ro. Tài khoản SOCKS đi qua cùng CURLOPT_PROXYUSERNAME, PROXYPASSWORD, nên bẫy mã hóa ở trên áp dụng y như proxy HTTP.

Đọc lỗi C++ CPR proxy

So lỗi bằng tên, không bằng số

So lỗi bằng tên, không bằng số

cpr::Error và ErrorCode riêng

CPR không ném ngoại lệ cho lỗi mạng. Response có trường error với code kiểu cpr::ErrorCode và message. Điểm cần chú ý: số của ErrorCode trong CPR không trùng với số CURLcode của libcurl.

Đọc tệp error.h, ErrorCode của CPR có COULDNT_RESOLVE_PROXY là 5, COULDNT_RESOLVE_HOST là 6, COULDNT_CONNECT là 7 giống libcurl. Nhưng HTTP_RETURNED_ERROR là 13 thay vì 22, OPERATION_TIMEDOUT là 18 thay vì 28, RECV_ERROR là 35 thay vì 56. So sánh bằng tên hằng, không so bằng số.

cpr::Response r = session.Get();
if (r.error.code == cpr::ErrorCode::COULDNT_RESOLVE_PROXY) {
    std::cerr << "Khong phan giai duoc proxy: " << r.error.message << "\n";
} else if (r.error.code == cpr::ErrorCode::OPERATION_TIMEDOUT) {
    std::cerr << "Qua han: " << r.error.message << "\n";
} else if (r.error) {
    std::cerr << "Loi mang: " << r.error.message << "\n";
} else if (r.status_code == 407) {
    std::cerr << "Proxy tu choi tai khoan\n";
} else if (r.status_code >= 400) {
    std::cerr << "Website tra " << r.status_code << "\n";
}

407 nằm ở hai nơi

Lab PycURL với cùng libcurl cho thấy: với URL http và tài khoản sai, libcurl hoàn tất trao đổi và trả mã 407 như một response, không có lỗi. Với URL https, libcurl báo lỗi CONNECT tunnel failed, response 407. Trong CPR, trường hợp đầu là status_code 407 với error rỗng, trường hợp sau là error có code khác OK và message chứa 407.

Mã xử lý ở trên kiểm status_code 407 sau khi không có error, phủ trường hợp http. Với https, kiểm message có chứa 407 trong nhánh lỗi mạng. Bài sửa lỗi 407 Proxy Authentication Required liệt kê nguyên nhân phía nhà cung cấp.

Bảng tra

Bảng dưới gom kết quả mô phỏng bằng libcurl và tên ErrorCode tương ứng trong CPR.

Bảng: Bảng tra

Tình huống

Hành vi libcurl trong lab

Trong CPR

Không khóa proxy cho giao thức, không biến môi trường

Đi thẳng

Không lỗi, không qua proxy

Mật khẩu qua EncodedAuthentication có ký tự đặc biệt

Proxy trả 407

status_code 407 hoặc lỗi CONNECT 407

Mật khẩu chưa mã hóa trong URL proxy

Không phân giải được proxy, tên lạ

ErrorCode::COULDNT_RESOLVE_PROXY

Proxy không mở cổng

Không kết nối được, over proxy

ErrorCode::COULDNT_CONNECT

Website chậm hơn Timeout

Quá hạn

ErrorCode::OPERATION_TIMEDOUT

Website trả 503

Response 503

status_code 503, không lỗi

socks5 với tên chỉ có trong proxy

Không phân giải được host

ErrorCode::COULDNT_RESOLVE_HOST

Với C++ CPR proxy, so lỗi bằng tên hằng cpr::ErrorCode, không bằng số. Số của CPR khác số CURLcode của libcurl ở nhiều mã quan trọng.

Timeout, redirect và thử lại trong C++ CPR proxy

Timeout và ConnectTimeout

CPR có cpr::Timeout cho cả request và cpr::ConnectTimeout cho bước kết nối, tính bằng mili giây. Khi đi qua proxy, ConnectTimeout đo kết nối tới proxy. Đặt cả hai cho mọi request qua proxy, vì mặc định libcurl không giới hạn thời gian tổng.

session.SetTimeout(cpr::Timeout{15000});
session.SetConnectTimeout(cpr::ConnectTimeout{5000});

Với tải tệp lớn, CPR có LowSpeed tương ứng LOW_SPEED_LIMIT của libcurl, cắt khi tốc độ quá thấp thay vì đặt Timeout quá dài.

Redirect

CPR mặc định theo redirect theo cấu hình của nó, có thể chỉnh bằng cpr::Redirect. Khi theo redirect qua proxy, tài khoản proxy dùng cho mọi chặng vì proxy không đổi. Với redirect từ http sang https, nhớ rằng CPR chọn proxy theo URL ban đầu khi chuẩn bị request, libcurl tự xử lý chặng sau với cấu hình proxy đã đặt.

Mình chưa kiểm chi tiết hành vi chọn proxy khi redirect đổi giao thức trong CPR. Nếu dự án gặp redirect http sang https qua proxy, đặt cùng một proxy cho cả hai khóa để tránh bất ngờ.

Thử lại

CPR không tự thử lại. Với lỗi COULDNT_CONNECT, OPERATION_TIMEDOUT hay RECV_ERROR qua proxy, tự viết vòng thử lại cho GET, giới hạn số lần, khoảng nghỉ tăng dần. Với POST tạo dữ liệu, không thử lại sau timeout. Khi website trả 429, đọc Retry-After. Bài lỗi 429 khi dùng proxy có cách xử lý.

Bất đồng bộ và nhiều proxy trong C++ CPR proxy

GetAsync và MultiPerform

CPR có các hàm Async trả future, và MultiPerform để chạy nhiều Session song song. Mỗi Session có Proxies riêng, nên có thể chia request ra nhiều proxy. Giới hạn số request đồng thời bằng hoặc thấp hơn hạn mức luồng của gói proxy.

Mình chưa chạy các hàm Async hay MultiPerform. Phần này dựa trên tài liệu. Với nhiều Session song song, mỗi Session giữ handle libcurl riêng, nhớ hủy hoặc tái sử dụng chúng đúng cách để không rò kết nối.

Một Session cho mỗi proxy

Với proxy xoay đổi IP theo tên người dùng, mỗi phiên cần một Session với tài khoản riêng. Với nhiều proxy tĩnh, một Session cho mỗi proxy, chọn Session theo vòng. Không đổi Proxies liên tục trên cùng một Session đang có kết nối giữ sẵn, vì kết nối cũ có thể được dùng lại với proxy cũ.

C++ CPR proxy sau proxy kiểm tra TLS

Lỗi chứng chỉ chỉ xuất hiện ở công ty

Ở công ty có thiết bị giải mã HTTPS, chứng chỉ website mà libcurl nhận được do CA nội bộ ký. Nếu bó chứng chỉ mà libcurl dùng không có CA đó, request báo lỗi chứng chỉ. Trong CPR, lỗi hiện qua error với mã thuộc nhóm SSL và message mô tả chứng chỉ không tin cậy.

Đổi proxy hay đổi tài khoản không sửa được lỗi này, vì đường đi vẫn đúng. Chỗ cần sửa là lòng tin chứng chỉ. Ở máy nhà, cùng chương trình chạy bình thường, đó là dấu hiệu điển hình.

SslOptions và CaInfo

CPR có cpr::SslOptions với các thành phần như CaInfo để chỉ tệp bó chứng chỉ, tương ứng CURLOPT_CAINFO của libcurl. Đặt CaInfo trỏ tới tệp PEM gồm CA nội bộ của công ty. Với bản libcurl dựng trên Schannel ở Windows, kho chứng chỉ của hệ điều hành có thể đã có CA nội bộ, tùy cách CPR được dựng.

Đừng chữa bằng cách tắt VerifyPeer hay VerifyHost. Làm vậy mọi kết nối HTTPS của Session đều có thể bị chặn bắt mà không có cảnh báo. Với chương trình gửi khóa API hay dữ liệu khách hàng, đây là rủi ro không đáng.

Proxy HTTPS khác proxy HTTP

Khi giá trị trong Proxies bắt đầu bằng https://, libcurl kết nối tới chính proxy bằng TLS. Khi đó cần thêm tùy chọn chứng chỉ cho proxy, trong libcurl là nhóm CURLOPT_PROXY_CAINFO. Mình chưa kiểm CPR có lớp tương ứng cho nhóm này ở bản 1.15.1. Đa số gói proxy thương mại dùng proxy HTTP thường, chỉ chọn https:// khi nhà cung cấp ghi rõ.

Đo hiệu năng C++ CPR proxy

elapsed trong Response

cpr::Response có trường elapsed tính bằng giây cho cả request. Ghi elapsed cùng status_code và tên proxy vào log giúp so sánh proxy với nhau theo thời gian. Proxy có elapsed tăng dần trong ngày có thể đang quá tải vào giờ cao điểm.

Muốn chi tiết hơn từng chặng, có thể lấy handle libcurl bên dưới qua Session và gọi curl_easy_getinfo cho các mốc như thời gian kết nối, thời gian bắt tay TLS, thời gian nhận byte đầu. Ý nghĩa các mốc khi đi qua proxy giống phần đo thời gian trong bài PycURL: kết nối là tới proxy, bắt tay TLS gồm cả đường hầm tới website.

Kiểm IP ra

Trước tác vụ chính, gọi một dịch vụ trả IP công khai qua Session đã cấu hình, so với IP của máy chạy chương trình. Nếu trùng, dừng với mã lỗi. Ca này bắt được lỗi thiếu khóa https, quên SetProxies hay bẫy mật khẩu khiến chương trình rơi về đi thẳng qua biến môi trường.

session.SetUrl(cpr::Url{"https://api.ipify.org"});
cpr::Response ip = session.Get();
if (ip.error || ip.status_code != 200 || ip.text == server_ip) {
    std::cerr << "Proxy khong hoat dong, dung lai" << std::endl;
    return 2;
}

Ghi IP ra vào log khởi động để đối chiếu khi có sự cố. Với proxy xoay, chỉ cần IP ra khác IP máy chủ.

Chạy đối chứng C++ CPR proxy

Proxy cục bộ có nhật ký

Cách chắc nhất để kiểm chương trình CPR là cho nó đi qua proxy ghi nhật ký. Dùng mitmproxy ở chế độ thường, Squid hoặc một proxy nhỏ tự viết. Proxy cần ghi phương thức, host đích và tài khoản nhận được.

Bộ ca kiểm tối thiểu

  • Chỉ khóa http, gọi URL https: nhật ký không có dòng, request đi thẳng.
  • Đủ khóa http và https: nhật ký có dòng cho cả hai loại URL.
  • ProxyAuthentication với mật khẩu chữ số: đạt.
  • ProxyAuthentication với mật khẩu có @ hoặc #: kiểm proxy có nhận đúng mật khẩu không.
  • Tài khoản trong URL proxy đã mã hóa: đạt.
  • no_proxy chứa host đích: nhật ký không có dòng.
  • Proxy chết: COULDNT_CONNECT trong khoảng ConnectTimeout.
  • Kiểm IP ra: gọi dịch vụ trả IP, so với IP proxy mong đợi.

Ca thứ tư là ca quyết định cách đặt tài khoản cho cả dự án. Nếu proxy nhận sai mật khẩu, chuyển sang tài khoản trong URL proxy.

Ghi kết quả

Ghi bản CPR, bản libcurl liên kết, hệ điều hành và kết quả từng ca. Mỗi lần nâng CPR, chạy lại ca thứ tư. Cách xử lý tài khoản có thể đổi giữa các bản.

Đưa C++ CPR proxy vào dự án thật

Một hàm dựng Session

Gom cấu hình mạng vào một hàm trả Session đã đặt Proxies, tài khoản, timeout và tiêu đề chung. Mã nghiệp vụ nhận Session từ hàm này, không tự dựng Proxies. Thay đổi proxy chỉ sửa một chỗ.

Không in Proxies hay URL proxy có tài khoản ra log. Khi ghi log, chỉ ghi tên máy proxy, host đích, status_code, error.code và thời gian. Bật Verbose của libcurl chỉ khi gỡ lỗi, vì nó có thể in tiêu đề Proxy-Authorization dạng base64.

Ghi rõ bẫy trong tài liệu nội bộ

Vì bẫy mật khẩu chỉ lộ ra với mật khẩu có ký tự đặc biệt, rất dễ quên sau vài tháng. Ghi một dòng vào README của dự án: không dùng ProxyAuthentication với mật khẩu có ký tự đặc biệt, đưa tài khoản vào URL proxy đã mã hóa. Kèm đường dẫn tới ca kiểm thứ tư trong bộ ca ở trên.

Khi nhà cung cấp proxy đổi mật khẩu định kỳ, mật khẩu mới có thể có ký tự đặc biệt dù mật khẩu cũ thì không. Đó là lúc chương trình đang chạy ổn bỗng báo 407 hàng loạt. Có dòng ghi chú này, người trực sự cố tìm ra nguyên nhân trong vài phút thay vì vài giờ.

Nếu nhóm muốn sửa tận gốc, có thể mở issue hoặc đóng góp cho CPR sau khi tự kiểm bằng một chương trình CPR thật. Trước khi làm vậy, chạy lại ca kiểm trên bản CPR mới nhất, vì mã có thể đã thay đổi sau ngày bài này được viết.

Chọn loại proxy

CPR hay dùng trong ứng dụng C++ cần gọi API hay tải dữ liệu: công cụ desktop, dịch vụ hiệu năng cao, phần mềm nhúng có mạng. Với API cần IP cố định, proxy tĩnh phù hợp. Với tải dữ liệu nhiều trang, proxy xoay chia tải. Proxy xác thực theo IP giúp tránh bẫy mật khẩu ở trên.

ProxyVN có proxy dân cư tĩnh, datacenter và proxy xoay, hỗ trợ HTTP và SOCKS5, cấp tài khoản user và mật khẩu. Nếu cần proxy cho Session CPR, anh em có thể mua proxy giá rẻ tại trang chủ ProxyVN rồi chạy bộ ca kiểm, nhất là ca mật khẩu có ký tự đặc biệt.

Câu hỏi thường gặp về C++ CPR proxy

Vì sao request https không qua proxy. Proxies chọn theo giao thức URL đích. Thiếu khóa https thì CPR không đặt proxy cho request https.

Giá trị của khóa https có phải bắt đầu bằng https:// không. Không bắt buộc. Thường là http:// vì kết nối tới proxy HTTP. libcurl tự mở CONNECT tới website https.

ProxyAuthentication có cần mã hóa mật khẩu không. EncodedAuthentication tự mã hóa. Theo mã đã đọc, chuỗi mã hóa đi thẳng vào tùy chọn libcurl không giải mã, nên mật khẩu có ký tự đặc biệt có thể bị proxy từ chối.

r.url có cho biết request qua proxy không. Không. Tài liệu ghi r.url in địa chỉ website.

Số ErrorCode có giống CURLcode không. Không. Một số mã trùng, nhiều mã khác. So bằng tên hằng.

Có dùng được SOCKS5 không. Có, đặt socks5h:// trong giá trị Proxies.

Có nên dùng biến môi trường thay cho Proxies không. Với công cụ dòng lệnh chạy trên máy người dùng, đọc biến môi trường là thân thiện vì người dùng đã quen. Với dịch vụ chạy trên máy chủ, đặt Proxies tường minh từ cấu hình của ứng dụng để hành vi không phụ thuộc máy.

Đổi proxy cho Session đang chạy được không. Gọi SetProxies với giá trị mới là được về mặt API. Nhưng kết nối cũ trong handle libcurl có thể được dùng lại. Khi cần IP mới, tạo Session mới cho chắc.

Mật khẩu proxy có dấu cách thì sao. Dấu cách cũng bị urlEncode thành %20 trong EncodedAuthentication, rơi vào cùng bẫy. Dùng tài khoản trong URL proxy với dấu cách mã hóa thành %20, libcurl sẽ giải mã đúng.

Checklist C++ CPR proxy

Checklist C++ CPR proxy

Checklist C++ CPR proxy

Trước khi triển khai

  • Khóa http và https đều có trong Proxies.
  • Kiểm ProxyAuthentication với mật khẩu thật, hoặc dùng tài khoản trong URL proxy đã mã hóa.
  • Đặt no_proxy để không phụ thuộc môi trường.
  • Dùng socks5h cho SOCKS5.
  • Đặt Timeout và ConnectTimeout.
  • So lỗi bằng tên cpr::ErrorCode.
  • Kiểm status_code 407 khi không có error.
  • In bản libcurl khi khởi động.

Giới hạn của bài

Mã CPR chưa được biên dịch và chạy trên máy lab vì không có trình biên dịch C++. Bẫy mật khẩu được suy ra từ mã nguồn nhánh master và mô phỏng lời gọi libcurl qua PycURL 7.49.0, libcurl 8.23.0. Chưa thử Async, MultiPerform, proxy HTTPS và gateway thương mại.

C++ CPR proxy và những điều cần nhớ

C++ CPR proxy chọn proxy theo giao thức URL đích, nên phải có đủ khóa http và https. Kiểm kỹ ProxyAuthentication với mật khẩu có ký tự đặc biệt, so lỗi bằng tên ErrorCode, đặt timeout và no_proxy. Cần proxy ổn định cho C++ CPR proxy, liên hệ Proxy.vn - Nhà cung cấp dịch vụ proxy chất lượng hàng đầu Việt Nam.

TIN TỨC LIÊN QUAN