Skip to content

Instantly share code, notes, and snippets.

@artur-kink
Created August 19, 2014 03:17
Show Gist options
  • Save artur-kink/96fffe58ddb7e4b081f6 to your computer and use it in GitHub Desktop.
Save artur-kink/96fffe58ddb7e4b081f6 to your computer and use it in GitHub Desktop.
C++ Webserver using libmicrohttpd. A simple wrapper for libmicrohttpd to create websites using C++.
#ifndef _CONTROLLER_
#define _CONTROLLER_
#include <sstream>
/**
* Base controller for handling http requests.
*/
class Controller{
public:
/**
* Check if given path and method are handled by this controller.
*/
virtual bool validPath(const char* path, const char* method) = 0;
/**
* Handles given request.
*/
virtual int handleRequest(struct MHD_Connection* connection,
const char* url, const char* method, const char* upload_data,
size_t* upload_data_size) = 0;
};
/**
* The dynamic controller is a controller for creating user defined pages.
*/
class DynamicController:public Controller{
public:
virtual bool validPath(const char* path, const char* method) = 0;
/**
* User defined http response.
*/
virtual void createResponse(struct MHD_Connection* connection,
const char* url, const char* method, const char* upload_data,
size_t* upload_data_size, std::stringstream& response) = 0;
virtual int handleRequest(struct MHD_Connection* connection,
const char* url, const char* method, const char* upload_data,
size_t* upload_data_size){
std::stringstream response_string;
createResponse(connection, url, method, upload_data, upload_data_size, response_string);
//Send response.
struct MHD_Response * response = MHD_create_response_from_buffer(strlen(response_string.str().c_str()),
(void*)response_string.str().c_str(), MHD_RESPMEM_MUST_COPY);
int ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
MHD_destroy_response(response);
return ret;
}
};
#endif
#include "WebServer.hpp"
#include <time.h>
class MyController:public DynamicController{
public:
virtual bool validPath(const char* path, const char* method){
if(strcmp(path, "/") == 0 && strcmp("GET", method) == 0){
return true;
}
return false;
}
virtual void createResponse(struct MHD_Connection * connection,
const char * url, const char * method, const char * upload_data,
size_t * upload_data_size, std::stringstream& response){
time_t time_cur;
time(&time_cur);
struct tm* time_now = localtime(&time_cur);
response << "<html><head><title>Hello World from cpp</title></head><body>Hello World at "
<< time_now->tm_hour << ":" << time_now->tm_min << ":" << time_now->tm_sec << "!</body></html>";
}
};
int main(int argc, char** argv){
MyController myPage;
WebServer server(8080);
server.addController(&myPage);
server.start();
}
#include "WebServer.hpp"
#include "Controller.hpp"
int WebServer::request_handler(void* cls, struct MHD_Connection* connection,
const char* url, const char* method, const char* version,
const char* upload_data, size_t* upload_data_size, void** ptr) {
std::cout << "Request: " << url << ", Method: " << method << std::endl;
WebServer* server = (WebServer*)cls;
Controller* controller = 0;
for(int i = 0; i < server->controllers.size(); i++){
Controller* c = server->controllers.at(i);
if(c->validPath(url, method)){
controller = c;
break;
}
}
if(!controller){
std::cout << "Path not found.\n";
struct MHD_Response* response = MHD_create_response_from_buffer(0, 0, MHD_RESPMEM_PERSISTENT);
return MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
}
return controller->handleRequest(connection, url, method, upload_data, upload_data_size);
}
WebServer::WebServer(int p){
port = p;
daemon = 0;
}
void WebServer::addController(Controller* controller){
controllers.push_back(controller);
}
int WebServer::start(){
daemon = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION,
8080, NULL, NULL, &request_handler, this, MHD_OPTION_END);
if(!daemon)
return 1;
while(1){
sleep(10000);
}
MHD_stop_daemon(daemon);
return 0;
}
#ifndef _WEBSERVER_
#define _WEBSERVER_
#include <microhttpd.h>
#include <iostream>
#include <string.h>
#include <vector>
#include "Controller.hpp"
class WebServer{
private:
int port;
struct MHD_Daemon* daemon;
/** List of controllers this server has. */
std::vector<Controller*> controllers;
static int request_handler(void * cls, struct MHD_Connection * connection,
const char * url, const char * method, const char * version,
const char * upload_data, size_t * upload_data_size, void ** ptr);
public:
WebServer(int p);
void addController(Controller* controller);
int start();
};
#endif
@bhelm
Copy link

bhelm commented Jan 6, 2017

Very useful, Thanks!

@mat-ej
Copy link

mat-ej commented May 21, 2017

When I try to send a post request the upload_data comes empty. (upload_data_size = 0)
Could you please help me why is this happening? This is quite urgent request.

Thanks so much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment