|
// Written by retoor@molodetz.nl
|
|
|
|
// The source code provides functionality for making HTTP POST and GET requests over SSL/TLS using OpenSSL. It includes initialization and cleanup of the OpenSSL library, creation of SSL context, socket creation and connection, and sending requests with handling responses. Furthermore, it interfaces with JSON and handles authentication using an external "auth.h" file.
|
|
|
|
// Includes: "auth.h", <json-c/json.h>
|
|
|
|
// MIT License
|
|
|
|
#ifndef CALPACA_HTTP_H
|
|
#define CALPACA_HTTP_H
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <openssl/ssl.h>
|
|
#include <openssl/err.h>
|
|
#include "auth.h"
|
|
#include <json-c/json.h>
|
|
|
|
void init_openssl() {
|
|
SSL_load_error_strings();
|
|
OpenSSL_add_ssl_algorithms();
|
|
}
|
|
|
|
void cleanup_openssl() {
|
|
EVP_cleanup();
|
|
}
|
|
|
|
SSL_CTX *create_context() {
|
|
const SSL_METHOD *method = TLS_method();
|
|
SSL_CTX *ctx = SSL_CTX_new(method);
|
|
SSL_CTX_load_verify_locations(ctx, "/etc/ssl/certs/ca-certificates.crt", NULL);
|
|
|
|
return ctx;
|
|
}
|
|
|
|
SSL_CTX *create_context2() {
|
|
const SSL_METHOD *method = TLS_client_method();
|
|
SSL_CTX *ctx = SSL_CTX_new(method);
|
|
if (!ctx) {
|
|
perror("Unable to create SSL context");
|
|
ERR_print_errors_fp(stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return ctx;
|
|
}
|
|
|
|
int create_socket(const char *hostname, int port) {
|
|
struct hostent *host;
|
|
struct sockaddr_in addr;
|
|
|
|
host = gethostbyname(hostname);
|
|
if (!host) {
|
|
perror("Unable to resolve host");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (sock < 0) {
|
|
perror("Unable to create socket");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
addr.sin_family = AF_INET;
|
|
addr.sin_port = htons(port);
|
|
addr.sin_addr.s_addr = *(long *)(host->h_addr);
|
|
|
|
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
|
|
perror("Unable to connect to host");
|
|
close(sock);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
return sock;
|
|
}
|
|
|
|
char *http_post(const char *hostname, char *url, char *data) {
|
|
init_openssl();
|
|
int port = 443;
|
|
SSL_CTX *ctx = create_context();
|
|
int sock = create_socket(hostname, port);
|
|
SSL *ssl = SSL_new(ctx);
|
|
SSL_set_connect_state(ssl);
|
|
SSL_set_tlsext_host_name(ssl, hostname);
|
|
SSL_set_fd(ssl, sock);
|
|
|
|
int buffer_size = 4096;
|
|
char *buffer = malloc(buffer_size);
|
|
|
|
if (SSL_connect(ssl) <= 0) {
|
|
ERR_print_errors_fp(stderr);
|
|
} else {
|
|
size_t len = strlen(data);
|
|
char *request = malloc(len + 4096);
|
|
sprintf(request,
|
|
"POST %s HTTP/1.1\r\n"
|
|
"Content-Length: %ld\r\n"
|
|
"Content-Type: application/json\r\n"
|
|
"Host: api.openai.com\r\n"
|
|
"Authorization: Bearer %s\r\n"
|
|
"Connection: close\r\n\r\n%s",
|
|
url, len, resolve_api_key(), data);
|
|
|
|
SSL_write(ssl, request, strlen(request));
|
|
free(request);
|
|
|
|
int bytes;
|
|
int bytes_total = 0;
|
|
while ((bytes = SSL_read(ssl, buffer + bytes_total, buffer_size - 1)) > 0) {
|
|
bytes_total += bytes;
|
|
buffer = realloc(buffer, bytes_total + buffer_size);
|
|
buffer[bytes_total] = '\0';
|
|
}
|
|
}
|
|
|
|
SSL_free(ssl);
|
|
close(sock);
|
|
SSL_CTX_free(ctx);
|
|
cleanup_openssl();
|
|
|
|
return buffer;
|
|
}
|
|
|
|
char *http_get(const char *hostname, char *url) {
|
|
init_openssl();
|
|
int port = 443;
|
|
SSL_CTX *ctx = create_context();
|
|
int sock = create_socket(hostname, port);
|
|
SSL *ssl = SSL_new(ctx);
|
|
SSL_set_connect_state(ssl);
|
|
SSL_set_tlsext_host_name(ssl, hostname);
|
|
SSL_set_fd(ssl, sock);
|
|
|
|
int buffer_size = 4096;
|
|
char *buffer = malloc(buffer_size);
|
|
|
|
if (SSL_connect(ssl) <= 0) {
|
|
ERR_print_errors_fp(stderr);
|
|
} else {
|
|
char request[buffer_size];
|
|
sprintf(request,
|
|
"GET %s HTTP/1.1\r\n"
|
|
"Host: api.openai.com\r\n"
|
|
"Authorization: Bearer %s\r\n"
|
|
"Connection: close\r\n\r\n",
|
|
url, resolve_api_key());
|
|
|
|
SSL_write(ssl, request, strlen(request));
|
|
|
|
int bytes;
|
|
int bytes_total = 0;
|
|
while ((bytes = SSL_read(ssl, buffer + bytes_total, buffer_size - 1)) > 0) {
|
|
bytes_total += bytes;
|
|
buffer = realloc(buffer, bytes_total + buffer_size);
|
|
buffer[bytes_total] = '\0';
|
|
}
|
|
}
|
|
|
|
SSL_free(ssl);
|
|
close(sock);
|
|
SSL_CTX_free(ctx);
|
|
cleanup_openssl();
|
|
|
|
return buffer;
|
|
}
|
|
#endif |