ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
ascii_query::HttpServer Class Reference

Simple single-threaded HTTP server. More...

#include <src/tooling/query/http_server.h>

Public Member Functions

 HttpServer ()
 
 ~HttpServer ()
 
 HttpServer (const HttpServer &)=delete
 
HttpServeroperator= (const HttpServer &)=delete
 
void addRoute (const std::string &method, const std::string &path, RouteHandler handler)
 Add a route handler.
 
void setDefaultHandler (RouteHandler handler)
 Set a default handler for unmatched routes.
 
bool start (uint16_t port)
 Start the server.
 
void stop ()
 Stop the server.
 
bool isRunning () const
 Check if server is running.
 
uint16_t port () const
 Get the port the server is listening on.
 
const std::string & lastError () const
 Get the last error message.
 
bool processOneRequest ()
 Process one request (blocking)
 

Detailed Description

Simple single-threaded HTTP server.

Definition at line 162 of file http_server.h.

Constructor & Destructor Documentation

◆ HttpServer() [1/2]

ascii_query::HttpServer::HttpServer ( )

Definition at line 111 of file http_server.cpp.

111 {
112#if defined(_WIN32)
113 // Initialize Winsock
114 WSADATA wsa_data;
115 WSAStartup(MAKEWORD(2, 2), &wsa_data);
116#endif
117
118 // Default 404 handler
119 default_handler_ = [](const HttpRequest &) { return HttpResponse::notFound(); };
120}
static HttpResponse notFound(const std::string &message="Not Found")

References ascii_query::HttpResponse::notFound().

◆ ~HttpServer()

ascii_query::HttpServer::~HttpServer ( )

Definition at line 122 of file http_server.cpp.

122 {
123 stop();
124
125#if defined(_WIN32)
126 WSACleanup();
127#endif
128}
void stop()
Stop the server.

References stop().

◆ HttpServer() [2/2]

ascii_query::HttpServer::HttpServer ( const HttpServer )
delete

Member Function Documentation

◆ addRoute()

void ascii_query::HttpServer::addRoute ( const std::string &  method,
const std::string &  path,
RouteHandler  handler 
)

Add a route handler.

Parameters
methodHTTP method (GET, POST, etc.)
pathURL path (exact match)
handlerHandler function

Definition at line 130 of file http_server.cpp.

130 {
131 routes_.push_back({method, path, std::move(handler)});
132}

◆ isRunning()

bool ascii_query::HttpServer::isRunning ( ) const
inline

Check if server is running.

Definition at line 200 of file http_server.h.

200 {
201 return running_;
202 }

◆ lastError()

const std::string & ascii_query::HttpServer::lastError ( ) const
inline

Get the last error message.

Definition at line 214 of file http_server.h.

214 {
215 return last_error_;
216 }

Referenced by main().

◆ operator=()

HttpServer & ascii_query::HttpServer::operator= ( const HttpServer )
delete

◆ port()

uint16_t ascii_query::HttpServer::port ( ) const
inline

Get the port the server is listening on.

Definition at line 207 of file http_server.h.

207 {
208 return port_;
209 }

Referenced by start().

◆ processOneRequest()

bool ascii_query::HttpServer::processOneRequest ( )

Process one request (blocking)

Used for testing or manual control. Normally you'd call start() instead.

Returns
true if a request was processed, false on error

Definition at line 230 of file http_server.cpp.

230 {
231 if (server_socket_ < 0) {
232 return false;
233 }
234
235 struct sockaddr_in client_addr {};
236 socklen_t client_len = sizeof(client_addr);
237
238 socket_t client_socket = accept(server_socket_, reinterpret_cast<struct sockaddr *>(&client_addr), &client_len);
239
240 if (client_socket == INVALID_SOCKET_VAL) {
241 return false;
242 }
243
244 handleClient(static_cast<int>(client_socket));
245 return true;
246}
int socket_t
Socket handle type (POSIX: int)
Definition socket.h:50
#define INVALID_SOCKET_VAL

References INVALID_SOCKET_VAL.

◆ setDefaultHandler()

void ascii_query::HttpServer::setDefaultHandler ( RouteHandler  handler)

Set a default handler for unmatched routes.

Parameters
handlerHandler function

Definition at line 134 of file http_server.cpp.

134{ default_handler_ = std::move(handler); }

◆ start()

bool ascii_query::HttpServer::start ( uint16_t  port)

Start the server.

Parameters
portPort to listen on
Returns
true if server started successfully

Definition at line 136 of file http_server.cpp.

136 {
137 if (running_) {
138 last_error_ = "Server already running";
139 return false;
140 }
141
142 // Create socket
143 server_socket_ = static_cast<int>(socket(AF_INET, SOCK_STREAM, 0));
144 if (server_socket_ == INVALID_SOCKET_VAL) {
145 last_error_ = "Failed to create socket";
146 return false;
147 }
148
149 // Set SO_REUSEADDR
150 int opt = 1;
151#if defined(_WIN32)
152 setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&opt), sizeof(opt));
153#else
154 setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
155#endif
156
157 // Bind
158 struct sockaddr_in addr {};
159 addr.sin_family = AF_INET;
160 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // localhost only for security
161 addr.sin_port = htons(port);
162
163 if (bind(server_socket_, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)) < 0) {
164 last_error_ = "Failed to bind to port " + std::to_string(port);
165 close_socket(server_socket_);
166 server_socket_ = -1;
167 return false;
168 }
169
170 // Listen
171 if (listen(server_socket_, 10) < 0) {
172 last_error_ = "Failed to listen on socket";
173 close_socket(server_socket_);
174 server_socket_ = -1;
175 return false;
176 }
177
178 port_ = port;
179 running_ = true;
180
181 // Start server thread
182 server_thread_ = std::thread(&HttpServer::serverLoop, this);
183
184 return true;
185}
uint16_t port() const
Get the port the server is listening on.
#define close_socket

References close_socket, INVALID_SOCKET_VAL, and port().

Referenced by main().

◆ stop()

void ascii_query::HttpServer::stop ( )

Stop the server.

Definition at line 187 of file http_server.cpp.

187 {
188 if (!running_) {
189 return;
190 }
191
192 running_ = false;
193
194 // Close server socket to unblock accept()
195 if (server_socket_ >= 0) {
196#if defined(_WIN32)
197 shutdown(server_socket_, SD_BOTH);
198#else
199 shutdown(server_socket_, SHUT_RDWR);
200#endif
201 close_socket(server_socket_);
202 server_socket_ = -1;
203 }
204
205 // Wait for server thread
206 if (server_thread_.joinable()) {
207 server_thread_.join();
208 }
209}

References close_socket.

Referenced by main(), and ~HttpServer().


The documentation for this class was generated from the following files: