2025-01-04 08:40:31 +01:00
// Written by retoor@molodetz.nl
2025-01-27 19:06:59 +01:00
// 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. It also interfaces with JSON and handles authentication using an external "auth.h" file.
2025-01-04 08:40:31 +01:00
// Includes: "auth.h", <json-c/json.h>
// MIT License
2025-03-03 17:06:05 +01:00
2025-01-05 22:59:51 +01:00
# ifndef R_HTTP_H
# define R_HTTP_H
2025-01-04 08:40:31 +01:00
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
# 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>
2025-01-05 22:59:51 +01:00
# include <stdbool.h>
# include "url.h"
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
2025-01-27 19:06:59 +01:00
void init_openssl ( ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
SSL_load_error_strings ( ) ;
OpenSSL_add_ssl_algorithms ( ) ;
}
2025-01-27 19:06:59 +01:00
void cleanup_openssl ( ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
EVP_cleanup ( ) ;
}
2025-01-27 19:06:59 +01:00
SSL_CTX * create_context ( ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 ;
}
2025-01-27 19:06:59 +01:00
SSL_CTX * create_context2 ( ) {
2025-01-04 08:40:31 +01:00
const SSL_METHOD * method = TLS_client_method ( ) ;
SSL_CTX * ctx = SSL_CTX_new ( method ) ;
2025-01-27 19:06:59 +01:00
if ( ! ctx ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
perror ( " Unable to create SSL context " ) ;
ERR_print_errors_fp ( stderr ) ;
exit ( EXIT_FAILURE ) ;
}
return ctx ;
}
2025-01-27 19:06:59 +01:00
int create_socket ( const char * hostname , int port ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
struct hostent * host ;
struct sockaddr_in addr ;
host = gethostbyname ( hostname ) ;
2025-01-27 19:06:59 +01:00
if ( ! host ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
perror ( " Unable to resolve host " ) ;
exit ( EXIT_FAILURE ) ;
}
int sock = socket ( AF_INET , SOCK_STREAM , 0 ) ;
2025-01-27 19:06:59 +01:00
if ( sock < 0 ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 ) ;
2025-01-27 19:06:59 +01:00
if ( connect ( sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) ! = 0 ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
perror ( " Unable to connect to host " ) ;
close ( sock ) ;
exit ( EXIT_FAILURE ) ;
}
return sock ;
}
2025-01-27 19:06:59 +01:00
typedef struct ssl_st ssl_stt ;
2025-01-05 22:59:51 +01:00
2025-01-27 19:06:59 +01:00
char * read_until_ssl ( ssl_stt * sock , char * until ) {
2025-03-03 17:06:05 +01:00
static char data [ 1024 * 1024 ] = { 0 } ;
2025-01-05 22:59:51 +01:00
int index = 0 ;
char chunk [ 2 ] ;
2025-01-27 19:06:59 +01:00
while ( SSL_read ( sock , chunk , 1 ) = = 1 ) {
2025-03-03 17:06:05 +01:00
data [ index + + ] = chunk [ 0 ] ;
2025-01-05 22:59:51 +01:00
data [ index ] = 0 ;
2025-01-27 19:06:59 +01:00
if ( strstr ( data , until ) ! = NULL ) {
2025-01-05 22:59:51 +01:00
return data ;
}
}
return NULL ;
}
2025-01-27 19:06:59 +01:00
char * read_until ( int sock , char * until ) {
2025-03-03 17:06:05 +01:00
static char data [ 1024 * 1024 ] = { 0 } ;
2025-01-05 22:59:51 +01:00
int index = 0 ;
char chunk [ 2 ] ;
2025-01-27 19:06:59 +01:00
while ( recv ( sock , chunk , 1 , 0 ) = = 1 ) {
2025-03-03 17:06:05 +01:00
data [ index + + ] = chunk [ 0 ] ;
2025-01-05 22:59:51 +01:00
data [ index ] = 0 ;
2025-01-27 19:06:59 +01:00
if ( strstr ( data , until ) ! = NULL ) {
2025-01-05 22:59:51 +01:00
return data ;
}
}
return NULL ;
}
2025-01-27 19:06:59 +01:00
size_t hex_to_int ( const char * hex ) {
2025-01-05 22:59:51 +01:00
size_t result = 0 ;
2025-01-27 19:06:59 +01:00
while ( * hex ) {
2025-01-05 22:59:51 +01:00
char c = * hex + + ;
2025-01-27 19:06:59 +01:00
if ( c > = ' 0 ' & & c < = ' 9 ' ) {
2025-01-05 22:59:51 +01:00
result = result * 16 + ( c - ' 0 ' ) ;
2025-01-27 19:06:59 +01:00
} else if ( c > = ' a ' & & c < = ' f ' ) {
2025-01-05 22:59:51 +01:00
result = result * 16 + ( c - ' a ' + 10 ) ;
2025-01-27 19:06:59 +01:00
} else if ( c > = ' A ' & & c < = ' F ' ) {
2025-01-05 22:59:51 +01:00
result = result * 16 + ( c - ' A ' + 10 ) ;
}
}
return result ;
}
2025-03-03 17:06:05 +01:00
bool http_has_header ( char * http_headers , char * http_header_name ) {
char search_for [ strlen ( http_header_name ) + 10 ] ;
2025-03-03 08:07:17 +01:00
search_for [ 0 ] = ' \0 ' ;
2025-03-03 17:06:05 +01:00
strcpy ( search_for , http_header_name ) ;
strcat ( search_for , " : " ) ;
2025-03-03 08:07:17 +01:00
return strstr ( http_headers , search_for ) ! = NULL ;
}
2025-03-03 17:06:05 +01:00
char * http_header_get_str ( char * http_headers , char * http_header_name ) {
char search_for [ strlen ( http_header_name ) + 10 ] ;
2025-03-03 08:07:17 +01:00
search_for [ 0 ] = ' \0 ' ;
2025-03-03 17:06:05 +01:00
strcpy ( search_for , http_header_name ) ;
strcat ( search_for , " : " ) ;
char * header = strstr ( http_headers , search_for ) ;
if ( ! header ) {
2025-03-03 08:07:17 +01:00
return NULL ;
}
header + = strlen ( search_for ) ;
2025-03-03 17:06:05 +01:00
char * end = strstr ( header , " \r \n " ) ;
2025-03-03 08:07:17 +01:00
* end = ' \0 ' ;
2025-03-03 17:06:05 +01:00
char * result = ( char * ) malloc ( end - header + 1 ) ;
2025-03-03 08:07:17 +01:00
strcpy ( result , header ) ;
return result ;
}
2025-03-03 17:06:05 +01:00
long http_header_get_long ( char * http_headers , char * http_header_name ) {
char * str_value = http_header_get_str ( http_headers , http_header_name ) ;
if ( ! str_value ) {
2025-03-03 08:07:17 +01:00
return 0 ;
2025-03-03 17:06:05 +01:00
}
2025-03-03 08:07:17 +01:00
long long_value = atol ( str_value ) ;
free ( str_value ) ;
return long_value ;
}
2025-03-03 17:06:05 +01:00
char * https_post ( const char * url , char * data ) {
2025-01-05 22:59:51 +01:00
url_t parsed_url ;
2025-01-27 19:06:59 +01:00
parse_url ( url , & parsed_url ) ;
char * hostname = parsed_url . hostname ;
char * path = parsed_url . path ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 ) ;
2025-01-04 08:35:39 +01:00
2025-01-27 19:06:59 +01:00
int buffer_size = 1024 * 1024 ;
2025-03-03 08:07:17 +01:00
char * buffer = ( char * ) malloc ( buffer_size ) ;
2025-01-05 22:59:51 +01:00
size_t chunk_size_total = 0 ;
2025-01-27 19:06:59 +01:00
if ( SSL_connect ( ssl ) < = 0 ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
ERR_print_errors_fp ( stderr ) ;
2025-01-27 19:06:59 +01:00
} else {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
size_t len = strlen ( data ) ;
2025-03-03 08:07:17 +01:00
char * request = ( char * ) malloc ( len + 1024 * 1024 ) ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 " ,
2025-01-05 22:59:51 +01:00
path , len , resolve_api_key ( ) , data ) ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
SSL_write ( ssl , request , strlen ( request ) ) ;
2025-01-04 08:35:39 +01:00
free ( request ) ;
2025-01-04 08:40:31 +01:00
2025-01-05 22:59:51 +01:00
char * headers = read_until_ssl ( ssl , " \r \n \r \n " ) ;
( void ) headers ;
2025-01-27 19:06:59 +01:00
2025-03-03 08:07:17 +01:00
long content_length = http_header_get_long ( headers , " Content-Length " ) ;
2025-03-03 17:06:05 +01:00
if ( content_length ) {
if ( content_length > buffer_size ) {
2025-03-03 08:07:17 +01:00
buffer_size = content_length ;
buffer = ( char * ) realloc ( buffer , buffer_size ) ;
}
size_t bytes_read = 0 ;
2025-03-03 17:06:05 +01:00
while ( bytes_read < content_length ) {
2025-03-03 08:07:17 +01:00
int bytes_read_chunk = SSL_read ( ssl , buffer + bytes_read , buffer_size - bytes_read ) ;
2025-03-03 17:06:05 +01:00
if ( bytes_read_chunk < = 0 ) {
2025-03-03 08:07:17 +01:00
free ( buffer ) ;
return NULL ;
}
bytes_read + = bytes_read_chunk ;
}
return buffer ;
}
2025-01-05 22:59:51 +01:00
size_t actual_buffer_size = buffer_size ;
2025-01-27 19:06:59 +01:00
while ( true ) {
2025-01-05 22:59:51 +01:00
char * header = read_until_ssl ( ssl , " \r \n " ) ;
size_t chunk_size = hex_to_int ( header ) ;
2025-03-03 17:06:05 +01:00
if ( chunk_size = = 0 ) {
2025-01-05 22:59:51 +01:00
break ;
2025-03-03 17:06:05 +01:00
}
2025-01-05 22:59:51 +01:00
size_t remaining = chunk_size ;
2025-01-27 19:06:59 +01:00
while ( remaining > 0 ) {
2025-01-05 22:59:51 +01:00
size_t to_read = ( remaining < buffer_size ) ? remaining : buffer_size ;
2025-03-03 08:07:17 +01:00
buffer = ( char * ) realloc ( buffer , actual_buffer_size + to_read + 1 ) ;
2025-01-05 22:59:51 +01:00
actual_buffer_size + = to_read ;
size_t bytes_read = SSL_read ( ssl , buffer + chunk_size_total , to_read ) ;
chunk_size_total + = bytes_read ;
2025-01-27 19:06:59 +01:00
if ( bytes_read < = 0 ) {
2025-01-05 22:59:51 +01:00
fprintf ( stderr , " Error reading chunk data \n " ) ;
return NULL ;
}
remaining - = bytes_read ;
}
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
}
2025-01-05 22:59:51 +01:00
buffer [ chunk_size_total ] = 0 ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
}
SSL_free ( ssl ) ;
close ( sock ) ;
SSL_CTX_free ( ctx ) ;
cleanup_openssl ( ) ;
2025-01-05 22:59:51 +01:00
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
return buffer ;
}
2025-03-03 17:06:05 +01:00
char * https_get ( const char * url ) {
2025-01-05 22:59:51 +01:00
url_t parsed_url ;
2025-01-27 19:06:59 +01:00
parse_url ( url , & parsed_url ) ;
char * hostname = parsed_url . hostname ;
char * path = parsed_url . path ;
2025-01-05 22:59:51 +01:00
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 ) ;
2025-01-27 19:06:59 +01:00
int buffer_size = 1024 * 1024 ;
char * buffer = malloc ( buffer_size ) ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
2025-01-27 19:06:59 +01:00
if ( SSL_connect ( ssl ) < = 0 ) {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
ERR_print_errors_fp ( stderr ) ;
2025-01-27 19:06:59 +01:00
} else {
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
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 " ,
2025-01-05 22:59:51 +01:00
path , resolve_api_key ( ) ) ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
SSL_write ( ssl , request , strlen ( request ) ) ;
2025-01-27 19:06:59 +01:00
char * headers = read_until_ssl ( ssl , " \r \n \r \n " ) ;
2025-01-05 22:59:51 +01:00
( void ) headers ;
size_t chunk_size_total = 0 ;
size_t actual_buffer_size = buffer_size ;
2025-01-27 19:06:59 +01:00
while ( true ) {
2025-01-05 22:59:51 +01:00
char * header = read_until_ssl ( ssl , " \r \n " ) ;
size_t chunk_size = hex_to_int ( header ) ;
2025-03-03 17:06:05 +01:00
if ( chunk_size = = 0 ) {
2025-01-05 22:59:51 +01:00
break ;
2025-03-03 17:06:05 +01:00
}
2025-01-05 22:59:51 +01:00
size_t remaining = chunk_size ;
2025-01-27 19:06:59 +01:00
while ( remaining > 0 ) {
2025-01-05 22:59:51 +01:00
size_t to_read = ( remaining < buffer_size ) ? remaining : buffer_size ;
2025-01-27 19:06:59 +01:00
buffer = realloc ( buffer , actual_buffer_size + to_read + 1 ) ;
2025-01-05 22:59:51 +01:00
actual_buffer_size + = to_read ;
size_t bytes_read = SSL_read ( ssl , buffer + chunk_size_total , to_read ) ;
chunk_size_total + = bytes_read ;
2025-01-27 19:06:59 +01:00
if ( bytes_read < = 0 ) {
2025-01-05 22:59:51 +01:00
fprintf ( stderr , " Error reading chunk data \n " ) ;
return NULL ;
}
remaining - = bytes_read ;
}
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
}
2025-01-05 22:59:51 +01:00
buffer [ chunk_size_total ] = 0 ;
chore: scaffold project with gitignore, makefile, cgi scripts, and core c headers
Add initial project structure including .gitignore for build artifacts,
Makefile with gcc build and run targets, README placeholder, cgi-bin
directory with gpt.py and gpt_template.html, and core C headers for
chat, http, line input, markdown rendering, and messages.
2025-01-04 06:00:03 +01:00
}
SSL_free ( ssl ) ;
close ( sock ) ;
SSL_CTX_free ( ctx ) ;
cleanup_openssl ( ) ;
return buffer ;
}
2025-01-05 22:59:51 +01:00
2025-01-27 19:06:59 +01:00
char * http_post ( char * url , char * data ) {
2025-01-05 22:59:51 +01:00
url_t parsed_url ;
2025-01-27 19:06:59 +01:00
parse_url ( url , & parsed_url ) ;
char * hostname = parsed_url . hostname ;
char * path = parsed_url . path ;
2025-01-05 22:59:51 +01:00
int port = atoi ( parsed_url . port ) ;
int sock = create_socket ( hostname , port ) ;
2025-01-27 19:06:59 +01:00
2025-01-27 18:57:21 +01:00
int buffer_size = 1024 * 1024 ;
2025-01-27 19:06:59 +01:00
char * buffer = malloc ( buffer_size ) ;
2025-01-05 22:59:51 +01:00
size_t chunk_size_total = 0 ;
2025-03-03 17:06:05 +01:00
2025-01-27 19:06:59 +01:00
size_t len = strlen ( data ) + strlen ( path ) + strlen ( resolve_api_key ( ) ) + 10 ;
char * request = malloc ( len + buffer_size ) ;
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 " ,
path , len , resolve_api_key ( ) , data ) ;
send ( sock , request , strlen ( request ) , 0 ) ;
free ( request ) ;
char * headers = read_until ( sock , " \r \n \r \n " ) ;
( void ) headers ;
2025-03-03 17:06:05 +01:00
2025-01-27 19:06:59 +01:00
size_t actual_buffer_size = buffer_size ;
while ( true ) {
char * header = read_until ( sock , " \r \n " ) ;
size_t chunk_size = hex_to_int ( header ) ;
if ( chunk_size = = 0 ) {
printf ( " END \n " ) ;
break ;
}
size_t remaining = chunk_size ;
while ( remaining > 0 ) {
size_t to_read = ( remaining < buffer_size ) ? remaining : buffer_size ;
buffer = realloc ( buffer , actual_buffer_size + to_read + 10 ) ;
actual_buffer_size + = to_read ;
size_t bytes_read = recv ( sock , buffer + chunk_size_total , to_read , 0 ) ;
if ( bytes_read < = 0 ) {
fprintf ( stderr , " Error reading chunk data \n " ) ;
return NULL ;
2025-01-05 22:59:51 +01:00
}
2025-03-03 17:06:05 +01:00
2025-01-27 19:06:59 +01:00
chunk_size_total + = bytes_read ;
remaining - = bytes_read ;
2025-01-05 22:59:51 +01:00
}
2025-01-27 19:06:59 +01:00
}
printf ( " HERE! \n " ) ;
buffer [ chunk_size_total ] = 0 ;
2025-01-05 22:59:51 +01:00
close ( sock ) ;
return buffer ;
}
2025-01-27 19:06:59 +01:00
char * http_get ( char * url ) {
2025-01-05 22:59:51 +01:00
url_t parsed_url ;
2025-01-27 19:06:59 +01:00
parse_url ( url , & parsed_url ) ;
char * hostname = parsed_url . hostname ;
char * path = parsed_url . path ;
2025-01-05 22:59:51 +01:00
int port = atoi ( parsed_url . port ) ;
int sock = create_socket ( hostname , port ) ;
2025-01-27 19:06:59 +01:00
int buffer_size = 1024 * 1024 ;
char * buffer = malloc ( buffer_size ) ;
2025-01-05 22:59:51 +01:00
2025-01-27 19:06:59 +01:00
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 " ,
path , resolve_api_key ( ) ) ;
2025-01-05 22:59:51 +01:00
2025-01-27 19:06:59 +01:00
send ( sock , request , strlen ( request ) , 0 ) ;
2025-01-05 22:59:51 +01:00
2025-01-27 19:06:59 +01:00
char * headers = read_until ( sock , " \r \n \r \n " ) ;
( void ) headers ;
size_t chunk_size_total = 0 ;
size_t actual_buffer_size = buffer_size ;
while ( true ) {
char * header = read_until ( sock , " \r \n " ) ;
size_t chunk_size = hex_to_int ( header ) ;
2025-03-03 17:06:05 +01:00
if ( chunk_size = = 0 ) {
2025-01-27 19:06:59 +01:00
break ;
2025-03-03 17:06:05 +01:00
}
2025-01-27 19:06:59 +01:00
size_t remaining = chunk_size ;
while ( remaining > 0 ) {
size_t to_read = ( remaining < buffer_size ) ? remaining : buffer_size ;
buffer = realloc ( buffer , actual_buffer_size + to_read + 1 ) ;
actual_buffer_size + = to_read ;
size_t bytes_read = recv ( sock , buffer + chunk_size_total , to_read , 0 ) ;
chunk_size_total + = bytes_read ;
if ( bytes_read < = 0 ) {
fprintf ( stderr , " Error reading chunk data \n " ) ;
return NULL ;
2025-01-05 22:59:51 +01:00
}
2025-01-27 19:06:59 +01:00
remaining - = bytes_read ;
2025-01-05 22:59:51 +01:00
}
2025-01-27 19:06:59 +01:00
}
buffer [ chunk_size_total ] = 0 ;
2025-01-05 22:59:51 +01:00
close ( sock ) ;
return buffer ;
}
2025-03-03 08:07:17 +01:00
# endif