- Simple API for making HTTP requests
- Support for GET and POST requests
- JSON sending and receiving capabilities
- Built-in JSON parsing and creation
- No external library dependencies - uses only standard C libraries and POSIX APIs
- Socket-based communication
- Configurable timeouts
- Detailed error reporting
- C compiler (gcc, clang, etc.)
- POSIX-compatible operating system (Linux, macOS, *BSD, etc.)
- CMake 3.10 or higher
For quick installation on Linux systems:
./install.sh
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make
sudo make install
sudo ldconfig
After installation, you can use Conduit in your CMake project:
find_package(conduit REQUIRED)
add_executable(your_app your_app.c)
target_link_libraries(your_app PRIVATE Conduit::conduit)
For non-CMake projects, you can use pkg-config:
gcc -o your_app your_app.c $(pkg-config --cflags --libs conduit)
conduit/
├── include/ # Public header files
│ ├── conduit.h # Main library interface
│ ├── failures.h # Error handling definitions
│ ├── http_client.h # HTTP client implementation
│ └── json_parser.h # JSON parsing utilities
├── src/ # Implementation files
│ ├── conduit.c
│ ├── failures.c
│ ├── http_client.c
│ └── json_parser.c
├── examples/ # Example applications
│ ├── simple_get.c
│ └── simple_post.c
├── cmake/ # CMake configuration files
│ └── conduit-config.cmake.in
├── conduit.pc.in # pkg-config template
└── install.sh # Installation script
mkdir build
cd build
cmake ..
make
mkdir build
cd build
cmake ..
make
sequenceDiagram
participant App as Application
participant Conduit as Conduit Library
participant Server as Web Server
%% GET Request Flow
App->>Conduit: conduit_connect(hostname, port)
Conduit->>Server: TCP Connection
Server-->>Conduit: Connection Established
Conduit-->>App: socket descriptor
App->>Conduit: conduit_send_request(sockfd, hostname, path)
Conduit->>Server: HTTP GET Request
App->>Conduit: conduit_receive_response(sockfd)
Server-->>Conduit: HTTP Response
Conduit-->>App: ConduitResponse structure
%% POST Request Flow
App->>Conduit: conduit_post_json(sockfd, hostname, path, json_body)
Conduit->>Server: HTTP POST Request with JSON
App->>Conduit: conduit_receive_response(sockfd)
Server-->>Conduit: HTTP Response
Conduit-->>App: ConduitResponse structure
App->>Conduit: conduit_free_response(response)
#include <stdio.h>
#include <conduit.h>
int main() {
// Connect to a server
int sockfd = conduit_connect("jsonplaceholder.typicode.com", 80);
if (sockfd < 0) {
fprintf(stderr, "Connection failed\n");
return 1;
}
// Send a GET request
if (conduit_send_request(sockfd, "jsonplaceholder.typicode.com", "/todos/1") < 0) {
fprintf(stderr, "Failed to send request\n");
return 1;
}
// Receive the response
ConduitResponse* response = conduit_receive_response(sockfd);
if (!response) {
fprintf(stderr, "Failed to receive response\n");
return 1;
}
// Process the response data
printf("Status code: %d\n", response->status_code);
// Parse and use JSON data if available
if (response->json && response->json->type == JSON_OBJECT) {
JsonObject* obj = response->json->value.object;
int userId = json_get_int(obj, "userId");
int id = json_get_int(obj, "id");
const char* title = json_get_string(obj, "title");
int completed = json_get_bool(obj, "completed");
printf("User ID: %d\n", userId);
printf("ID: %d\n", id);
printf("Title: %s\n", title);
printf("Completed: %s\n", completed ? "true" : "false");
}
// Free the response resources
conduit_free_response(response);
return 0;
}
#include <stdio.h>
#include <conduit.h>
int main() {
// Connect to a server
int sockfd = conduit_connect("jsonplaceholder.typicode.com", 80);
if (sockfd < 0) {
fprintf(stderr, "Connection failed\n");
return 1;
}
// Prepare JSON data to send
const char* json_body = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
// Send a POST request with JSON data
if (conduit_post_json(sockfd, "jsonplaceholder.typicode.com", "/posts", json_body) < 0) {
fprintf(stderr, "Failed to send POST request\n");
return 1;
}
// Receive the response
ConduitResponse* response = conduit_receive_response(sockfd);
if (!response) {
fprintf(stderr, "Failed to receive response\n");
return 1;
}
// Process the response data
printf("Status code: %d\n", response->status_code);
printf("Response body: %s\n", response->body);
// Free the response resources
conduit_free_response(response);
return 0;
}
int conduit_connect(const char* hostname, int port);
Establishes a connection to the specified server.
Parameters:
hostname
: The server hostname or IP addressport
: The port number
Returns:
- A socket file descriptor if successful
- A negative error code if an error occurs
int conduit_send_request(int sockfd, const char* hostname, const char* path);
Sends an HTTP GET request to the server.
Parameters:
sockfd
: The socket file descriptor fromconduit_connect
hostname
: The hostname for the Host headerpath
: The path for the request URL
Returns:
- 0 if successful
- A negative error code if an error occurs
int conduit_post_json(int sockfd, const char* hostname, const char* path, const char* json_body);
Sends an HTTP POST request with a JSON body to the server.
Parameters:
sockfd
: The socket file descriptor fromconduit_connect
hostname
: The hostname for the Host headerpath
: The path for the request URLjson_body
: The JSON data to send as a string
Returns:
- 0 if successful
- A negative error code if an error occurs
ConduitResponse* conduit_receive_response(int sockfd);
Receives and processes the HTTP response.
Parameters:
sockfd
: The socket file descriptor fromconduit_connect
Returns:
- A pointer to a
ConduitResponse
structure if successful - NULL if an error occurs
void conduit_free_response(ConduitResponse* response);
Frees all memory allocated for a response.
Parameters:
response
: The response structure to free
int json_get_int(JsonObject* obj, const char* key);
const char* json_get_string(JsonObject* obj, const char* key);
int json_get_bool(JsonObject* obj, const char* key);
JsonValue* conduit_parse_json(const char* json_string);
Extract values from a parsed JSON object or parse a JSON string.
Parameters:
obj
: The JSON object to extract fromkey
: The key to look upjson_string
: The JSON string to parse
Returns:
- The requested value if found
- Default value (0, NULL, or false) if not found or wrong type
- Parsed JSON value pointer for
conduit_parse_json
JsonValue* json_create_null();
JsonValue* json_create_boolean(int boolean_value);
JsonValue* json_create_number(double number_value);
JsonValue* json_create_string(const char* string_value);
JsonValue* json_create_object();
Create JSON values for building JSON data structures.
Returns:
- A pointer to a new JsonValue structure of the specified type
typedef struct {
int status_code; // HTTP status code
char* body; // Response body as string
char* headers; // Response headers
char* content_type; // Content-Type header value
JsonValue* json; // Parsed JSON (if response is JSON)
} ConduitResponse;
The library provides detailed error reporting via error codes and messages:
typedef enum {
ERR_HOSTNAME_RESOLUTION,
ERR_SOCKET_CREATION,
ERR_SEVER_CONNECTION,
ERR_SEND_HTTP_REQ,
ERR_BUFF_OVERFLOW,
ERR_RECEIVING_DATA
} ErrorCode;
const char* get_error_message(ErrorCode code);
This project is licensed under the MIT License - see the LICENSE file for details.