Skip to content

Instantly share code, notes, and snippets.

@Hakkadaikon
Created February 27, 2025 21:04
Show Gist options
  • Save Hakkadaikon/2a4a4a48260b612a18448ad06db71316 to your computer and use it in GitHub Desktop.
Save Hakkadaikon/2a4a4a48260b612a18448ad06db71316 to your computer and use it in GitHub Desktop.
OpenRouter Example
#include <curl/curl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
typedef char* PCHAR;
typedef void* PVOID;
typedef CURL* PCURL;
typedef struct curl_slist CurlList;
typedef struct curl_slist* PCurlList;
typedef struct curl_slist** PPCurlList;
typedef struct {
PCHAR response;
size_t size;
} OpenRouterResponse;
typedef OpenRouterResponse* POpenRouterResponse;
static size_t writeCallback(PVOID ptr, size_t size, size_t nmemb, PVOID userdata);
static bool isBlankStr(const PCHAR str, const size_t size);
static void makeHeaders(const PCHAR api_key, PPCurlList headers);
static void makeJsonData(const PCHAR model, const PCHAR content, const size_t capacity, PCHAR json_data);
static void setCurlOpt(const PCHAR url, const PCurlList headers, const PCHAR json_data, POpenRouterResponse chunk, PCURL curl);
CURLcode reqOpenRouter(const PCHAR api_key, const PCHAR model, const PCHAR content, POpenRouterResponse chunk);
int main(void)
{
char api_key[] = "-- api-key --";
PCHAR model = "openai/gpt-4o";
PCHAR content = "What is the meaning of life?";
OpenRouterResponse chunk;
memset(&chunk, 0x00, sizeof(chunk));
CURLcode res = reqOpenRouter(api_key, model, content, &chunk);
if (res == CURLE_OK) {
printf("response : %s\n", chunk.response);
}
if (chunk.response != NULL) {
free(chunk.response);
}
return (res == CURLE_OK) ? 0 : 1;
}
CURLcode reqOpenRouter(const PCHAR api_key, const PCHAR model, const PCHAR content, POpenRouterResponse chunk)
{
const PCHAR url = "https://openrouter.ai/api/v1/chat/completions";
CURLcode res = CURLE_OK;
curl_global_init(CURL_GLOBAL_DEFAULT);
PCURL curl = curl_easy_init();
if (!curl) {
curl_global_cleanup();
return res;
}
PCurlList headers = NULL;
char json_data[2048];
makeHeaders(api_key, &headers);
makeJsonData(model, content, sizeof(json_data), json_data);
setCurlOpt(url, headers, json_data, chunk, curl);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
goto FINALIZE;
}
FINALIZE:
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
curl_global_cleanup();
return res;
}
static size_t writeCallback(PVOID ptr, size_t size, size_t nmemb, PVOID userdata)
{
size_t realsize = size * nmemb;
POpenRouterResponse res = (POpenRouterResponse)userdata;
if (isBlankStr(ptr, realsize)) {
return realsize;
}
PCHAR ptr_new = realloc(res->response, res->size + realsize + 1);
if (ptr_new == NULL) {
return 0;
}
res->response = ptr_new;
memcpy(&(res->response[res->size]), ptr, realsize);
res->size += realsize;
res->response[res->size] = '\0';
return realsize;
}
static bool isBlankStr(const PCHAR str, const size_t size)
{
for (int i = 0; i < size; i++) {
char c = str[i];
if (c != ' ' && c != '\r' && c != '\n') {
return false;
}
}
return true;
}
static void makeHeaders(const PCHAR api_key, PPCurlList headers)
{
char auth_header[256];
snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key);
*headers = curl_slist_append(*headers, "Content-Type: application/json");
*headers = curl_slist_append(*headers, auth_header);
}
static void makeJsonData(const PCHAR model, const PCHAR content, const size_t capacity, PCHAR json_data)
{
snprintf(
json_data,
capacity,
"{\"model\":\"%s\",\"messages\":[{\"role\":\"user\",\"content\":\"%s\"}]}",
model,
content);
}
static void setCurlOpt(const PCHAR url, const PCurlList headers, const PCHAR json_data, POpenRouterResponse chunk, PCURL curl)
{
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (PVOID)chunk);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment