ไลบรารี HTTP/HTTPS ข้ามแพลตฟอร์มแบบไฟล์เดียว C++11 ไฟล์เดียวเท่านั้น
มันง่ายมากที่จะติดตั้ง เพียงรวมไฟล์ httplib.h ไว้ในโค้ดของคุณ!
สำคัญ
ไลบรารีนี้ใช้ซ็อกเก็ต I/O 'การบล็อก' หากคุณกำลังมองหาไลบรารี่ที่มีซ็อกเก็ต I/O 'ไม่ปิดกั้น' นี่ไม่ใช่ไลบรารีที่คุณต้องการ
#กำหนด CPPHTTPLIB_OPENSSL_SUPPORT#include "path/to/httplib.h"// HTTPhttplib::Server svr;// HTTPShttplib::SSLServer svr;
svr.Get("/hi", [](const httplib::Request &, httplib::Response &res) {
res.set_content("สวัสดีชาวโลก!", "ข้อความ/ธรรมดา");
-
svr.listen("0.0.0.0", 8080); #define CPPHTTPLIB_OPENSSL_SUPPORT#include "path/to/httplib.h"// HTTPhttplib::Client cli("http://cpp-httplib-server.yhirose.repl.co");// HTTPShttplib::Client cli(" https://cpp-httplib-server.yhirose.repl.co");ความละเอียดอัตโนมัติ = cli.Get("/hi");
ความละเอียด -> สถานะ;
ความละเอียด -> ร่างกาย; การสนับสนุน SSL ใช้ได้กับ CPPHTTPLIB_OPENSSL_SUPPORT ควรเชื่อมโยง libssl และ libcrypto
บันทึก
ปัจจุบัน cpp-httplib รองรับเฉพาะเวอร์ชัน 3.0 ขึ้นไป โปรดดูหน้านี้เพื่อรับข้อมูลเพิ่มเติม
เคล็ดลับ
สำหรับ macOS: ขณะนี้ cpp-httplib สามารถใช้ใบรับรองระบบกับ CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN ได้ CoreFoundation และ Security ควรเชื่อมโยงกับ -framework
#define CPPHTTPLIB_OPENSSL_SUPPORT#include "path/to/httplib.h"// Serverhttplib::SSLServer svr("./cert.pem", "./key.pem");// Clienthttplib::Client cli("https: //localhost:1234"); // โครงการ + โฮสต์httplib::SSLClient cli("localhost:1234"); // hosthttplib::SSLClient cli("localhost", 1234); // โฮสต์ พอร์ต// ใช้ CA Bundlecli.set_ca_cert_path("./ca-bundle.crt");// ปิดการใช้งานการตรวจสอบใบรับรองcli.enable_server_certificate_verification(false);// ปิดการใช้งานการตรวจสอบโฮสต์cli.enable_server_host_verification(false);บันทึก
เมื่อใช้ SSL ดูเหมือนจะเป็นไปไม่ได้ที่จะหลีกเลี่ยง SIGPIPE ในทุกกรณี เนื่องจากในระบบปฏิบัติการบางระบบ SIGPIPE สามารถระงับได้เฉพาะต่อข้อความเท่านั้น แต่ไม่มีวิธีใดที่จะทำให้ไลบรารี OpenSSL ทำเช่นนั้นสำหรับการสื่อสารภายใน หากโปรแกรมของคุณต้องการหลีกเลี่ยงการยุติการทำงานบน SIGPIPE วิธีทั่วไปเพียงอย่างเดียวอาจเป็นการตั้งค่าตัวจัดการสัญญาณเพื่อให้ SIGPIPE จัดการหรือเพิกเฉยด้วยตัวคุณเอง
#include <httplib.h>int main(เป็นโมฆะ)
{ ใช้เนมสเปซ httplib;
เซิร์ฟเวอร์ svr;
svr.Get("/hi", [](const คำขอ& คำขอ, การตอบสนอง & ความละเอียด) {
res.set_content("สวัสดีชาวโลก!", "ข้อความ/ธรรมดา");
- // จับคู่เส้นทางคำขอกับนิพจน์ทั่วไป // และแยกการจับภาพ
svr.Get(R"(/numbers/(d+))", [&](const Request& req, Response& res) { ตัวเลขอัตโนมัติ = req.matches [1];
res.set_content(ตัวเลข, "ข้อความ/ธรรมดา");
- // จับส่วนที่สองของเส้นทางคำขอเป็นพารามิเตอร์เส้นทาง "id"
svr.Get("/users/:id", [&](const คำขอ & คำขอ, การตอบสนอง & res) { auto user_id = req.path_params.at ("id");
res.set_content(user_id, "ข้อความ/ธรรมดา");
- // แยกค่าจากส่วนหัว HTTP และพารามิเตอร์การสืบค้น URL
svr.Get("/body-header-param", [](const Request& req, Response& res) { if (req.has_header("Content-Length")) { auto val = req.get_header_value("Content-Length" );
} if (req.has_param("key")) { auto val = req.get_param_value("key");
-
res.set_content(req.body, "ข้อความ/ธรรมดา");
-
svr.Get("/stop", [&](const คำขอ& คำขอ, การตอบสนอง & res) {
svr.หยุด();
-
svr.listen("localhost", 1234);
- นอกจากนี้ยังรองรับวิธี Post , Put , Delete และ Options อีกด้วย
พอร์ต int = svr.bind_to_any_port("0.0.0.0");
svr.listen_after_bind(); // Mount / to ./www directoryauto ret = svr.set_mount_point("/", "./www");if (!ret) { // ไม่มีไดเร็กทอรีฐานที่ระบุ...}// Mount / สาธารณะไปที่ ./www directoryret = svr.set_mount_point("/public", "./www");// เมานต์ /public ไปที่ ./www1 และ ./www2 directoryret = svr.set_mount_point("/public", "./www1"); // ลำดับที่ 1 เพื่อ searchret = svr.set_mount_point("/public", "./www2"); // ลำดับที่ 2 เพื่อค้นหา// ลบ mount /ret = svr.remove_mount_point("/");// ลบ mount /publicret = svr.remove_mount_point("/public"); // นามสกุลไฟล์ที่ผู้ใช้กำหนดและประเภท MIME mappingssvr.set_file_extension_and_mimetype_mapping("cc", "text/xc");
svr.set_file_extension_and_mimetype_mapping("cpp", "ข้อความ/xc");
svr.set_file_extension_and_mimetype_mapping("hh", "ข้อความ/xh");ต่อไปนี้เป็นการแม็ปในตัว:
| ส่วนขยาย | ประเภทไมม์ | ส่วนขยาย | ประเภทไมม์ |
|---|---|---|---|
| ซีเอสเอส | ข้อความ/ซีเอส | เอ็มพีจีเอ | เสียง/mpeg |
| CSV | ข้อความ/CSV | เว็บบา | เสียง/เว็บเอ็ม |
| ข้อความ | ข้อความ/ธรรมดา | คลื่น | เสียง/คลื่น |
| vtt | ข้อความ/vtt | อื่น ๆ | แบบอักษร/otf |
| html,htm | ข้อความ/html | ทีทีเอฟ | แบบอักษร/ttf |
| apng | รูปภาพ/apng | ว้าว | แบบอักษร/woff |
| เอวิฟ | รูปภาพ/avif | woff2 | แบบอักษร/woff2 |
| บีเอ็มพี | รูปภาพ/bmp | 7z | แอปพลิเคชัน / x-7z-compressed |
| กิ๊ฟ | รูปภาพ/gif | อะตอม | แอปพลิเคชัน/อะตอม+xml |
| PNG | รูปภาพ/png | ใบสมัคร/pdf | |
| SVG | รูปภาพ/svg+xml | เอ็มเจเอส, เจเอส | แอปพลิเคชัน / จาวาสคริปต์ |
| เว็บพี | รูปภาพ/webp | json.json | แอปพลิเคชัน/json |
| ไอโอ | รูปภาพ/x-ไอคอน | RSS | แอปพลิเคชัน/rss+xml |
| ทิฟ | รูปภาพ/TIFF | ทาร์ | แอปพลิเคชั่น/x-tar |
| ทิฟ | รูปภาพ/TIFF | xhtml,xht | แอปพลิเคชัน/xhtml+xml |
| เจเพ็ก, jpg | รูปภาพ/jpeg | xslt | แอปพลิเคชัน/xslt+xml |
| mp4 | วิดีโอ/mp4 | xml | แอปพลิเคชัน/xml |
| เอ็มเพก | วิดีโอ/mpeg | กซ | แอปพลิเคชั่น/gzip |
| เว็บเอ็ม | วิดีโอ/เว็บเอ็ม | ซิป | แอปพลิเคชัน / zip |
| mp3 | เสียง/mp3 | เสีย | แอปพลิเคชัน/wasm |
คำเตือน
วิธีการเซิร์ฟเวอร์ไฟล์แบบคงที่เหล่านี้ไม่ปลอดภัยสำหรับเธรด
// ตัวจัดการถูกเรียกทันทีก่อนที่การตอบกลับจะถูกส่งไปยัง clientvr.set_file_request_handler([](const Request &req, Response &res) {
-
- svr.set_logger([](const auto& req, const auto& res) { your_logger (req, res);
- svr.set_error_handler([](const auto& req, auto& res) { auto fmt = "<p>สถานะข้อผิดพลาด: <span style='color:red;'>%d</span></p>"; char buf [BUFSIZ]; snprintf(buf, ขนาดของ(buf), fmt, res.status);
res.set_content(buf, "ข้อความ/html");
-ตัวจัดการข้อยกเว้นจะถูกเรียกถ้าตัวจัดการการกำหนดเส้นทางผู้ใช้ส่งข้อผิดพลาด
svr.set_Exception_handler([](const auto& req, auto& res, std::Exception_ptr ep) { auto fmt = "<h1>ข้อผิดพลาด 500</h1><p>%s</p>"; char buf[BUFSIZ] ; ลอง { std::rethrow_Exception(ep);
} catch (std::ข้อยกเว้น &e) { snprintf(buf, sizeof(buf), fmt, e.what());
} catch (...) { // ดูหมายเหตุต่อไปนี้ snprintf(buf, sizeof(buf), fmt, "Unknown Exception");
-
res.set_content(buf, "ข้อความ/html");
res.status = StatusCode::InternalServerError_500;
-คำเตือน
หากคุณไม่ได้ระบุบล็อก catch (...) สำหรับตัวชี้ข้อยกเว้นที่เขียนใหม่ ข้อยกเว้นที่ไม่ถูกตรวจจับจะทำให้เซิร์ฟเวอร์เสียหายในที่สุด ระวัง!
svr.set_pre_routing_handler ([] (const อัตโนมัติ& คำขอ, อัตโนมัติ & ความละเอียด) { ถ้า (req.path == "/ สวัสดี") {
res.set_content("โลก", "ข้อความ/html"); กลับเซิร์ฟเวอร์::HandlerResponse::จัดการ;
} ส่งคืนเซิร์ฟเวอร์::HandlerResponse::ไม่ได้จัดการ;
- svr.set_post_routing_handler ([] (const อัตโนมัติ & คำขอ, อัตโนมัติ & ความละเอียด) {
res.set_header("ADDITIONAL_HEADER", "value");
- svr.Post("/multipart", [&](const auto& req, auto& res) { auto size = req.files.size(); auto ret = req.has_file("name1"); const auto& file = req. get_file_value("name1"); // file.filename; // file.content_type; // file.content;}); svr.Post("/content_receiver",
[&](const Request &req, Response &res, const ContentReader &content_reader) { if (req.is_multipart_form_data()) { // หมายเหตุ: `content_reader` กำลังบล็อกจนกว่าจะอ่านทุกช่องข้อมูลแบบฟอร์ม
ไฟล์ MultipartFormDataItems; content_reader(
[&](const MultipartFormData &file) {
files.push_back(ไฟล์); กลับเป็นจริง;
-
[&](const char *data, size_t data_length) {
files.back().content.append(ข้อมูล, data_length); กลับเป็นจริง;
-
} อื่น {
std::ตัวสตริง; content_reader([&](const char *data, size_t data_length) {
body.append(ข้อมูล, data_length); กลับเป็นจริง;
-
-
- const size_t DATA_CHUNK_SIZE = 4;
svr.Get("/stream", [&](const Request &req, Response &res) { ข้อมูลอัตโนมัติ = new std::string("abcdefg");
res.set_content_provider(
ข้อมูล -> ขนาด (), // ความยาวของเนื้อหา "ข้อความ/ธรรมดา", // ประเภทเนื้อหา
[&, data](ออฟเซ็ต size_t, ความยาว size_t, DataSink &sink) { const auto &d = *data;
sink.write(&d[ออฟเซ็ต], std::min(ความยาว, DATA_CHUNK_SIZE)); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกกระบวนการ
-
[data](บูลสำเร็จ) { ลบข้อมูล; -
-ไม่มีความยาวของเนื้อหา:
svr.Get("/stream", [&](const คำขอ &req, การตอบสนอง &res) {
res.set_content_provider( "ข้อความ/ธรรมดา", // ประเภทเนื้อหา
[&](ออฟเซ็ต size_t, DataSink &sink) { ถ้า (/* ยังมีข้อมูลอยู่ */) {
std::vector<char> ข้อมูล; //เตรียมข้อมูล...
sink.write(data.data(), data.size());
} อื่น {
sink.done(); // ไม่มีข้อมูลอีกต่อไป
} คืนค่าจริง; // return 'false' หากคุณต้องการยกเลิกกระบวนการ
-
- svr.Get("/chunked", [&](const คำขอ& คำขอ, การตอบสนอง & res) {
res.set_chunked_content_provider( "ข้อความ/ธรรมดา",
[](ออฟเซ็ต size_t, DataSink & sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done(); // ไม่มีข้อมูลส่งคืนจริงอีกต่อไป; // return 'false' หากคุณต้องการยกเลิกกระบวนการ
-
-
-พร้อมตัวอย่าง:
svr.Get("/chunked", [&](const คำขอ& คำขอ, การตอบสนอง & res) {
res.set_header("ตัวอย่าง", "Dummy1, Dummy2");
res.set_chunked_content_provider( "ข้อความ/ธรรมดา",
[](ออฟเซ็ต size_t, DataSink & sink) {
sink.write("123", 3);
sink.write("345", 3);
sink.write("789", 3);
sink.done_with_trailer({
{"Dummy1", "DummyVal1"},
{"ดัมมี่2", "ดัมมี่วัล2"}
- กลับเป็นจริง;
-
-
- svr.Get("/content", [&](const คำขอ &req, การตอบสนอง &res) {
res.set_file_content("./path/to/conent.html");
-
svr.Get("/content", [&](const คำขอ &req, การตอบสนอง &res) {
res.set_file_content("./path/to/conent", "ข้อความ/html");
- ตามค่าเริ่มต้น เซิร์ฟเวอร์จะส่งการตอบสนอง 100 Continue สำหรับส่วนหัว Expect: 100-continue
// ส่ง '417 ความคาดหวังล้มเหลว' response.svr.set_expect_100_continue_handler([](const Request &req, Response &res) { return StatusCode::ExpectationFailed_417;
- // ส่งสถานะสุดท้ายโดยไม่ต้องอ่านข้อความ body.svr.set_expect_100_continue_handler([](const Request &req, Response &res) { return res.status = StatusCode::Unauthorized_401;
-svr.set_keep_alive_max_count(2); // ค่าเริ่มต้นคือ 5svr.set_keep_alive_timeout(10); // ค่าเริ่มต้นคือ 5
svr.set_read_timeout(5, 0); // 5 วินาทีsvr.set_write_timeout (5, 0); // 5 วินาทีsvr.set_idle_interval(0, 100000); // 100 มิลลิวินาที
svr.set_payload_max_length(1024 * 1024 * 512); // 512MB
บันทึก
เมื่อประเภทเนื้อหาคำขอเป็น 'www-form-urlencoded' ความยาวของเพย์โหลดจริงไม่ควรเกิน CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH
โปรดดูตัวอย่างเซิร์ฟเวอร์และตัวอย่างไคลเอนต์
ThreadPool ถูกใช้เป็นคิวงาน เริ่มต้น และจำนวนเธรดเริ่มต้นคือ 8 หรือ std::thread::hardware_concurrency() คุณสามารถเปลี่ยนได้ด้วย CPPHTTPLIB_THREAD_POOL_COUNT
หากคุณต้องการตั้งค่าจำนวนเธรด ณ รันไทม์ ไม่มีวิธีที่สะดวก... แต่นี่คือวิธีการ
svr.new_task_queue = [] { คืน ThreadPool ใหม่ (12); - คุณยังสามารถจัดเตรียมพารามิเตอร์ทางเลือกเพื่อจำกัดจำนวนคำขอที่ค้างอยู่ได้สูงสุด เช่น คำขอที่ผู้ฟัง accept() แต่ยังคงรอให้บริการโดยเธรดของผู้ปฏิบัติงาน
svr.new_task_queue = [] { คืน ThreadPool ใหม่ (/*num_threads=*/12, /*max_queued_requests=*/18); -ขีดจำกัดเริ่มต้นคือ 0 (ไม่จำกัด) เมื่อถึงขีดจำกัดแล้ว Listener จะปิดการเชื่อมต่อไคลเอ็นต์
คุณสามารถจัดหาการใช้งานเธรดพูลของคุณเองได้ตามความต้องการของคุณ
คลาส YourThreadPoolTaskQueue : TaskQueue สาธารณะ {สาธารณะ: YourThreadPoolTaskQueue (size_t n) {
pool_.start_with_thread_count(n);
} virtual bool enqueue(std::function<void()> fn) override { /* ส่งคืน true หากงานอยู่ในคิวจริง หรือ false * หากผู้เรียกต้องตัดการเชื่อมต่อที่เกี่ยวข้อง */ return pool_.enqueue(fn);
} การปิดระบบเป็นโมฆะเสมือน () แทนที่ {
pool_.shutdown_gracefully();
}ส่วนตัว:
YourThreadPool พูล_;
-
svr.new_task_queue = [] { ส่งคืน YourThreadPoolTaskQueue ใหม่ (12);
- #include <httplib.h>#include <iostream>int main(โมฆะ)
-
httplib::ไคลเอนต์ cli("localhost", 1234); if (res อัตโนมัติ = cli.Get ("/ hi")) { if (res->status == StatusCode::OK_200) {
std::cout << res->body << std::endl;
-
} else { ข้อผิดพลาดอัตโนมัติ = res.error();
std::cout << "ข้อผิดพลาด HTTP:" << httplib::to_string(err) << std::endl;
-
-เคล็ดลับ
ตัวสร้างที่มีสตริง Scheme-host-Port ได้รับการสนับสนุนแล้ว!
httplib::Client cli("localhost");
httplib::Client cli("localhost:8080");
httplib::Client cli("http://localhost");
httplib::ไคลเอนต์ cli("http://localhost:8080");
httplib::Client cli("https://localhost");
httplib::SSLClient cli("localhost"); นี่คือรายการข้อผิดพลาดจาก Result::error()
ข้อผิดพลาดแจงนับ {
สำเร็จ = 0,
ไม่ทราบ,
การเชื่อมต่อ,
BindIPAddress,
อ่าน,
เขียน,
เกินการเปลี่ยนเส้นทางนับ,
ยกเลิก,
การเชื่อมต่อ SSL,
SSLLoadingCerts,
การตรวจสอบเซิร์ฟเวอร์ SSL
ไม่รองรับ MultipartBoundaryChars,
การบีบอัด
การเชื่อมต่อหมดเวลา,
- httplib::ส่วนหัวส่วนหัว = {
{ "ยอมรับการเข้ารหัส", "gzip, deflate" }
};auto res = cli.Get("/hi", ส่วนหัว);หรือ
ความละเอียดอัตโนมัติ = cli.Get("/hi", {{"ยอมรับการเข้ารหัส", "gzip, deflate"}});หรือ
cli.set_default_headers({
{ "ยอมรับการเข้ารหัส", "gzip, deflate" }
});ความละเอียดอัตโนมัติ = cli.Get("/hi"); res = cli.Post("/post", "text", "text/plain");
res = cli.Post("/person", "name=john1¬e=coder", "application/x-www-form-urlencoded"); httplib::พารามิเตอร์พารามิเตอร์;
params.emplace("ชื่อ", "จอห์น");
params.emplace("note", "coder");auto res = cli.Post("/post", params);หรือ
httplib::พารามิเตอร์พารามิเตอร์{
{ "ชื่อ", "จอห์น" },
{ "หมายเหตุ", "ผู้เขียนโค้ด" }
};auto res = cli.Post("/post", params); httplib::รายการ MultipartFormDataItems = {
{ "text1", "ค่าเริ่มต้นของข้อความ", "", "" },
{ "text2", "aωb", "", "" },
{ "file1", "hnennlnlnon", "hello.txt", "ข้อความ/ธรรมดา" },
{ "file2", "{n "world", truen}n", "world.json", "application/json" },
{ "file3", "", "", "application/octet-stream" },
};auto res = cli.Post("/multipart", items); res = cli.Put("/resource/foo", "text", "text/plain"); res = cli.Delete("/resource/foo"); res = cli.Options("*");
res = cli.Options("/resource/foo");cli.set_connection_timeout(0, 300000); // 300 มิลลิวินาทีscli.set_read_timeout(5, 0); // 5 วินาทีcli.set_write_timeout(5, 0); // 5 วินาที
std::string body;auto res = cli.Get("/large-data",
[&](const char *data, size_t data_length) {
body.append(ข้อมูล, data_length); กลับเป็นจริง;
- std::string body;auto res = cli.Get( "/stream", Headers(),
[&](const การตอบสนอง &ตอบกลับ) { EXPECT_EQ(StatusCode::OK_200, response.status); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกคำขอ
-
[&](const char *data, size_t data_length) {
body.append(ข้อมูล, data_length); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกคำขอ
- std::string body = ...;res อัตโนมัติ = cli.Post( "/stream", body.size(),
[](ออฟเซ็ต size_t, ความยาว size_t, DataSink &sink) {
sink.write(body.data() + ออฟเซ็ต, ความยาว); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกคำขอ
}, "ข้อความ/ธรรมดา"); ความละเอียดอัตโนมัติ = cli.Post ( "/ สตรีม",
[](ออฟเซ็ต size_t, DataSink & sink) {
sink.os << "ข้อมูลเป็นกลุ่ม 1";
sink.os << "ข้อมูลเป็นกลุ่ม 2";
sink.os << "ข้อมูลเป็นกลุ่ม 3";
sink.done(); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกคำขอ
}, "ข้อความ/ธรรมดา"); httplib::ไคลเอนต์ cli (url, พอร์ต); // พิมพ์: 0/000 ไบต์ => 50% completeauto res = cli.Get ("/", [] (uint64_t len, uint64_t รวม) { printf ("%lld / %lld ไบต์ => %d%% เสร็จสมบูรณ์n",
เลน, ทั้งหมด,
(int)(len*100/ทั้งหมด)); กลับเป็นจริง; // return 'false' หากคุณต้องการยกเลิกคำขอ}
- 
// Authenticationcli.set_basic_auth พื้นฐาน ("ผู้ใช้", "ผ่าน"); // Digest Authenticationcli.set_digest_auth ("ผู้ใช้", "ผ่าน"); // Bearer Token Authenticationcli.set_bearer_token_auth ("token");บันทึก
จำเป็นต้องมี OpenSSL สำหรับการตรวจสอบสิทธิ์แบบแยกส่วน
cli.set_proxy("host", port);// Basic Authenticationcli.set_proxy_basic_auth("user", "pass");// Digest Authenticationcli.set_proxy_digest_auth("user", "pass");// Bearer Token Authenticationcli.set_proxy_bearer_token_auth ("ผ่าน");บันทึก
จำเป็นต้องมี OpenSSL สำหรับการตรวจสอบสิทธิ์แบบแยกส่วน
httplib::Client cli("httpbin.org");auto res = cli.Get("/range/32", { httplib::make_range_header({{1, 10}}) // 'Range: bytes=1- 10'});// res->สถานะควรเป็น 206.// res->body ควรเป็น "bcdefghijk" httplib::make_range_header({{1, 10}, {20, -1}}) // 'ช่วง: ไบต์=1-10, 20-'httplib::make_range_header({{100, 199}, {500, 599 }}) // 'ช่วง: ไบต์=100-199, 500-599'httplib::make_range_header({{0, 0}, {-1, 1}}) // 'ช่วง: ไบต์=0-0, -1' httplib::ไคลเอนต์ cli("localhost", 1234);
cli.Get("/สวัสดี"); // ด้วย "การเชื่อมต่อ: ปิด"cli.set_keep_alive(true);
cli.Get("/โลก");
cli.set_keep_alive(เท็จ);
cli.Get("/คำขอสุดท้าย"); // ด้วย "การเชื่อมต่อ: ปิด" httplib::Client cli("yahoo.com");auto res = cli.Get("/");
ความละเอียด -> สถานะ; // 301cli.set_follow_location(จริง);
res = cli.Get("/");
ความละเอียด -> สถานะ; // 200บันทึก
คุณลักษณะนี้ยังไม่พร้อมใช้งานบน Windows
cli.set_interface("eth0"); // ชื่ออินเทอร์เฟซ ที่อยู่ IP หรือชื่อโฮสต์เซิร์ฟเวอร์สามารถใช้การบีบอัดกับเนื้อหาประเภท MIME ต่อไปนี้:
ข้อความทุกประเภท ยกเว้น text/event-stream
รูปภาพ/svg+xml
แอปพลิเคชัน / จาวาสคริปต์
แอปพลิเคชัน/json
แอปพลิเคชัน/xml
แอปพลิเคชัน/xhtml+xml
การบีบอัด 'gzip' สามารถใช้ได้กับ CPPHTTPLIB_ZLIB_SUPPORT ควรเชื่อมโยง libz
การบีบอัด Brotli สามารถใช้ได้กับ CPPHTTPLIB_BROTLI_SUPPORT ควรมีการเชื่อมโยงไลบรารีที่จำเป็น โปรดดู https://github.com/google/brotli สำหรับรายละเอียดเพิ่มเติม
cli.set_compress(จริง);
res = cli.Post("/resource/foo", "...", "ข้อความ/ธรรมดา"); cli.set_decompress(เท็จ);
res = cli.Get("/resource/foo", {{"ยอมรับการเข้ารหัส", "gzip, deflate, br"}});
ความละเอียด -> ร่างกาย; // ข้อมูลที่ถูกบีบอัดpoll แทน select select system call ใช้เป็นค่าเริ่มต้นเนื่องจากได้รับการสนับสนุนอย่างกว้างขวางมากขึ้น หากคุณต้องการให้ cpp-httplib ใช้ poll แทน คุณสามารถทำได้ด้วย CPPHTTPLIB_USE_POLL
รองรับ Unix Domain Socket บน Linux และ macOS
// Serverhttplib::เซิร์ฟเวอร์ svr("./my-socket.sock");
svr.set_address_family(AF_UNIX).listen("./my-socket.sock", 80);// Clienthttplib::Client cli("./my-socket.sock");
cli.set_address_family(AF_UNIX);"my-socket.sock" อาจเป็นเส้นทางสัมพัทธ์หรือเส้นทางสัมบูรณ์ แอปพลิเคชันของคุณจะต้องมีสิทธิ์ที่เหมาะสมสำหรับเส้นทาง คุณยังสามารถใช้ที่อยู่ซ็อกเก็ตนามธรรมบน Linux ได้ หากต้องการใช้ที่อยู่ซ็อกเก็ตนามธรรม ให้เพิ่มไบต์ว่าง ('x00') ไว้ข้างหน้าเส้นทาง
$ ./split.py -husage: split.py [-h] [-e EXTENSION] [-o OUT]สคริปต์นี้แยก httplib.h ออกเป็น .h และ .cc parts.ข้อโต้แย้งทางเลือก: -h, --help show ข้อความช่วยเหลือนี้และ exit -e EXTENSION, --extension EXTENSION ส่วนขยายของไฟล์การใช้งาน (ค่าเริ่มต้น: cc) -o OUT, --out OUT ตำแหน่งที่จะเขียนไฟล์ (ค่าเริ่มต้น: out)$ ./split.pyเขียนออก/httplib.h และ out/httplib.cc
Dockerfile สำหรับเซิร์ฟเวอร์ HTTP แบบคงที่พร้อมใช้งาน หมายเลขพอร์ตของเซิร์ฟเวอร์ HTTP นี้คือ 80 และให้บริการไฟล์คงที่จากไดเร็กทอรี /html ในคอนเทนเนอร์
> นักเทียบท่า build -t cpp-httplib-server ....> นักเทียบท่า run --rm -it -p 8080:80 -v ./docker/html:/html cpp-httplib-server ให้บริการ HTTP บนพอร์ต 0.0.0.0 80 ... 192.168.65.1 - - [31/ส.ค./2567:21:33:56 +0000] "GET / HTTP/1.1" 200 599 "-" "curl/8.7.1"192.168.65.1 - - [31/ส.ค./2567 :21:34:26 +0000] "รับ / HTTP/1.1" 200 599 "-" "Mozilla/5.0 ..."192.168.65.1 - - [31/ส.ค./2024:21:34:26 +0000] "GET /favicon.ico HTTP/1.1" 404 152 " -" "โมซิลล่า/5.0 ... "
จากด็อคเกอร์ฮับ
> นักเทียบท่าทำงาน --rm -it -p 8080:80 -v ./docker/html:/html yhirose4dockerhub/cpp-httplib-server ...> นักเทียบท่าวิ่ง --init --rm -it -p 8080:80 -v ./docker/html:/html cpp-httplib-server ให้บริการ HTTP บนพอร์ต 0.0.0.0 80 ... 192.168.65.1 - - [31/ส.ค./2567:21:33:56 +0000] "GET / HTTP/1.1" 200 599 "-" "curl/8.7.1"192.168.65.1 - - [31/ส.ค./2567 :21:34:26 +0000] "รับ / HTTP/1.1" 200 599 "-" "Mozilla/5.0 ..."192.168.65.1 - - [31/ส.ค./2024:21:34:26 +0000] "GET /favicon.ico HTTP/1.1" 404 152 " -" "โมซิลล่า/5.0 ... "
g++ 4.8 และต่ำกว่าไม่สามารถสร้างไลบรารีนี้ได้เนื่องจาก <regex> ในเวอร์ชันใช้งานไม่ได้
รวม httplib.h ก่อน Windows.h หรือรวม Windows.h โดยกำหนด WIN32_LEAN_AND_MEAN ไว้ล่วงหน้า
#include <httplib.h>#include <Windows.h>
#กำหนด WIN32_LEAN_AND_MEAN#include <Windows.h>#include <httplib.h>
บันทึก
cpp-httplib รองรับเฉพาะ Visual Studio ล่าสุดอย่างเป็นทางการเท่านั้น อาจใช้งานได้กับ Visual Studio เวอร์ชันเก่า แต่ฉันไม่สามารถยืนยันได้อีกต่อไป คำขอดึงนั้นยินดีต้อนรับเสมอสำหรับ Visual Studio เวอร์ชันเก่า เว้นแต่ว่าจะฝ่าฝืนความสอดคล้องของ C ++ 11
บันทึก
Windows 8 หรือต่ำกว่า, Visual Studio 2013 หรือต่ำกว่า และ Cygwin และ MSYS2 รวมถึง MinGW ไม่รองรับหรือทดสอบ
ใบอนุญาต MIT (© 2024 Yuji Hirose)
คนเหล่านี้มีส่วนช่วยอย่างมากในการขัดเกลาห้องสมุดนี้ไปอีกระดับหนึ่งจากของเล่นธรรมดาๆ!