1

I'm developing a local client-server application in C++. Client requires to Server a binary file to be sent, through a POST request. Based on the code available on this repository https://github.com/eidheim/Simple-Web-Server I've implemented my own test version:

#include "server_https.hpp"
#include "client_https.hpp"
#include <future>

// Added for the json-example
#define BOOST_SPIRIT_THREADSAFE
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>

// Added for the default_resource example
#include "crypto.hpp"
#include <algorithm>
#include <boost/filesystem.hpp>
#include <fstream>
#include <vector>

#include <sys/stat.h>

using namespace std;
// Added for the json-example:
using namespace boost::property_tree;

using HttpsServer = SimpleWeb::Server<SimpleWeb::HTTPS>;
using HttpsClient = SimpleWeb::Client<SimpleWeb::HTTPS>;
typedef unsigned char BYTE;

std::vector<BYTE> readFile(const char* filename){
    // open the file:
    std::streampos fileSize;
    std::ifstream file(filename, std::ios::binary);
    
    if ( !file )
        std::cout << std::strerror(errno) << '\n';

    // get its size:
    file.seekg(0, std::ios::end);
    fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    // read the data:
    std::vector<BYTE> fileData(fileSize);
    file.read((char*) &fileData[0], fileSize);
    return fileData;
}


int main() {

  HttpsServer server("/cert/CA/localhost/localhost.crt", "/cert/CA/localhost/localhost.key");
  server.config.port = 8080;

  server.resource["^/file$"]["POST"] = [](std::shared_ptr<HttpsServer::Response> response, std::shared_ptr<HttpsServer::Request> request) {
 
    auto binaryFile = readFile("../source/Directory.zip");         
    stringstream stream;
    stream << "HTTP/1.1 200 OK\r\n" << "Content-Length: " <<  binaryFile.size()*sizeof(BYTE) << "\r\n\r\n" << "Content: "; 
    stream.write( (char*) &binaryFile[0], sizeof(BYTE)*binaryFile.size() );
    response->write(stream);                
  };
  

  promise<unsigned short> server_port;
  thread server_thread([&server, &server_port]() {
    server.start([&server_port](unsigned short port) {
      server_port.set_value(port);
    });
  });
  
  cout << "Server listening on port " << server_port.get_future().get() << endl<< endl;

  {
    string json_string = "{\"zipFile\": \"SimpleZipFile\"}";
    HttpsClient client("localhost:8080", false);
    try {
    
    cout << "Example POST request to https://localhost:8080/file" << endl;
    auto r2 = client.request("POST", "/file", json_string);
    cout << "Post request correcly done" << endl << endl;
    std::string payload = r2->content.string();
    std::size_t found = payload.find("Content: ");
    payload.erase(0,found+9);


    std::ofstream destFile;
    destFile.open("../destination/Directory.zip", std::ios::out | std::ios::binary);
    if ( !destFile )
        std::cout << std::strerror(errno) << '\n';

    destFile.write( payload.c_str(), payload.size() );
    destFile.close();
    
    }
    catch(const SimpleWeb::system_error &e) {
      cerr << "Client request error: " << e.what() << endl;
    }    

  }
  

  server_thread.join();

}

Everything works fine, but actually I would like to change this code to allowing data transfer with Chunked transfer encoding. I understand theoretically how Chunked transfer encoding work, but It's not clear how implementing it. Server has to sent an unknown number of chunks to client, but when response->write(chunck) is invoked just the first chunck would be transmitted and server will end the post request handling. How can I send multiple chuncks?

0 Answers0