17static char *clone_str(
const char *s) {
42 if (!name)
return NULL;
58 if (!client || !req)
return;
71 if (
c->name &&
c->value) buf_len +=
strlen(
c->name) + 1 +
strlen(
c->value) + 2;
84 if (!
c->name || !
c->value)
continue;
103static char *trim(
char *s) {
104 while (*s &&
isspace((
unsigned char)*s)) s++;
106 while (
e > s &&
isspace((
unsigned char)
e[-1])) *--
e =
'\0';
117 if (!client || !res)
return;
119 if (!h->key || !h->value ||
strcasecmp(h->key->data,
"Set-Cookie") != 0)
continue;
120 char *buf = clone_str(h->value->data);
135 char *name = clone_str(trim(
name_val));
136 char *value = clone_str(trim(
eq + 1));
137 if (!name || !value) {
148 path = clone_str(trim(
rest + 5));
188 if (!app)
return NULL;
190 if (!client)
return NULL;
219 if (!client || !client->
app || !path)
return NULL;
221 if (!req)
return NULL;
247 const char *body = opts ? opts->
body :
NULL;
266 cookie_jar_apply(client, req, opts ? opts->
cookies :
NULL, opts ? opts->cookie_count : 0);
274 cookie_jar_update(client, res);
289 return do_request(client, method, path, opts);
377 const char *content_type,
const char *data,
381 const char *
boundary =
"CWISTTestClientBoundary7MA4YWxkTrZu0gW";
387 if (!body)
return NULL;
392 "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
395 (
size_t)
snprintf(body + pos, body_len + 1 - pos,
"Content-Type: %s\r\n\r\n", content_type);
396 memcpy(body + pos, data, data_len);
424 if (!client || !name)
return;
428 c->value = value ? clone_str(value) :
NULL;
431 c->path = clone_str(path);
436 c->name = clone_str(name);
437 c->value = value ? clone_str(value) :
NULL;
438 c->path = path ? clone_str(path) :
NULL;
451 if (!client || !name)
return NULL;
453 return c ?
c->value :
NULL;
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
#define CWIST_DEFER_FREE
Attach to a pointer variable's declaration to cwist_free() it automatically when that variable's encl...
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
Safe string type with helper methods.
cwist_error_t cwist_sstring_assign_len(cwist_sstring *str, const char *data, size_t len)
Assign raw bytes with length.
cwist_error_t cwist_sstring_assign(cwist_sstring *str, const char *data)
Assign a C string.
void cwist_http_request_destroy(cwist_http_request *req)
Destroy an HTTP request object.
cwist_error_t cwist_http_header_add(cwist_http_header_node **head, const char *key, const char *value)
Add a header to the list.
cwist_http_response * cwist_http_response_create(void)
Create a new HTTP response object.
cwist_http_request * cwist_http_request_create(void)
Create a new HTTP request object.
void cwist_query_map_clear(cwist_query_map *map)
Clear all entries.
cwist_query_map * cwist_query_map_create(void)
Create a new query map.
void cwist_query_map_parse(cwist_query_map *map, const char *raw_query)
Parse raw query strings (e.g., "a=1&b=2") into the map.
Main Application Context.
cwist_query_map * query_params
Parsed query parameters.
cwist_sstring * path
e.g., "/users/1"
cwist_sstring * query
e.g., "active=true" (raw)
cwist_http_header_node * headers
cwist_http_method_t method
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
cwist_http_header_node * headers
struct cwist_test_client_cookie * next
A single key/value pair for headers or ad-hoc cookies.
Optional parameters for advanced test requests.
const char * content_type
const char * query_string
const cwist_test_client_kv * cookies
const cwist_test_client_kv * headers
cwist_test_client_cookie * cookies
void cwist_app_dispatch(cwist_app *app, cwist_http_request *req, cwist_http_response *res)
Dispatch a request internally through the app's router and middleware. Used by the test client and ad...
cwist_http_response * cwist_test_client_post_json(cwist_test_client *client, const char *path, const char *json_body)
Send a POST request with a JSON body and application/json content type.
cwist_http_response * cwist_test_client_post_multipart(cwist_test_client *client, const char *path, const char *field_name, const char *file_name, const char *content_type, const char *data, size_t data_len)
Send a POST request with a single-file multipart/form-data body. Builds the multipart body with a fix...
cwist_http_response * cwist_test_client_put(cwist_test_client *client, const char *path, const char *body)
Send a PUT request with a plain-text body.
cwist_http_response * cwist_test_client_get(cwist_test_client *client, const char *path)
Send a GET request.
void cwist_test_client_clear_cookies(cwist_test_client *client)
Remove and free all cookies in the client's jar.
cwist_http_response * cwist_test_client_delete(cwist_test_client *client, const char *path)
Send a DELETE request.
void cwist_test_client_destroy(cwist_test_client *client)
Destroy a test client and free all its cookies.
cwist_http_response * cwist_test_client_request_ex(cwist_test_client *client, cwist_http_method_t method, const char *path, const cwist_test_client_request_options *opts)
Send a request with explicit method and options.
cwist_http_response * cwist_test_client_patch(cwist_test_client *client, const char *path, const char *body)
Send a PATCH request with a plain-text body.
void cwist_test_client_set_cookie(cwist_test_client *client, const char *name, const char *value, const char *path)
Set or replace a cookie in the client's jar. A cookie with the same name gets its value replaced (and...
const char * cwist_test_client_get_cookie(cwist_test_client *client, const char *name)
Get the value of a cookie from the client's jar.
cwist_test_client * cwist_test_client_create(cwist_app *app)
Create a test HTTP client bound to an app.
cwist_http_response * cwist_test_client_post(cwist_test_client *client, const char *path, const char *body)
Send a POST request with a plain-text body.
In-process HTTP test client (ala Flask test_client).