2022-02-17 快速搭建c++的web服务器

目录

摘要:

依赖的库:

cpp-httplib: 

备份地址:

编写c++的web服务器:

http模块:

server模块:

router模块:

编译:

makefile:

build.sh

功能测试:


摘要:

说明如何快速搭建c++的web服务器, 便于后续使用c++编写web业务

总文件在: c++-web服务器,用来最小化研究用c++完成web服务器的功能-互联网文档类资源-CSDN下载

github:

GitHub - adofsauron/cpp-web-mini

依赖的库:

cpp-httplib: 

GitHub - yhirose/cpp-httplib: A C++ header-only HTTP/HTTPS server and client libraryhttps://github.com/yhirose/cpp-httplib/

备份地址:

cpp-httplib-0.10.2.tar.gz-互联网文档类资源-CSDN下载

编写c++的web服务器:

目录结构:

.
├── agent
├── build.sh
├── Makefile
├── src
│   ├── base
│   ├── config
│   ├── http
│   │   └── httplib.h
│   ├── proc
│   ├── router
│   │   ├── router.cc
│   │   ├── router.h
│   │   ├── router_test.cc
│   │   └── router_test.h
│   └── server
│       ├── run.cc
│       └── server.h
└── utest
    └── ut_testData.sh

8 directories, 11 files

http模块:

// 

server模块:

server.h

#include <chrono>
#include <cstdio>
#include "../http/httplib.h"

std::string dump_headers(const httplib::Headers &headers) {
    std::string s;
    char buf[BUFSIZ] = {0};

    for (auto it = headers.begin(); it != headers.end(); ++it) {
        const auto &x = *it;
        snprintf(buf, sizeof(buf), "%s: %s\n", x.first.c_str(), x.second.c_str());
        s += buf;
    }

    return s;
}

std::string log(const httplib::Request &req, const httplib::Response &res) {
    std::string s;
    char buf[BUFSIZ] = {0};

    s += "================================\n";

    snprintf(buf, sizeof(buf), "%s %s %s", req.method.c_str(),
            req.version.c_str(), req.path.c_str());
    s += buf;

    std::string query;
    for (auto it = req.params.begin(); it != req.params.end(); ++it) {
        const auto &x = *it;
        snprintf(buf, sizeof(buf), "%c%s=%s",
                    (it == req.params.begin()) ? '?' : '&', x.first.c_str(),
                    x.second.c_str());
        query += buf;
    }
    snprintf(buf, sizeof(buf), "%s\n", query.c_str());
    s += buf;

    s += dump_headers(req.headers);

    s += "--------------------------------\n";

    snprintf(buf, sizeof(buf), "%d %s\n", res.status, res.version.c_str());
    s += buf;
    s += dump_headers(res.headers);
    s += "\n";

    if (!res.body.empty()) { s += res.body; }

    s += "\n";

    return s;
}

run.cc



#include "server.h"
#include "../router/router.h"
#include "../router/router_test.h"

#define SERVER_CERT_FILE "./cert.pem"
#define SERVER_PRIVATE_KEY_FILE "./key.pem"

#define LISTERN_HOST "localhost"
#define LISTERN_PORT 8080

int main(void) {
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
    httplib::SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
#else
    httplib::Server svr;
#endif
  
    if (!svr.is_valid()) {
        printf("server has an error...\n");
        return -1;
    }

    svr.set_error_handler([](const httplib::Request & /*req*/, httplib::Response &res) {
        const char *fmt = "<p>Error Status: <span style='color:red;'>%d</span></p>";
        char buf[BUFSIZ] = {0};
        snprintf(buf, sizeof(buf), fmt, res.status);
        res.set_content(buf, "text/html");
    });

    svr.set_logger([](const httplib::Request &req, const httplib::Response &res) {
        printf("%s", log(req, res).c_str());
    });

    // router
    RunRouter(svr);

    // router test
    RunRouterTest(svr);

    svr.listen(LISTERN_HOST, LISTERN_PORT);

    return 0;
}

router模块:

router.h

#ifndef __ROUTER_H__
#define __ROUTER_H__

#include "../http/httplib.h"

void RunRouter(httplib::Server& svr);

#endif // __ROUTER_H__

router.cc

#include "router.h"

void RunRouter(httplib::Server& svr)
{
    svr.Post("/", [=](const httplib::Request & /*req*/, httplib::Response &res) {
        res.set_content("ok", "text/plain");
    });

    svr.Post("/ping", [](const httplib::Request & /*req*/, httplib::Response &res) {
        res.set_content("pong", "text/plain");
    });

    svr.Post("/slow", [](const httplib::Request & /*req*/, httplib::Response &res) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        res.set_content("Slow...\n", "text/plain");
    });
}

