Skip to main content

Status Codes, Headers and JSON

Handlers configure the response through http_res_t *res before returning the body. This example builds a tiny JSON API.

#include "kraken.h"

#define PORT 8000
#define BACKLOG 10

static int visits = 0;

// GET /api/visits
char *visits_handler(http_req_t *req, http_res_t *res)
{
res_content_type(res, "application/json");
res_header(res, "Cache-Control", "no-store");
res_header(res, "Access-Control-Allow-Origin", "*");

return res_sendf("{\"visits\": %d}\n", ++visits);
}

// GET /api/teapot
char *teapot_handler(http_req_t *req, http_res_t *res)
{
res_status(res, HTTP_STATUS_NOT_IMPLEMENTED);
res_content_type(res, "application/json");

return "{\"error\": \"no tea here\"}\n";
}

int main()
{
http_server_t *server = http_server_init(PORT, BACKLOG);

register_route(server, "/api/visits", visits_handler);
register_route(server, "/api/teapot", teapot_handler);

http_server_listen(server);
http_server_free(server);
}
$ curl -i localhost:8000/api/visits
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 14
Date: Mon, 06 Oct 2026 18:30:00 GMT
Connection: close
Server: Kraken
Cache-Control: no-store
Access-Control-Allow-Origin: *

{"visits": 1}

Status codes​

res_status sets the status code. Responses are 200 OK unless you change it. The http_status_t enum has names for the supported codes:

CodeName
100HTTP_STATUS_CONTINUE
200HTTP_STATUS_OK
201HTTP_STATUS_CREATED
202HTTP_STATUS_ACCEPTED
204HTTP_STATUS_NO_CONTENT
400HTTP_STATUS_BAD_REQUEST
401HTTP_STATUS_UNAUTHORIZED
403HTTP_STATUS_FORBIDDEN
404HTTP_STATUS_NOT_FOUND
405HTTP_STATUS_METHOD_NOT_ALLOWED
500HTTP_STATUS_INTERNAL_SERVER_ERROR
501HTTP_STATUS_NOT_IMPLEMENTED
502HTTP_STATUS_BAD_GATEWAY
503HTTP_STATUS_SERVICE_UNAVAILABLE
504HTTP_STATUS_GATEWAY_TIMEOUT

Setting a code that isn't in this list sends a 500 Internal Server Error and logs a message.

Content type​

res_content_type sets the Content-Type header. The default is text/html. Pass a string literal, Kraken keeps the pointer rather than copying it.

Headers​

res_header adds any other header. Both the name and the value are copied, so they can come from a local buffer. Setting the same header twice replaces the old value. Every response also gets Content-Length, Date, Connection: close and Server: Kraken.

Thread safety​

Handlers run on 20 worker threads at the same time. The visits counter above is fine for a demo, but two requests can update it at once. For anything that matters, use <stdatomic.h> (atomic_int visits) or a mutex.