Skip to content
Snippets Groups Projects
Commit 2b3cdd0a authored by Daniel Müller's avatar Daniel Müller :speech_balloon:
Browse files

Change project structure

- Moved header files to inc directory
- Moved example main.cpp to examples directory
- Changed the default build target to static lib
- Added CMake build system config
parent 9a072b13
No related branches found
No related tags found
No related merge requests found
cmake_minimum_required(VERSION 3.10)
project(cpphttpd)
file(GLOB SRC_FILES "src/*.cpp")
file(GLOB HEADER_FILES "inc/*.hpp")
include_directories(inc)
add_library(cpphttpd STATIC ${SRC_FILES} ${HEADER_FILES})
set_target_properties(cpphttpd PROPERTIES PREFIX "")
add_executable(example.run EXCLUDE_FROM_ALL example/main.cpp)
target_link_libraries(example.run cpphttpd)
target_link_libraries(example.run pthread)
add_custom_target(example example.run)
# Name of the executable # Name of the executable
NAME = prog.run NAME = cpphttpd.a
# Include directory
INC_DIR = inc
# Main source code directory # Main source code directory
SRC_DIR = src SRC_DIR = src
# Build output directory # Build output directory
...@@ -13,24 +15,27 @@ SRC = $(wildcard $(SRC_DIR)/*.cpp) ...@@ -13,24 +15,27 @@ SRC = $(wildcard $(SRC_DIR)/*.cpp)
OBJ = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC:.cpp=.o))) OBJ = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC:.cpp=.o)))
LD_FLAGS = -g -pthread LD_FLAGS = -g -pthread -I$(INC_DIR)
COMPILE_FLAGS = -g -c -O3 COMPILE_FLAGS = -g -c -O3 -I$(INC_DIR)
# Build rule for the main target executable # Build rule for the main target executable
$(TARGET): $(OBJ) $(TARGET): $(OBJ)
g++ $(LD_FLAGS) -o $@ $(OBJ) ar rcs $@ $(OBJ)
# Build rule for normal source files # Build rule for normal source files
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp
g++ $(COMPILE_FLAGS) -o $@ $< g++ $(COMPILE_FLAGS) -o $@ $<
example: $(TARGET)
g++ $(LD_FLAGS) -o build/example.run example/main.cpp $(TARGET)
.PHONY: clean .PHONY: clean
clean: clean:
rm $(OBJ) $(TARGET) rm $(OBJ) $(TARGET)
.PHONY: run .PHONY: run
run: $(TARGET) run: $(TARGET) example
./$(TARGET) ./build/example.run
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
#include <cstring> #include <cstring>
#include <sstream> #include <sstream>
#include <chrono> #include <chrono>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <unistd.h> #include <unistd.h>
#include "httpd.hpp" #include "httpd.hpp"
#include "http_service.hpp" #include "http_service.hpp"
HttpRouteHandling handle_echo_path(const HttpRequest &req, HttpResponse &res) HttpRouteHandling handle_echo_path(const HttpRequest &req, HttpResponse &res)
{ {
std::string echo_text = req.regexMatches().at(1); std::string echo_text = req.regexMatches().at(1);
std::string resp = "Echo: " + echo_text; std::string resp = "Echo: " + echo_text;
res.send((uint8_t*) resp.c_str(), resp.size()); res.send((uint8_t*) resp.c_str(), resp.size());
return HttpRouteHandling::End; return HttpRouteHandling::End;
} }
// Calculate the first N prime numbers where N is extracted from the request uri // Calculate the first N prime numbers where N is extracted from the request uri
HttpRouteHandling handle_prime(const HttpRequest &req, HttpResponse &res) HttpRouteHandling handle_prime(const HttpRequest &req, HttpResponse &res)
{ {
std::string result; std::string result;
int number_of_primes_found = 0; int number_of_primes_found = 0;
int max = std::stoi(req.regexMatches().at(1)); int max = std::stoi(req.regexMatches().at(1));
int num = 2; int num = 2;
while(number_of_primes_found < max) while(number_of_primes_found < max)
{ {
bool is_prime = true; bool is_prime = true;
for (int i = 2; i <= num/2; i++) for (int i = 2; i <= num/2; i++)
{ {
if (num % i == 0) if (num % i == 0)
{ {
is_prime = false; is_prime = false;
break; break;
} }
} }
if (is_prime) if (is_prime)
{ {
result += std::to_string(num) + " "; result += std::to_string(num) + " ";
number_of_primes_found++; number_of_primes_found++;
} }
num++; num++;
} }
res.send((uint8_t*) result.c_str(), result.size()); res.send((uint8_t*) result.c_str(), result.size());
return HttpRouteHandling::End; return HttpRouteHandling::End;
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
// Create the webserver on port 8081. By default listening on 0.0.0.0 // Create the webserver on port 8081. By default listening on 0.0.0.0
HttpServer srv(8081); HttpServer srv(8081);
// Log Middleware example // Log Middleware example
srv.addRoute(HttpRoute( srv.addRoute(HttpRoute(
"", "",
[](const HttpRequest &req, HttpResponse &res) { [](const HttpRequest &req, HttpResponse &res) {
std::string log = "Request: " + req.ip() + " => " + req.uri() + "\n"; std::string log = "Request: " + req.ip() + " => " + req.uri() + "\n";
log += " Agent: " + req.headers().getHeader(HttpHeader::UserAgent).getValue() + "\n"; log += " Agent: " + req.headers().getHeader(HttpHeader::UserAgent).getValue() + "\n";
std::cout << log; std::cout << log;
return HttpRouteHandling::Continue; return HttpRouteHandling::Continue;
}, },
HttpRoute::MatchType::MatchAny HttpRoute::MatchType::MatchAny
)); ));
// Example index route with hardcoded html response // Example index route with hardcoded html response
srv.addRoute(HttpRoute( srv.addRoute(HttpRoute(
"/(index.html)?", // match "/" or "/index.html" "/(index.html)?", // match "/" or "/index.html"
[](const HttpRequest &req, HttpResponse &res) { [](const HttpRequest &req, HttpResponse &res) {
char body[] = R"EOT( char body[] = R"EOT(
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<title>Example HTML Document</title> <title>Example HTML Document</title>
</head> </head>
<body> <body>
<h1><a href="/example.html">example.html</a></h1> <h1><a href="/example.html">example.html</a></h1>
<h1><a href="/cached/example.html">cached example.html</a></h1> <h1><a href="/cached/example.html">cached example.html</a></h1>
<h1><a href="/prime/100">first 100 primes</a></h1> <h1><a href="/prime/100">first 100 primes</a></h1>
<h1><a href="/echo/Hello">echo hello</a></h1> <h1><a href="/echo/Hello">echo hello</a></h1>
</body> </body>
</html> </html>
)EOT"; )EOT";
res.sendAll((uint8_t*)body, sizeof(body)); res.sendAll((uint8_t*)body, sizeof(body));
return HttpRouteHandling::End; return HttpRouteHandling::End;
} }
)); ));
// Static file example // Static file example
srv.addRoute(serveFile( srv.addRoute(serveFile(
"/example.html", "/example.html",
"./static/example.html", "./static/example.html",
"text/html; charset=utf-8" "text/html; charset=utf-8"
)); ));
// Cached static file example. The file is loaded into memory at launch // Cached static file example. The file is loaded into memory at launch
srv.addRoute(serveFileCached( srv.addRoute(serveFileCached(
"/cached/example.html", "/cached/example.html",
"./static/example.html", "./static/example.html",
"text/html; charset=utf-8" "text/html; charset=utf-8"
)); ));
// Example for a handler function that uses regex to extract a path segment // Example for a handler function that uses regex to extract a path segment
srv.addRoute(HttpRoute( srv.addRoute(HttpRoute(
"/prime/(\\d+)", "/prime/(\\d+)",
&handle_prime &handle_prime
)); ));
// Example for a handler function that uses regex to extract a path segment // Example for a handler function that uses regex to extract a path segment
srv.addRoute(HttpRoute( srv.addRoute(HttpRoute(
"/echo/([a-zA-Z0-9_\\-.]+)/?", "/echo/([a-zA-Z0-9_\\-.]+)/?",
&handle_echo_path &handle_echo_path
)); ));
try try
{ {
// Start serving the content // Start serving the content
srv.serveForever(); srv.serveForever();
} }
catch(const HttpException& e) catch(const HttpException& e)
{ {
std::cerr << e.what() << '\n'; std::cerr << e.what() << '\n';
} }
return 0; return 0;
} }
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment