Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_network_mock.c

Mock HTTP server example using Nilorea network module.

Mock HTTP server example using Nilorea network module

Author
Castagnier Mickael
Version
1.0
Date
26/03/2026
/*
* Nilorea Library
* Copyright (C) 2005-2026 Castagnier Mickael
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "nilorea/n_str.h"
#include "nilorea/n_log.h"
#include <getopt.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#define MOCK_PORT 19090
static N_MOCK_SERVER* g_server = NULL;
static void on_request(N_HTTP_REQUEST* req, N_HTTP_RESPONSE* resp, void* user_data) {
(void)user_data;
n_log(LOG_INFO, "mock: %s %s", req->method, req->path);
if (strcmp(req->method, "GET") == 0 &&
strcmp(req->path, "/api/test") == 0) {
resp->status_code = 200;
strncpy(resp->content_type, "application/json",
sizeof(resp->content_type) - 1);
resp->body = char_to_nstr("{\"status\":\"ok\"}");
} else {
resp->status_code = 404;
strncpy(resp->content_type, "text/plain",
sizeof(resp->content_type) - 1);
resp->body = char_to_nstr("Not Found");
}
}
static void* server_thread(void* arg) {
(void)arg;
return NULL;
}
int main(int argc, char* argv[]) {
int getoptret = 0;
while ((getoptret = getopt(argc, argv, "V:h")) != -1) {
switch (getoptret) {
case 'V':
if (strcmp(optarg, "LOG_DEBUG") == 0)
else if (strcmp(optarg, "LOG_INFO") == 0)
else if (strcmp(optarg, "LOG_NOTICE") == 0)
else if (strcmp(optarg, "LOG_ERR") == 0)
break;
case 'h':
default:
fprintf(stderr, "Usage: %s [-V LOG_LEVEL]\n", argv[0]);
return 1;
}
}
/* Start mock server */
if (!g_server) {
fprintf(stderr, "FAIL: could not start mock server\n");
return 1;
}
printf("CHECK start server ... PASS\n");
/* Run server in a thread */
pthread_t thr;
if (pthread_create(&thr, NULL, server_thread, NULL) != 0) {
fprintf(stderr, "FAIL: could not create server thread\n");
return 1;
}
/* Give the server thread time to start accepting */
usleep(100000); /* 100ms */
/* Connect and send a GET /api/test request */
int sock_fd = -1;
{
struct addrinfo hints;
struct addrinfo* res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
char port_str[16];
snprintf(port_str, sizeof(port_str), "%d", MOCK_PORT);
if (getaddrinfo("127.0.0.1", port_str, &hints, &res) != 0 || !res) {
fprintf(stderr, "FAIL: getaddrinfo\n");
pthread_join(thr, NULL);
return 1;
}
sock_fd = (int)socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (sock_fd < 0 ||
connect(sock_fd, res->ai_addr, res->ai_addrlen) != 0) {
fprintf(stderr, "FAIL: connect\n");
freeaddrinfo(res);
pthread_join(thr, NULL);
return 1;
}
freeaddrinfo(res);
}
/* Send HTTP request */
const char* http_req =
"GET /api/test HTTP/1.1\r\n"
"Host: localhost\r\n"
"Connection: close\r\n"
"\r\n";
ssize_t sent = send(sock_fd, http_req, strlen(http_req), 0);
if (sent <= 0) {
fprintf(stderr, "FAIL: send\n");
close(sock_fd);
pthread_join(thr, NULL);
return 1;
}
/* Read response */
char resp_buf[4096];
memset(resp_buf, 0, sizeof(resp_buf));
ssize_t total = 0;
ssize_t nr = 0;
while ((nr = recv(sock_fd, resp_buf + total,
sizeof(resp_buf) - 1 - (size_t)total, 0)) > 0) {
total += nr;
}
close(sock_fd);
printf("Response:\n%s\n", resp_buf);
/* Verify response contains expected data */
int pass = 1;
if (strstr(resp_buf, "200") == NULL) {
fprintf(stderr, "FAIL: expected 200 in response\n");
pass = 0;
}
if (strstr(resp_buf, "{\"status\":\"ok\"}") == NULL) {
fprintf(stderr, "FAIL: expected JSON body in response\n");
pass = 0;
}
printf("CHECK GET /api/test ... %s\n", pass ? "PASS" : "FAIL");
/* Stop server and clean up */
pthread_join(thr, NULL);
printf("CHECK cleanup ... PASS\n");
return pass ? 0 : 1;
}
int main(void)
int getoptret
Definition ex_fluid.c:60
int log_level
Definition ex_fluid.c:61
static char * port_str
static void * server_thread(void *arg)
Thread function that runs the server accept loop.
#define MOCK_PORT
mock server port
static void on_request(N_HTTP_REQUEST *req, N_HTTP_RESPONSE *resp, void *user_data)
Request handler: returns JSON for GET /api/test, 404 otherwise.
static N_MOCK_SERVER * g_server
global server pointer for thread
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:120
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:79
#define LOG_INFO
informational
Definition n_log.h:81
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:254
N_STR * body
response body
Definition n_network.h:757
char path[2048]
request path
Definition n_network.h:747
char method[16]
HTTP method.
Definition n_network.h:746
int status_code
HTTP status code.
Definition n_network.h:755
char content_type[128]
Content-Type header value.
Definition n_network.h:756
void n_mock_server_free(N_MOCK_SERVER **server)
Free a mock server and close the listening socket.
Definition n_network.c:5570
void n_mock_server_stop(N_MOCK_SERVER *server)
Signal the mock server to stop accepting connections.
Definition n_network.c:5561
void n_mock_server_run(N_MOCK_SERVER *server)
Run the mock server accept loop.
Definition n_network.c:5476
N_MOCK_SERVER * n_mock_server_start(int port, void(*on_request)(N_HTTP_REQUEST *, N_HTTP_RESPONSE *, void *), void *user_data)
Start a mock HTTP server: set up listener and return immediately.
Definition n_network.c:5442
parsed HTTP request for mock server callback
Definition n_network.h:745
HTTP response to send from mock server callback.
Definition n_network.h:754
mock HTTP server handle
Definition n_network.h:761
Common headers and low-level functions & define.
Generic log system.
Network Engine.
N_STR and string function declaration.