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
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
#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 */
SOCKET sock_fd = INVALID_SOCKET;
{
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 = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (sock_fd == INVALID_SOCKET ||
connect(sock_fd, res->ai_addr, (socklen_t)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, NETW_BUFLEN_CAST(strlen(http_req)), 0);
if (sent <= 0) {
fprintf(stderr, "FAIL: send\n");
closesocket(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,
NETW_BUFLEN_CAST(sizeof(resp_buf) - 1 - (size_t)total), 0)) > 0) {
total += nr;
}
closesocket(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:59
int log_level
Definition ex_fluid.c:60
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:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:121
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:80
#define LOG_INFO
informational
Definition n_log.h:82
N_STR * char_to_nstr(const char *src)
Convert a char into a N_STR, short version.
Definition n_str.c:255
N_STR * body
response body
Definition n_network.h:1049
char path[2048]
request path
Definition n_network.h:1039
char method[16]
HTTP method.
Definition n_network.h:1038
int status_code
HTTP status code.
Definition n_network.h:1047
char content_type[128]
Content-Type header value.
Definition n_network.h:1048
void n_mock_server_free(N_MOCK_SERVER **server)
Free a mock server and close the listening socket.
Definition n_network.c:7224
void n_mock_server_stop(N_MOCK_SERVER *server)
Signal the mock server to stop accepting connections.
Definition n_network.c:7215
int SOCKET
default socket declaration
Definition n_network.h:102
void n_mock_server_run(N_MOCK_SERVER *server)
Run the mock server accept loop.
Definition n_network.c:7130
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:7096
parsed HTTP request for mock server callback
Definition n_network.h:1037
HTTP response to send from mock server callback.
Definition n_network.h:1046
mock HTTP server handle
Definition n_network.h:1053
Common headers and low-level functions & define.
Generic log system.
Network Engine.
N_STR and string function declaration.