Query Parameters
The framework provides a typed API for extracting query parameters from the request URL.
API
String Parameter
c
#include "query.h"
const char* query_param_char(httprequest_t* request, const char* param_name, int* ok);Gets a parameter as a string.
Parametersrequest — pointer to HTTP request.param_name — parameter name.ok — pointer to success flag (1 — success, 0 — error).
Return Value
Pointer to the string value or NULL.
Integer Parameters
c
int query_param_int(httprequest_t* request, const char* param_name, int* ok);
unsigned int query_param_uint(httprequest_t* request, const char* param_name, int* ok);
long query_param_long(httprequest_t* request, const char* param_name, int* ok);
unsigned long query_param_ulong(httprequest_t* request, const char* param_name, int* ok);Return Value
Numeric value or 0 on error (check the ok flag).
Floating-Point Parameters
c
float query_param_float(httprequest_t* request, const char* param_name, int* ok);
double query_param_double(httprequest_t* request, const char* param_name, int* ok);
long double query_param_ldouble(httprequest_t* request, const char* param_name, int* ok);Return Value
Numeric value or 0.0 on error.
Array
c
json_doc_t* query_param_array(httprequest_t* request, const char* param_name, int* ok);Parses an array from the query string.
Supported formats:
?items[]=a&items[]=b&items[]=c?items=a,b,c
Return Value
JSON document with the array. Must be freed with json_free().
Object
c
json_doc_t* query_param_object(httprequest_t* request, const char* param_name, int* ok);Parses an object from the query string.
Format: ?filter[name]=John&filter[age]=25
Return Value
JSON document with the object. Must be freed with json_free().
Usage Examples
Basic Parameters
c
// URL: /search?query=hello&page=2&limit=10
void search(httpctx_t* ctx) {
int ok = 0;
// String parameter
const char* query = query_param_char(ctx->request, "query", &ok);
if (!ok || query == NULL) {
ctx->response->status_code = 400;
ctx->response->send_data(ctx->response, "Parameter 'query' is required");
return;
}
// Numeric parameters with default values
int page = query_param_int(ctx->request, "page", &ok);
if (!ok) page = 1;
int limit = query_param_int(ctx->request, "limit", &ok);
if (!ok) limit = 20;
char response[256];
snprintf(response, sizeof(response),
"Search: %s, Page: %d, Limit: %d",
query, page, limit
);
ctx->response->send_data(ctx->response, response);
}Floating-Point Parameters
c
// URL: /calculate?price=99.99&tax=0.2
void calculate(httpctx_t* ctx) {
int ok = 0;
double price = query_param_double(ctx->request, "price", &ok);
if (!ok) {
ctx->response->send_data(ctx->response, "Invalid price");
return;
}
double tax = query_param_double(ctx->request, "tax", &ok);
if (!ok) tax = 0.0;
double total = price * (1 + tax);
char response[64];
snprintf(response, sizeof(response), "Total: %.2f", total);
ctx->response->send_data(ctx->response, response);
}Working with Arrays
c
// URL: /filter?tags[]=php&tags[]=javascript&tags[]=python
// or: /filter?tags=php,javascript,python
void filter_by_tags(httpctx_t* ctx) {
int ok = 0;
json_doc_t* tags_doc = query_param_array(ctx->request, "tags", &ok);
if (!ok || tags_doc == NULL) {
ctx->response->send_data(ctx->response, "No tags provided");
return;
}
json_token_t* tags = json_root(tags_doc);
int count = json_array_size(tags);
str_t* result = str_create_empty(256);
str_append(result, "Tags: ", 6);
for (int i = 0; i < count; i++) {
json_token_t* tag = json_array_get(tags, i);
const char* tag_value = json_string(tag);
if (i > 0) str_append(result, ", ", 2);
str_append(result, tag_value, strlen(tag_value));
}
ctx->response->send_data(ctx->response, str_get(result));
str_free(result);
json_free(tags_doc);
}Working with Objects
c
// URL: /users?filter[status]=active&filter[role]=admin&filter[min_age]=18
void filter_users(httpctx_t* ctx) {
int ok = 0;
json_doc_t* filter_doc = query_param_object(ctx->request, "filter", &ok);
if (!ok || filter_doc == NULL) {
ctx->response->send_data(ctx->response, "No filter provided");
return;
}
json_token_t* filter = json_root(filter_doc);
// Extract values from object
json_token_t* status_token = json_object_get(filter, "status");
json_token_t* role_token = json_object_get(filter, "role");
json_token_t* min_age_token = json_object_get(filter, "min_age");
const char* status = status_token ? json_string(status_token) : "any";
const char* role = role_token ? json_string(role_token) : "any";
int min_age = min_age_token ? atoi(json_string(min_age_token)) : 0;
char response[256];
snprintf(response, sizeof(response),
"Filter: status=%s, role=%s, min_age=%d",
status, role, min_age
);
ctx->response->send_data(ctx->response, response);
json_free(filter_doc);
}Parameter Validation
c
void get_product(httpctx_t* ctx) {
int ok = 0;
// ID is required and must be positive
int id = query_param_int(ctx->request, "id", &ok);
if (!ok || id <= 0) {
ctx->response->status_code = 400;
ctx->response->send_data(ctx->response, "Valid product ID is required");
return;
}
// Get product...
char response[64];
snprintf(response, sizeof(response), "Product ID: %d", id);
ctx->response->send_data(ctx->response, response);
}Pagination
c
void list_items(httpctx_t* ctx) {
int ok = 0;
// Pagination parameters with default values
int page = query_param_int(ctx->request, "page", &ok);
if (!ok || page < 1) page = 1;
int per_page = query_param_int(ctx->request, "per_page", &ok);
if (!ok || per_page < 1 || per_page > 100) per_page = 20;
int offset = (page - 1) * per_page;
// Sorting
const char* sort = query_param_char(ctx->request, "sort", &ok);
if (!ok || sort == NULL) sort = "created_at";
const char* order = query_param_char(ctx->request, "order", &ok);
if (!ok || order == NULL) order = "desc";
// Build SQL query or use ORM...
char response[256];
snprintf(response, sizeof(response),
"Page: %d, Per page: %d, Offset: %d, Sort: %s %s",
page, per_page, offset, sort, order
);
ctx->response->send_data(ctx->response, response);
}Multiple Filters
c
// URL: /products?category=electronics&min_price=100&max_price=1000&in_stock=true
void filter_products(httpctx_t* ctx) {
int ok = 0;
const char* category = query_param_char(ctx->request, "category", &ok);
double min_price = query_param_double(ctx->request, "min_price", &ok);
if (!ok) min_price = 0;
double max_price = query_param_double(ctx->request, "max_price", &ok);
if (!ok) max_price = 999999;
const char* in_stock_str = query_param_char(ctx->request, "in_stock", &ok);
int in_stock = (ok && in_stock_str && strcmp(in_stock_str, "true") == 0);
// Apply filters...
json_doc_t* doc = json_root_create_object();
json_token_t* root = json_root(doc);
if (category) json_object_set(root, "category", json_create_string(category));
json_object_set(root, "min_price", json_create_number(min_price));
json_object_set(root, "max_price", json_create_number(max_price));
json_object_set(root, "in_stock", json_create_bool(in_stock));
ctx->response->header_add(ctx->response, "Content-Type", "application/json");
ctx->response->send_data(ctx->response, json_stringify(doc));
json_free(doc);
}Error Handling
Always check the ok flag after extracting a parameter:
c
void safe_handler(httpctx_t* ctx) {
int ok = 0;
int value = query_param_int(ctx->request, "value", &ok);
if (!ok) {
// Parameter is missing or has invalid format
ctx->response->status_code = 400;
ctx->response->send_data(ctx->response, "Invalid or missing 'value' parameter");
return;
}
// Parameter successfully retrieved
// ...
}