Learning to write an HTTP web server. The server itself is there. I start a server, send an HTTP request curl -D dumpbin 127.0.0.1:2000 . On the server, I save the query in a string variable. Now (and I don’t know how to do it) I need to parse the entire received request, compile a response and send it back. I can handle the dispatch, but there are problems with parsing and compiling the answer. They said that libcurl should be used, but I don’t understand how they can parse the finished lines and whether it is possible. Help, please, with an example of such use of this, if it is possible. Advise which libraries can still be used to solve this problem.

 //Вид запроса (это то, что вернул мой эхо-сервер при использовании утилиты curl): request = "GET /index.html HTTP/1.1\r\n" "Host: 127.0.0.1:5991\r\n" "User-Agent: curl/7.47.0\r\n" "Accept: */*\r\n" "\r\n"; //Вид ответа (это я прочитал в комментах к заданию на степике): answer = "HTTP/1.0 200 OK\r\n" "Content-length: %d\r\n" "Connection: close\r\n" "Content-Type: text/html\r\n" "\r\n" "%s"; 

The bottom line is that there is data that is separated by \r\n and ends with a double carriage return and the string \r\n\r\n

  • Show an example of the HTTP header itself, or are these headers? As I remember, http headers are "text: test divided by 10 bytes". If they are, then they can be very simply parsed through while, for. - Denis Kotlyarov
  • Added a request type to the description. - Ligvest O
  • @LigvestO, what exactly is your problem? You do not know how to find in the string \r or \n ? Try reading man by strchr, strtok, strstr etc (although this is not C ++ at all). - PinkTux
  • There are no problems, but it would be much more effective not to invent a new bicycle, but to use the already debugged and formed library. As a result, I had to write a bicycle. - Ligvest O

2 answers 2

tl; dr; see end of response to implement header parser


As a rule, licurl used to write clients, see the FAQ :

5.17 Can I write a server with libcurl?

No. libcurl offers the internet protocol server. libcurl is only a client-side library. But there wasn’t even a need for a server. And there are really good stand-alone ones that have been tested and proven for many years. There is no need to reinvent them!

In free translation:

5.17 Can I use libcurl to write a server?

Not. libcurl does not offer functions or other building blocks to create any IP server. libcurl is only a client library. You need to continue your library searches to build a server. There are a large number of such open source libraries for most protocols. There is also a large number of applications tested over the years. You should not reinvent them.

Although to build the client, libcurl really handy thing, as @Pink Tux mentioned in its answer. Including the headlines you get already broken down one by one.


To build a server, as one of the options, you can use mongoose (on c , as a pair of .c/.h added to your project, or one of the many c++ wrappers). An example of a minimal server is quite cumbersome, so I will not give here. You can see here .


Another option is the cpp-netlib library which was originally planned as part of the boost (but then the developers' plans changed). In its simplest form, the http server looks like this:

 namespace http = boost::network::http; struct handler; typedef http::server<handler> http_server; struct handler { void operator() (http_server::request const &request, http_server::response &response) { response = http_server::response::stock_reply( http_server::response::ok, "Hello, world!"); } void log(http_server::string_type const &info) { std::cerr << "ERROR: " << info << '\n'; } }; int main(int arg, char * argv[]) { handler handler_; http_server::options options(handler_); http_server server_( options.address("0.0.0.0") .port("8000")); server_.run(); } 

If you need something more high-level (with template support, json, middlewares), you can take a crow that connects to your project with a single header file. In spirit, it resembles Python Flask . Sample server:

 #include "crow_all.h" int main() { crow::SimpleApp app; CROW_ROUTE(app, "/")([](){ return "Hello world"; }); app.port(18080).multithreaded().run(); } 

If it’s still interesting to parse the headers yourself, you can for example like this code:

 std::istringstream rawstream(raw); std::map<std::string, std::string> headers; std::string header; while (std::getline(rawstream, header) && header != "\r") { std::string::size_type index = header.find(':'); if (index != std::string::npos) { headers.insert(std::make_pair( boost::algorithm::trim_copy(header.substr(0, index)), boost::algorithm::trim_copy(header.substr(index + 1)) )); } } 

In raw type std::string place a string with your headers (or even an entire client request), in headers get a map from the names / values ​​of the headers. Use for example:

 std::cout << headers["Content-Type"] << std::endl; 

Please note that according to the standard, the name of the header can be any case. Therefore, CONTENT-TYPE , content-type and Content-Type are all one title, and for convenience, you can bring the title name into lowercase before adding to the map :

 headers.insert(std::make_pair( boost::algorithm::to_lower_copy(boost::algorithm::trim_copy(header.substr(0, index))), boost::algorithm::trim_copy(header.substr(index + 1)) )); 

The current example is on Ideone.com .


PS For testing, instead of curl you can use postman in which you can set headers, the body of the pages (including json), save sets of queries, etc.

  • I did not find a solution in all the libraries proposed (+ some found during the "investigation"), but used the proposed code. I made it for myself. Thanks for the help. - Ligvest O

libcurl provides the ability to specify a handler for different data. For example, to "catch" the response headers, you can use the following approach:

 static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) { /* * Эта функция будет вызываться на каждый возвращаемый заголовок. */ return nitems * size; } int main() { CURL *curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "http://yahoo.com/"); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback); curl_easy_perform(curl); } return 0; } 

See the libcurl documentation for details . In addition, for C ++ there are wrappers, for example, curlcpp .

  • Saw. I tried. How it works - I do not understand. I need to process the request on the server. And this, as I understand it, is the client function to process the response from the server already. - Ligvest O