router_test.h

#ifndef __TEST_API_H__
#define __TEST_API_H__

#include "../http/httplib.h"

void RunRouterTest(httplib::Server& svr);

#endif /* __TEST_API_H__ */

router_test.cc

#include <iostream>
#include "router_test.h"

void RunRouterTest(httplib::Server& svr)
{
    // test data
    svr.Post("/testData", [](const httplib::Request& req, httplib::Response &res) {
        std::cout << "testData body: " << req.body << std::endl;

        {
            httplib::Client cli("localhost", 8080);
            if (auto res = cli.Post("/ping")) {
                std::cout << "res->status: " << res->status << std::endl;
                std::cout << "res->get_header: " << res->get_header_value("Content-Type") << std::endl;
                std::cout << "res->body: " << res->body << std::endl;
            } else {
                std::cout << "error code: " << res.error() << std::endl;
            }
        }

        res.set_content(req.body.c_str(), "text/plain");
    });
}

编译:

makefile:

#CXX = clang++
CXXFLAGS = -O2 -std=c++17 -I.. -Wall -Wextra -pthread

PREFIX = /usr/local
#PREFIX = $(shell brew --prefix)

OPENSSL_DIR = $(PREFIX)/opt/openssl@1.1
#OPENSSL_DIR = $(PREFIX)/opt/openssl@3
OPENSSL_SUPPORT = -DCPPHTTPLIB_OPENSSL_SUPPORT -I$(OPENSSL_DIR)/include -L$(OPENSSL_DIR)/lib -lssl -lcrypto

ZLIB_SUPPORT = -DCPPHTTPLIB_ZLIB_SUPPORT -lz

BROTLI_DIR = $(PREFIX)/opt/brotli
BROTLI_SUPPORT = -DCPPHTTPLIB_BROTLI_SUPPORT -I$(BROTLI_DIR)/include -L$(BROTLI_DIR)/lib -lbrotlicommon -lbrotlienc -lbrotlidec

SRC = src/server/run.cc \
		src/router/router.cc \
		src/router/router_test.cc

TARGET = agent

all: ${TARGET}

agent : ${SRC} Makefile
	$(CXX) -o ${TARGET} $(CXXFLAGS) ${SRC} $(ZLIB_SUPPORT) $(BROTLI_SUPPORT)

pem:
	openssl genrsa 2048 > key.pem
	openssl req -new -key key.pem | openssl x509 -days 3650 -req -signkey key.pem > cert.pem

clean:
	rm ${TARGET} -f

build.sh

#!/bin/bash

# yum install brotli-devel openssl-devel -y

make clean

make -j4


功能测试:

root@localhost:~/work/ndb-influxdb-instance/src/agent# ./build.sh 
rm agent -f
g++ -o agent -O2 -std=c++2a -I.. -Wall -Wextra -pthread src/server/run.cc src/router/router.cc src/router/router_test.cc -DCPPHTTPLIB_ZLIB_SUPPORT -lz -DCPPHTTPLIB_BROTLI_SUPPORT -I/usr/local/opt/brotli/include -L/usr/local/opt/brotli/lib -lbrotlicommon -lbrotlienc -lbrotlidec
root@localhost:~/work/ndb-influxdb-instance/src/agent# 
root@localhost:~/work/ndb-influxdb-instance/src/agent# 
root@localhost:~/work/ndb-influxdb-instance/src/agent# ./agent 
testData body: hello world
================================
POST HTTP/1.1 /ping
Accept: */*
Connection: close
Content-Length: 0
Host: localhost:8080
REMOTE_ADDR: ::1
REMOTE_PORT: 51950
User-Agent: cpp-httplib/0.10.1
--------------------------------
200 HTTP/1.1
Connection: close
Content-Length: 4
Content-Type: text/plain

pong
res->status: 200
res->get_header: text/plain
res->body: pong
================================
POST HTTP/1.1 /testData?hello world=
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded
Host: localhost:8080
REMOTE_ADDR: ::1
REMOTE_PORT: 51948
User-Agent: curl/7.78.0
--------------------------------
200 HTTP/1.1
Content-Length: 11
Content-Type: text/plain
Keep-Alive: timeout=5, max=5

hello world

root@localhost:~/work/ndb-influxdb-instance/src/agent/utest# ./ut_testData.sh 
curl -X POST --data hello world http://localhost:8080/testData
hello world

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟世者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值