├── docs ├── tutorials │ ├── web_assembly.md │ ├── headers.md │ └── query_param.md ├── public_api │ ├── BearHttpsRequest_free.md │ ├── BearHttpsResponse_get_body_size.md │ ├── BearHttpsResponse_get_error_code.md │ ├── BearHttpsResponse_free.md │ ├── BearHttpsResponse_error.md │ ├── BearHttpsResponse_get_headers_size.md │ ├── BearHttpsResponse_get_status_code.md │ ├── newBearHttpsRequest.md │ ├── BearHttpsRequest_send_body_str.md │ ├── BearHttpsRequest_send_cJSON.md │ ├── BearHttpsResponse_get_error_msg.md │ ├── BearHttpsRequest_fetch.md │ ├── BearHttpsResponse_read_body_str.md │ ├── BearHttpsRequest_set_max_redirections.md │ ├── BearHttpsRequest_add_header.md │ ├── BearHttpsRequest_send_any.md │ ├── BearHttpsResponse_get_header_value_by_key.md │ ├── BearHttpsRequest_set_chunk_header_read_props.md │ ├── BearHttpsRequest_create_cJSONPayloadArray.md │ ├── BearHttpsRequest_create_cJSONPayloadObject.md │ ├── BearHttpsRequest_add_header_fmt.md │ ├── BearHttpsRequest_set_known_ips.md │ ├── BearHttpsRequest_set_dns_providers.md │ ├── BearHttpsResponse_get_header_key_by_index.md │ ├── BearHttpsResponse_read_body_json.md │ ├── BearHttpsResponse_get_header_value_by_index.md │ ├── BearHttpsRequest_set_trusted_anchors.md │ ├── BearHttpsResponse_get_header_value_by_sanitized_key.md │ ├── BearHttpsRequest_send_cJSON_with_ownership_control.md │ ├── BearHttpsRequest_send_body_str_with_ownership_control.md │ ├── BearHttpsRequest_send_any_with_ownership_control.md │ └── newBearHttpsRequest_with_url_ownership_config.md ├── instalations │ ├── one_file.md │ ├── precompiled.md │ ├── full_dir.md │ └── build_from_scratch.md ├── dependencies.md ├── public_api.md └── ai_doc.md ├── darwinconf.lua ├── src ├── one.c ├── _WIN32 │ ├── src_dependencies │ │ ├── dep_declareB.dependencies.h │ │ └── dep_defineB.dependencies.c │ └── fdefine.socket.c ├── !__EMSCRIPTEN__ │ ├── config │ │ ├── macros.protocol.h │ │ ├── macros.http1_states.h │ │ ├── macros.body_read_mode.h │ │ ├── globals.dns.c │ │ └── macros.sizes.h │ ├── network │ │ ├── globals.cache_dns.h │ │ ├── types.dns_cache.h │ │ ├── fdefine.sock.c │ │ ├── fdefine.ipv4_connect.c │ │ └── fdefine.connect_host.c │ ├── request │ │ ├── types.dns_provider.h │ │ ├── typesC.request.h │ │ ├── fdefine.request.c │ │ ├── fdefine.body_send.c │ │ └── fdefine.fetch.c │ ├── namespace │ │ ├── typesH.namespace.h │ │ ├── fdefine.namespace.c │ │ ├── response │ │ │ ├── fdefine.response.c │ │ │ └── typesE.response.h │ │ └── request │ │ │ ├── fdefine.request.c │ │ │ └── typesE.request.h │ ├── requisition_props │ │ ├── types.requisition_props.h │ │ └── fdefine.requisition_props.c │ ├── src_dependencies │ │ ├── dep_declareB.dependencies.h │ │ └── dep_defineB.dependencies.c │ └── response │ │ ├── response │ │ ├── typesD.response.h │ │ └── fdefine.response.c │ │ ├── fdefine.read_write.c │ │ ├── fdefine.body_read.c │ │ ├── fdefine.body_read_chunk.c │ │ └── fdefine.http_parser.c ├── ALL │ ├── StringArray │ │ ├── types.StringArray.h │ │ └── fdefine.StringArray.c │ ├── headers │ │ ├── typesB.headers.h │ │ └── fdefine.headers.c │ ├── src_dependencies │ │ ├── dep_define.dependencies.c │ │ └── dep_declare.dependencies.h │ ├── config │ │ ├── macros.body_types.h │ │ ├── macros.ownership.h │ │ └── macros.errors.h │ ├── keyval │ │ ├── types.keyval.h │ │ └── fdefine.keyval.c │ ├── request │ │ ├── request │ │ │ ├── types.body_types.h │ │ │ └── fdefine.request.c │ │ └── fdefine.body_send.c │ ├── fdefine.ownership.c │ ├── response │ │ ├── fdefine.body_read.c │ │ └── fdefine.response.c │ ├── fdefine.extra.c │ └── fdefine.str.c ├── _MSC_VER │ └── dep_declareB.dependencies.h ├── tests.os_test.h ├── __EMSCRIPTEN__ │ ├── response │ │ ├── typesD.response.h │ │ ├── fdefine.response.c │ │ └── fdefine.read_body.c │ ├── src_dependencies │ │ └── dep_declareB.dependencies.h │ └── request │ │ ├── typesC.request.h │ │ ├── fdefine.request.c │ │ └── fdefine.fetch.c └── __unix__&&!__EMSCRIPTEN__ │ └── network │ ├── fdefine.socket.c │ └── fdefine.connect_host.c ├── release.json ├── examples └── example_simple.c ├── .gitignore ├── LICENSE ├── darwindeps.json ├── devops.releasefier.lua └── README.md /docs/tutorials/web_assembly.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /darwinconf.lua: -------------------------------------------------------------------------------- 1 | darwin.load_all("build") -------------------------------------------------------------------------------- /src/one.c: -------------------------------------------------------------------------------- 1 | 2 | #ifndef BEARHTTPS_CLIENT_ONE 3 | #define BEARHTTPS_CLIENT_ONE 4 | #include "imports/imports.fdefine.h" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/_WIN32/src_dependencies/dep_declareB.dependencies.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declare.h" 4 | //silver_chain_scope_end 5 | 6 | #if defined(_WIN32) 7 | 8 | 9 | 10 | #endif -------------------------------------------------------------------------------- /src/_WIN32/src_dependencies/dep_defineB.dependencies.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_define.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | #if defined(_WIN32) 8 | typedef __m128i __m128i_u; 9 | 10 | 11 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/config/macros.protocol.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | #define BEARSSL_HTTPS_HTTP1_0 0 7 | #define BEARSSL_HTTPS_HTTP1_1 1 8 | 9 | #endif -------------------------------------------------------------------------------- /src/ALL/StringArray/types.StringArray.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | typedef struct privateBearHttpsStringArray { 6 | int size; 7 | char **strings; 8 | }privateBearHttpsStringArray; 9 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/config/macros.http1_states.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | #define PRIVATE_BEARHTTPS_COLLECTING_NUMBER 0 7 | #define PRIVATE_BEARHTTPS_READING_CHUNK 1 8 | #endif -------------------------------------------------------------------------------- /src/ALL/headers/typesB.headers.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.types.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | typedef struct private_BearHttpsHeaders{ 8 | int size; 9 | private_BearHttpsKeyVal **keyvals; 10 | }private_BearHttpsHeaders; 11 | 12 | -------------------------------------------------------------------------------- /src/ALL/src_dependencies/dep_define.dependencies.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.globals.h" 4 | //silver_chain_scope_end 5 | 6 | #if !defined(BEARSSL_HTTPS_MOCK_CJSON_DEFINE) && defined(BEARSSL_HTTPS_CJSON_DECLARATED) 7 | #include "../../../dependencies/cJSON.c" 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ALL/config/macros.body_types.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | 9 | 10 | #define PRIVATE_BEARSSL_NO_BODY 0 11 | #define PRIVATE_BEARSSL_BODY_RAW 1 12 | #define PRIVATE_BEARSSL_BODY_FILE 2 13 | #define PRIVATE_BEARSSL_BODY_JSON 3 14 | -------------------------------------------------------------------------------- /src/ALL/keyval/types.keyval.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | 9 | typedef struct private_BearHttpsKeyVal{ 10 | char *key; 11 | bool key_owner; 12 | char *value; 13 | bool value_owner; 14 | 15 | }private_BearHttpsKeyVal; 16 | 17 | -------------------------------------------------------------------------------- /src/ALL/config/macros.ownership.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | #define BEARSSL_HTTPS_REFERENCE 0 8 | #define BEARSSL_HTTPS_GET_OWNERSHIP 1 9 | #define BEARSSL_HTTPS_COPY 2 10 | 11 | #define BEARSSL_DEFAULT_STRATEGY BEARSSL_HTTPS_COPY 12 | 13 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/network/globals.cache_dns.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.fdeclare.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | privateBearHttpsDnsCache privateBearHttpsDnsCache_itens[BEARSSL_DNS_CACHE_SIZE] ={0}; 8 | 9 | int privateBearHttpsDnsCache_last_free_point = 0; 10 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/network/types.dns_cache.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | typedef struct privateBearHttpsDnsCache{ 8 | 9 | char host[BEARSSL_DNS_CACHE_HOST_SIZE]; 10 | char ip[BEARSSL_DNS_CACHE_IP_SIZE]; 11 | }privateBearHttpsDnsCache; 12 | #endif -------------------------------------------------------------------------------- /src/_MSC_VER/dep_declareB.dependencies.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../imports/imports.dep_declare.h" 4 | //silver_chain_scope_end 5 | 6 | #if defined(_MSC_VER) 7 | #include 8 | #include 9 | 10 | typedef SSIZE_T ssize_t; 11 | typedef __m128i __m128i_u; 12 | 13 | #define __src_inner_hbyteswap_ulong _byteswap_ulong 14 | #endif 15 | -------------------------------------------------------------------------------- /release.json: -------------------------------------------------------------------------------- 1 | { 2 | "replacers": { 3 | "BIG_VERSION": "0", 4 | "SMALL_VERSION": "9", 5 | "PATCH_VERSION": "2" 6 | }, 7 | "release": "{BIG_VERSION}.{SMALL_VERSION}.{PATCH_VERSION}", 8 | "tag": "{BIG_VERSION}.{SMALL_VERSION}.{PATCH_VERSION}", 9 | "description": "new release to BearHttpsClient", 10 | "assets": ["release/BearHttpsClient.c", "release/BearHttpsClient.h", "release/BearHttpsClient.zip", "release/BearHttpsClientOne.c"] 11 | } -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/request/types.dns_provider.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | 11 | typedef struct BearHttpsClientDnsProvider { 12 | const char *hostname; 13 | const char *route; 14 | const char *ip; 15 | int port; 16 | }BearHttpsClientDnsProvider; 17 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_free.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_free 2 | ```c 3 | void BearHttpsRequest_free(BearHttpsRequest *self); 4 | ``` 5 | ### Description 6 | Frees the memory allocated for a `BearHttpsRequest` object and all its associated resources. This function should be called for every request object created to prevent memory leaks. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object to free 10 | 11 | ### Returns 12 | This function does not return a value. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_body_size.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_body_size 2 | ```c 3 | int BearHttpsResponse_get_body_size(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Gets the size of the response body in bytes. This is useful for determining how much data was received. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | The size of the response body in bytes, or -1 if the response is invalid or an error occurred. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_error_code.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_error_code 2 | ```c 3 | int BearHttpsResponse_get_error_code(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Gets a numeric error code if an error occurred during the HTTP request. This provides a machine-readable way to identify specific error conditions. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | A numeric error code, or 0 if no error occurred. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_free.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_free 2 | ```c 3 | void BearHttpsResponse_free(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Frees the memory allocated for a `BearHttpsResponse` object and all its associated resources. This function should be called for every response object received to prevent memory leaks. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object to free 10 | 11 | ### Returns 12 | This function does not return a value. 13 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/typesH.namespace.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.typesE.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | typedef struct BearHttpsNamespace{ 10 | short REFERENCE; 11 | short GET_OWNERSHIP; 12 | short COPY; 13 | BearHttpsRequestNamespace request; 14 | BearHttpsResponseNamespace response; 15 | } BearHttpsNamespace; 16 | 17 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_error.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_error 2 | ```c 3 | bool BearHttpsResponse_error(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Checks if an error occurred during the HTTP request. This should be the first function called after receiving a response to determine if the request was successful. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | `true` if an error occurred, `false` if the request was successful. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_headers_size.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_headers_size 2 | ```c 3 | int BearHttpsResponse_get_headers_size(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Gets the number of headers in the HTTP response. This is useful for iterating through all response headers. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | The number of headers in the response, or -1 if the response is invalid or an error occurred. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_status_code.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_status_code 2 | ```c 3 | int BearHttpsResponse_get_status_code(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Gets the HTTP status code from the response (e.g., 200 for OK, 404 for Not Found, 500 for Internal Server Error). 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | The HTTP status code as an integer, or -1 if the response is invalid or an error occurred. 13 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/requisition_props/types.requisition_props.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | 11 | typedef struct private_BearHttpsRequisitionProps{ 12 | char *hostname; 13 | char *route; 14 | bool is_ipv4; 15 | bool is_ipv6; 16 | bool is_https; 17 | int port; 18 | }private_BearHttpsRequisitionProps ; 19 | 20 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/config/macros.body_read_mode.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | #define PRIVATE_BEARSSL_BY_CONTENT_LENGTH 0 8 | #define PRIVATE_BEARSSL_BY_CHUNKED 1 9 | //when no content length or chunked encoding is present, the body is read until an error occurs or the end of the stream is reached. 10 | #define PRIVATE_BEARSSL_BY_READ_ERROR 2 11 | #endif -------------------------------------------------------------------------------- /src/tests.os_test.h: -------------------------------------------------------------------------------- 1 | 2 | #if !defined(__EMSCRIPTEN__) 3 | 4 | // Discoment these to allo emcc on your intelisense 5 | // never Discoment these for building the lib 6 | // these disable code errors on intelisense //but also make the code not works on browser 7 | // so to work on browser compile with -D__EMSCRIPTEN__ 8 | //#define __EMSCRIPTEN_DISABLE_ERRORS__ 9 | //#define __EMSCRIPTEN__ 10 | #endif 11 | #if !defined(_WIN32) 12 | // Discoment these to allo emcc on your intelisense 13 | // never Discoment these for building the lib 14 | //#define _WIN32 15 | #endif -------------------------------------------------------------------------------- /docs/public_api/newBearHttpsRequest.md: -------------------------------------------------------------------------------- 1 | 2 | ### Function: newBearHttpsRequest 3 | ```c 4 | BearHttpsRequest * newBearHttpsRequest(const char *url); 5 | ``` 6 | ### Description 7 | Creates a new `BearHttpsRequest` object with the specified URL. The URL is copied internally, so the original string can be freed after this call. 8 | ### Parameters 9 | - `url`: A string representing the URL for the request. This should be a valid HTTPS URL. 10 | 11 | ### Returns 12 | A pointer to the newly created `BearHttpsRequest` object. If the URL is invalid or memory allocation fails, it returns `NULL`. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_body_str.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_body_str 2 | ```c 3 | void BearHttpsRequest_send_body_str(BearHttpsRequest *self, char *content); 4 | ``` 5 | ### Description 6 | Sends a string as the request body using the default ownership strategy (copy). This is a convenience function for sending text data, JSON strings, or other string-based content. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `content`: Pointer to the null-terminated string to send 11 | 12 | ### Returns 13 | This function does not return a value. 14 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_cJSON.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_cJSON 2 | ```c 3 | void BearHttpsRequest_send_cJSON(BearHttpsRequest *self, cJSON *json); 4 | ``` 5 | ### Description 6 | Sends a cJSON object as the request body using the default ownership strategy (copy). This is a convenience function for sending JSON data. The JSON is automatically serialized to a string before sending. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `json`: Pointer to the cJSON object to send 11 | 12 | ### Returns 13 | This function does not return a value. 14 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_error_msg.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_error_msg 2 | ```c 3 | const char* BearHttpsResponse_get_error_msg(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Gets a human-readable error message if an error occurred during the HTTP request. This function should only be called if `BearHttpsResponse_error()` returns `true`. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | A pointer to a null-terminated string containing the error message, or `NULL` if no error occurred or the response is invalid. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_fetch.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_fetch 2 | ```c 3 | BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self); 4 | ``` 5 | ### Description 6 | Executes the HTTP request and returns the response. This function performs the actual network communication, including DNS resolution, SSL/TLS handshake, and data transfer. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | 11 | ### Returns 12 | A pointer to a `BearHttpsResponse` object containing the server's response. The caller is responsible for freeing the response using `BearHttpsResponse_free()`. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_read_body_str.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_read_body_str 2 | ```c 3 | const char* BearHttpsResponse_read_body_str(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Reads the response body as a null-terminated string. This is useful for text-based responses like HTML, JSON, or plain text. **Important: Always check for NULL before using the return value.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | A pointer to the response body as a null-terminated string, or `NULL` if the body is empty, invalid, or the response has an error. 13 | -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/response/typesD.response.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.typesC.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | typedef struct BearHttpsResponse{ 10 | c2wasm_js_var response; 11 | private_BearHttpsHeaders *headers; 12 | int error_code; 13 | unsigned char *body; 14 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 15 | cJSON *json_body; 16 | #endif 17 | long body_size; 18 | char *error_msg; 19 | int status_code; 20 | }BearHttpsResponse ; 21 | 22 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_set_max_redirections.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_set_max_redirections 2 | ```c 3 | void BearHttpsRequest_set_max_redirections(BearHttpsRequest *self, int max_redirections); 4 | ``` 5 | ### Description 6 | Sets the maximum number of HTTP redirections (3xx responses) that the client will automatically follow. By default, redirections are followed up to a reasonable limit. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `max_redirections`: Maximum number of redirections to follow (0 to disable redirections) 11 | 12 | ### Returns 13 | This function does not return a value. 14 | -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/src_dependencies/dep_declareB.dependencies.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declare.h" 4 | //silver_chain_scope_end 5 | 6 | #if defined(__EMSCRIPTEN__) 7 | 8 | 9 | #include 10 | // these its just for intelisense stop showing errors 11 | #if defined(__EMSCRIPTEN_DISABLE_ERRORS__) 12 | #undef __EMSCRIPTEN__ 13 | #endif 14 | #define C2WASM_ALLOW_ASYNC 15 | #include "../../../dependencies/c2wasm.c" 16 | 17 | #if defined(__EMSCRIPTEN_DISABLE_ERRORS__) 18 | #define __EMSCRIPTEN__ 19 | #endif 20 | 21 | 22 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_add_header.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_add_header 2 | ```c 3 | void BearHttpsRequest_add_header(BearHttpsRequest *self, const char *key, const char *value); 4 | ``` 5 | ### Description 6 | Adds a header to the HTTP request. The header key and value are copied internally, so the original strings can be freed after this call. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `key`: The header key/name (e.g., "Content-Type", "Authorization") 11 | - `value`: The header value (e.g., "application/json", "Bearer token123") 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_any.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_any 2 | ```c 3 | void BearHttpsRequest_send_any(BearHttpsRequest *self, unsigned char *content, long size); 4 | ``` 5 | ### Description 6 | Sends binary data as the request body using the default ownership strategy (copy). This is a convenience function that calls `BearHttpsRequest_send_any_with_ownership_control` with `BEARSSL_HTTPS_COPY`. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `content`: Pointer to the binary data to send 11 | - `size`: Size of the data in bytes 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/config/globals.dns.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.fdeclare.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | BearHttpsClientDnsProvider privateBearHttpsProviders[] = { 10 | {.hostname= "dns.google.com",.route="/resolve",.ip = "8.8.8.8",.port=443}, 11 | {.hostname= "dns.nextdns.io",.route="/dns-query",.ip = "217.146.9.93",.port=443}, 12 | 13 | 14 | }; 15 | 16 | 17 | int privateBearHttpsProvidersSize = sizeof(privateBearHttpsProviders)/sizeof(BearHttpsClientDnsProvider); 18 | 19 | 20 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/fdefine.namespace.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | BearHttpsNamespace newBearHttpsNamespace(){ 10 | BearHttpsNamespace self = {0}; 11 | self.REFERENCE = BEARSSL_HTTPS_REFERENCE; 12 | self.GET_OWNERSHIP = BEARSSL_HTTPS_GET_OWNERSHIP; 13 | self.COPY = BEARSSL_HTTPS_COPY; 14 | self.response = newBearHttpsResponseNamespace(); 15 | self.request= newBearHttpsRequestNamespace(); 16 | return self; 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/src_dependencies/dep_declareB.dependencies.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declare.h" 4 | //silver_chain_scope_end 5 | 6 | #if !defined(__EMSCRIPTEN__) 7 | 8 | 9 | 10 | 11 | #if !defined(UniversalSocket_dep) 12 | #include "../../../dependencies/UniversalSocket.h" 13 | #define BEARSSL_HTTPS_UNIVERSAL_SOCKET_DECLARATED 14 | #endif 15 | 16 | #if !defined(BR_BEARSSL_H__) 17 | #define BR_ENABLE_INTRINSICS 1 18 | #include "../../../dependencies/BearSSLSingleUnit.h" 19 | #define BEARSSL_HTTPS_BEARSSL_DECLARATED 20 | #endif 21 | 22 | 23 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_header_value_by_key.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_header_value_by_key 2 | ```c 3 | const char* BearHttpsResponse_get_header_value_by_key(BearHttpsResponse *self, const char *key); 4 | ``` 5 | ### Description 6 | Gets the value of a response header by its key (name). Header key matching is case-sensitive. **Important: Always check for NULL before using the return value.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | - `key`: The header key to search for (e.g., "Content-Type", "Set-Cookie") 11 | 12 | ### Returns 13 | A pointer to the header value string, or `NULL` if the key is not found or the response has an error. 14 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_set_chunk_header_read_props.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_set_chunk_header_read_props 2 | ```c 3 | void BearHttpsRequest_set_chunk_header_read_props(BearHttpsRequest *self, int chunk_size, int max_chunk_size); 4 | ``` 5 | ### Description 6 | Configures the chunk reading properties for HTTP response headers. This controls how the client reads response data in chunks, which can be useful for memory management and large responses. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `chunk_size`: The size of each chunk to read 11 | - `max_chunk_size`: The maximum chunk size allowed 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/config/macros.sizes.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | #define BEARSSL_HEADER_CHUNK 200 9 | #define BEARSSL_HEADER_REALLOC_FACTOR 3 10 | #define BEARSSL_MAX_REDIRECTIONS 10 11 | #define BEARSSL_BODY_CHUNK_SIZE 1024 12 | #define BEARSSL_BODY_REALLOC_FACTOR 1.5 13 | #define BEARSSL_DNS_CACHE_HOST_SIZE 1000 14 | #define BEARSSL_DNS_CACHE_IP_SIZE 200 15 | #define BEARSSL_DNS_CACHE_SIZE 100 16 | #define BEARSSL_TIMEOUT 2000 17 | #define BEARSSL_MILISECONDS_MULTIPLIER 1000 18 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_create_cJSONPayloadArray.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_create_cJSONPayloadArray 2 | ```c 3 | const cJSON * BearHttpsRequest_create_cJSONPayloadArray(BearHttpsRequest *self); 4 | ``` 5 | ### Description 6 | Creates a new cJSON array and stores it internally in the request for later use as the request body. This is useful for building JSON array payloads programmatically. The returned JSON array is managed by the request and will be freed automatically. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | 11 | ### Returns 12 | A pointer to the newly created cJSON array, or `NULL` if creation fails. The returned pointer is const and should not be freed manually. 13 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_create_cJSONPayloadObject.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_create_cJSONPayloadObject 2 | ```c 3 | const cJSON * BearHttpsRequest_create_cJSONPayloadObject(BearHttpsRequest *self); 4 | ``` 5 | ### Description 6 | Creates a new cJSON object and stores it internally in the request for later use as the request body. This is useful for building JSON payloads programmatically. The returned JSON object is managed by the request and will be freed automatically. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | 11 | ### Returns 12 | A pointer to the newly created cJSON object, or `NULL` if creation fails. The returned pointer is const and should not be freed manually. 13 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/src_dependencies/dep_defineB.dependencies.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_define.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | #if !defined(BEARSSL_HTTPS_MOCK_UNIVERSAL_SOCKET_DEFINE) && defined(BEARSSL_HTTPS_UNIVERSAL_SOCKET_DECLARATED) 11 | #include "../../../dependencies/UniversalSocket.c" 12 | #endif 13 | 14 | #if !defined(BEARSSL_HTTPS_MOCK_BEARSSL_DEFINE) && defined(BEARSSL_HTTPS_BEARSSL_DECLARATED) 15 | #include "../../../dependencies/BearSSLTrustAnchors.c" 16 | #include "../../../dependencies/BearSSLSingleUnit.c" 17 | #endif 18 | 19 | 20 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_add_header_fmt.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_add_header_fmt 2 | ```c 3 | void BearHttpsRequest_add_header_fmt(BearHttpsRequest *self, const char *key, const char *format, ...); 4 | ``` 5 | ### Description 6 | Adds a header to the HTTP request using printf-style formatting for the value. This is useful when you need to construct header values dynamically. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `key`: The header key/name (e.g., "Content-Length", "Authorization") 11 | - `format`: Printf-style format string for the header value 12 | - `...`: Variable arguments matching the format string 13 | 14 | ### Returns 15 | This function does not return a value. 16 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_set_known_ips.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_set_known_ips 2 | ```c 3 | void BearHttpsRequest_set_known_ips(BearHttpsRequest *self, const char *known_ips[], int known_ips_size); 4 | ``` 5 | ### Description 6 | Sets a list of known IP addresses for the request's hostname. This allows the client to bypass DNS resolution and connect directly to specific IP addresses, which can improve performance and reliability. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `known_ips`: Array of IP address strings (e.g., ["93.184.216.34", "93.184.216.35"]) 11 | - `known_ips_size`: Number of IP addresses in the array 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_set_dns_providers.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_set_dns_providers 2 | ```c 3 | void BearHttpsRequest_set_dns_providers(BearHttpsRequest *self, BearHttpsClientDnsProvider *dns_providers, int total_dns_providers); 4 | ``` 5 | ### Description 6 | Sets custom DNS providers for resolving hostnames. This allows the client to use DNS-over-HTTPS providers instead of the system's default DNS resolver. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `dns_providers`: Array of `BearHttpsClientDnsProvider` structures containing DNS provider configurations 11 | - `total_dns_providers`: Number of DNS providers in the array 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_header_key_by_index.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_header_key_by_index 2 | ```c 3 | const char* BearHttpsResponse_get_header_key_by_index(BearHttpsResponse *self, int index); 4 | ``` 5 | ### Description 6 | Gets the key (name) of a response header by its index position. Use this function with `BearHttpsResponse_get_headers_size()` to iterate through all headers. **Important: Always check for NULL before using the return value.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | - `index`: Zero-based index of the header (0 to headers_size - 1) 11 | 12 | ### Returns 13 | A pointer to the header key string, or `NULL` if the index is invalid or the response has an error. 14 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_read_body_json.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_read_body_json 2 | ```c 3 | const cJSON * BearHttpsResponse_read_body_json(BearHttpsResponse *self); 4 | ``` 5 | ### Description 6 | Reads and parses the response body as a JSON object. This automatically handles JSON parsing and returns a cJSON object that can be used to access JSON data. **Important: Always check for NULL before using the return value. The returned cJSON is const and should not be freed manually.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | 11 | ### Returns 12 | A pointer to a const cJSON object representing the parsed JSON, or `NULL` if the body is not valid JSON, is empty, or the response has an error. 13 | -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/request/typesC.request.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.typesB.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | 7 | 8 | typedef struct BearHttpsRequest{ 9 | char *url; 10 | bool route_owner; 11 | char method[30]; 12 | private_BearHttpsHeaders *headers; 13 | short body_type; 14 | union{ 15 | private_BearHttpsBodyRawRequest body_raw; 16 | private_BearHttpsBodyRequestFile body_file; 17 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 18 | private_BearHttpsBodyJsonRequest body_json; 19 | #endif 20 | }; 21 | 22 | }BearHttpsRequest ; 23 | 24 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_header_value_by_index.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_header_value_by_index 2 | ```c 3 | const char* BearHttpsResponse_get_header_value_by_index(BearHttpsResponse *self, int index); 4 | ``` 5 | ### Description 6 | Gets the value of a response header by its index position. Use this function with `BearHttpsResponse_get_headers_size()` to iterate through all headers. **Important: Always check for NULL before using the return value.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | - `index`: Zero-based index of the header (0 to headers_size - 1) 11 | 12 | ### Returns 13 | A pointer to the header value string, or `NULL` if the index is invalid or the response has an error. 14 | -------------------------------------------------------------------------------- /src/ALL/request/request/types.body_types.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.macros.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | typedef struct private_BearHttpsBodyRawRequest{ 8 | unsigned char *value; 9 | long size; 10 | bool onwer; 11 | }private_BearHttpsBodyRawRequest; 12 | 13 | 14 | typedef struct private_BearHttpsBodyRequestFile{ 15 | char *path; 16 | char content_type[100]; 17 | bool onwer; 18 | }private_BearHttpsBodyRequestFile; 19 | 20 | 21 | 22 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 23 | 24 | typedef struct private_BearHttpsBodyJsonRequest{ 25 | cJSON *json; 26 | bool onwer; 27 | }private_BearHttpsBodyJsonRequest; 28 | #endif 29 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_set_trusted_anchors.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_set_trusted_anchors 2 | ```c 3 | void BearHttpsRequest_set_trusted_anchors(BearHttpsRequest *self, br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size); 4 | ``` 5 | ### Description 6 | Sets custom trusted anchors (root certificates) for SSL/TLS certificate validation. This allows the client to use a custom set of trusted Certificate Authorities instead of the default ones. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `trust_anchors`: Array of `br_x509_trust_anchor` structures containing trusted certificate authorities 11 | - `trusted_anchors_size`: Number of trust anchors in the array 12 | 13 | ### Returns 14 | This function does not return a value. 15 | -------------------------------------------------------------------------------- /src/ALL/src_dependencies/dep_declare.dependencies.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.tests.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifndef BearsslHttps_allocate 13 | #define BearsslHttps_allocate malloc 14 | #endif 15 | 16 | #ifndef BearsslHttps_reallocate 17 | #define BearsslHttps_reallocate realloc 18 | #endif 19 | 20 | #ifndef BearsslHttps_free 21 | #define BearsslHttps_free free 22 | #endif 23 | 24 | 25 | #if !defined(cJSON__h) && !defined(BEARSSL_HTTPS_MOCK_CJSON) 26 | #include "../../../dependencies/cJSON.h" 27 | #define BEARSSL_HTTPS_CJSON_DECLARATED 28 | #endif 29 | -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/request/fdefine.request.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | 7 | BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url,short url_ownership_mode){ 8 | c2wasm_start(); 9 | 10 | BearHttpsRequest *self = (BearHttpsRequest *)malloc(sizeof(BearHttpsRequest)); 11 | *self = (BearHttpsRequest){0}; 12 | BearHttpsRequest_set_url_with_ownership_config(self,url,url_ownership_mode); 13 | self->headers = private_newBearHttpsHeaders(); 14 | self->body_type =PRIVATE_BEARSSL_NO_BODY; 15 | private_BearsslHttps_strcpy(self->method,"GET"); 16 | return self; 17 | } 18 | #endif -------------------------------------------------------------------------------- /docs/public_api/BearHttpsResponse_get_header_value_by_sanitized_key.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsResponse_get_header_value_by_sanitized_key 2 | ```c 3 | const char* BearHttpsResponse_get_header_value_by_sanitized_key(BearHttpsResponse *self, const char *key); 4 | ``` 5 | ### Description 6 | Gets the value of a response header by its key (name) using case-insensitive matching. This function normalizes the key for better compatibility with different server implementations. **Important: Always check for NULL before using the return value.** 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsResponse` object 10 | - `key`: The header key to search for (case-insensitive, e.g., "content-type", "Content-Type") 11 | 12 | ### Returns 13 | A pointer to the header value string, or `NULL` if the key is not found or the response has an error. 14 | -------------------------------------------------------------------------------- /examples/example_simple.c: -------------------------------------------------------------------------------- 1 | #include "BearHttpsClientOne.c" 2 | 3 | int main(){ 4 | BearHttpsRequest *request = newBearHttpsRequest("https://example.com"); 5 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 6 | if(BearHttpsResponse_error(response)){ 7 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 8 | BearHttpsRequest_free(request); 9 | BearHttpsResponse_free(response); 10 | return 1; 11 | } 12 | 13 | const char *body = BearHttpsResponse_read_body_str(response); 14 | if(BearHttpsResponse_error(response)){ 15 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 16 | BearHttpsRequest_free(request); 17 | BearHttpsResponse_free(response); 18 | return 1; 19 | } 20 | 21 | printf("Body: %s\n",body); 22 | BearHttpsRequest_free(request); 23 | BearHttpsResponse_free(response); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_cJSON_with_ownership_control.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_cJSON_with_ownership_control 2 | ```c 3 | void BearHttpsRequest_send_cJSON_with_ownership_control(BearHttpsRequest *self, cJSON *json, short ownership_mode); 4 | ``` 5 | ### Description 6 | Sends a cJSON object as the request body with control over how the JSON object is handled by the library. The JSON is automatically serialized to a string before sending. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `json`: Pointer to the cJSON object to send 11 | - `ownership_mode`: Controls how the JSON object is handled. Can be: 12 | - `BEARSSL_HTTPS_REFERENCE` (0): Keeps the reference (caller must ensure JSON remains valid) 13 | - `BEARSSL_HTTPS_GET_OWNERSHIP` (1): Takes ownership and frees the JSON when not needed 14 | - `BEARSSL_HTTPS_COPY` (2): Makes a copy of the JSON 15 | 16 | ### Returns 17 | This function does not return a value. 18 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_body_str_with_ownership_control.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_body_str_with_ownership_control 2 | ```c 3 | void BearHttpsRequest_send_body_str_with_ownership_control(BearHttpsRequest *self, char *content, short ownership_mode); 4 | ``` 5 | ### Description 6 | Sends a string as the request body with control over how the content is handled by the library. This is useful for sending text data, JSON strings, or other string-based content. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `content`: Pointer to the null-terminated string to send 11 | - `ownership_mode`: Controls how the content is handled. Can be: 12 | - `BEARSSL_HTTPS_REFERENCE` (0): Keeps the reference (caller must ensure content remains valid) 13 | - `BEARSSL_HTTPS_GET_OWNERSHIP` (1): Takes ownership and frees the content when not needed 14 | - `BEARSSL_HTTPS_COPY` (2): Makes a copy of the content 15 | 16 | ### Returns 17 | This function does not return a value. 18 | -------------------------------------------------------------------------------- /docs/public_api/BearHttpsRequest_send_any_with_ownership_control.md: -------------------------------------------------------------------------------- 1 | ### Function: BearHttpsRequest_send_any_with_ownership_control 2 | ```c 3 | void BearHttpsRequest_send_any_with_ownership_control(BearHttpsRequest *self, unsigned char *content, long size, short ownership_mode); 4 | ``` 5 | ### Description 6 | Sends binary data as the request body with control over how the content is handled by the library. This function allows sending any type of binary data. 7 | 8 | ### Parameters 9 | - `self`: Pointer to the `BearHttpsRequest` object 10 | - `content`: Pointer to the binary data to send 11 | - `size`: Size of the data in bytes 12 | - `ownership_mode`: Controls how the content is handled. Can be: 13 | - `BEARSSL_HTTPS_REFERENCE` (0): Keeps the reference (caller must ensure content remains valid) 14 | - `BEARSSL_HTTPS_GET_OWNERSHIP` (1): Takes ownership and frees the content when not needed 15 | - `BEARSSL_HTTPS_COPY` (2): Makes a copy of the content 16 | 17 | ### Returns 18 | This function does not return a value. 19 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/network/fdefine.sock.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | static int private_BearHttps_sock_read(void *ctx, unsigned char *buf, size_t len) 9 | { 10 | for (;;) { 11 | ssize_t read_len; 12 | 13 | read_len = Universal_recv(*(int*)ctx, buf, len,0); 14 | if (read_len <= 0) { 15 | if (read_len < 0 && errno == EINTR) { 16 | continue; 17 | } 18 | return -1; 19 | } 20 | return (int)read_len; 21 | } 22 | } 23 | 24 | 25 | static int private_BearHttps_sock_write(void *ctx, const unsigned char *buf, size_t len) 26 | { 27 | for (;;) { 28 | ssize_t write_len; 29 | write_len = Universal_send(*(int *)ctx, buf, len,0); 30 | if (write_len <= 0) { 31 | if (write_len < 0 && errno == EINTR) { 32 | continue; 33 | } 34 | return -1; 35 | } 36 | return (int)write_len; 37 | } 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /docs/public_api/newBearHttpsRequest_with_url_ownership_config.md: -------------------------------------------------------------------------------- 1 | ### Function: newBearHttpsRequest_with_url_ownership_config 2 | ```c 3 | BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url, short url_ownership_mode); 4 | ``` 5 | ### Description 6 | Creates a new `BearHttpsRequest` object with the specified URL and ownership mode. This function allows control over how the URL string is handled by the library. 7 | 8 | ### Parameters 9 | - `url`: A string representing the URL for the request. This should be a valid HTTPS URL. 10 | - `url_ownership_mode`: Controls how the URL string is handled. Can be: 11 | - `BEARSSL_HTTPS_REFERENCE` (0): Keeps the reference of the URL (caller must ensure URL remains valid) 12 | - `BEARSSL_HTTPS_GET_OWNERSHIP` (1): Takes ownership of the URL and frees it when not needed 13 | - `BEARSSL_HTTPS_COPY` (2): Makes a copy of the URL 14 | 15 | ### Returns 16 | A pointer to the newly created `BearHttpsRequest` object. If the URL is invalid or memory allocation fails, it returns `NULL`. 17 | -------------------------------------------------------------------------------- /src/_WIN32/fdefine.socket.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if defined(_WIN32) 6 | 7 | static int private_BearHttps_socket_set_nonblocking(int sockfd) { 8 | u_long mode = 1; 9 | return ioctlsocket(sockfd, FIONBIO, &mode); 10 | } 11 | 12 | static int private_BearHttps_socket_set_blocking(int sockfd) { 13 | u_long mode = 0; 14 | return ioctlsocket(sockfd, FIONBIO, &mode); 15 | } 16 | 17 | static int private_BearHttps_socket_check_connect_error(int sockfd) { 18 | int error = 0; 19 | socklen_t len = sizeof(error); 20 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0 || error != 0) { 21 | return -1; 22 | } 23 | return 0; 24 | } 25 | 26 | static int private_BearHttps_socket_check_connect_in_progress(int ret) { 27 | if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK) { 28 | return -1; 29 | } 30 | return 0; 31 | } 32 | 33 | #endif -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/response/fdefine.response.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | 7 | BearHttpsResponse *private_newBearHttpsResponse(){ 8 | BearHttpsResponse *self = (BearHttpsResponse *)malloc(sizeof(BearHttpsResponse)); 9 | *self = (BearHttpsResponse){0}; 10 | self->headers = private_newBearHttpsHeaders(); 11 | 12 | return self; 13 | } 14 | 15 | 16 | void BearHttpsResponse_free(BearHttpsResponse *self){ 17 | if(!self){ 18 | return; 19 | } 20 | private_BearHttpsHeaders_free(self->headers); 21 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 22 | if(self->json_body){ 23 | cJSON_Delete(self->json_body); 24 | } 25 | #endif 26 | if(self->body){ 27 | free(self->body); 28 | } 29 | if(self->error_msg){ 30 | free(self->error_msg); 31 | } 32 | 33 | free(self); 34 | 35 | } 36 | 37 | 38 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | server 3 | teste.lua 4 | *.d 5 | fdeclare.all.h 6 | saida.jpg 7 | doTheWorld.h 8 | basic.png 9 | .idea 10 | teste* 11 | web_cache 12 | c2wasm.c 13 | dtw.c 14 | vgcore* 15 | BearSSL 16 | test.js 17 | test.wasm 18 | dependencies 19 | BearHttpsClientOne.c 20 | prompt.md 21 | darwintypes.lua 22 | # Object files 23 | .vscode 24 | src/imports 25 | release 26 | teste.c 27 | micro_client.c 28 | test.c 29 | *.o 30 | *.ko 31 | *.obj 32 | *.elf 33 | cliente.c 34 | CWebStudioOne.c 35 | # Linker output 36 | *.ilk 37 | *.map 38 | *.exp 39 | 40 | # Precompiled Headers 41 | *.gch 42 | *.pch 43 | 44 | # Libraries 45 | *.lib 46 | *.a 47 | *.la 48 | *.lo 49 | 50 | # Shared objects (inc. Windows DLLs) 51 | *.dll 52 | *.so 53 | *.so.* 54 | *.dylib 55 | 56 | # Executables 57 | *.exe 58 | *.out 59 | *.app 60 | *.i*86 61 | *.x86_64 62 | *.hex 63 | 64 | # Debug files 65 | *.dSYM/ 66 | *.su 67 | *.idb 68 | *.pdb 69 | 70 | # Kernel Module Compile Results 71 | *.mod* 72 | *.cmd 73 | .tmp_versions/ 74 | modules.order 75 | Module.symvers 76 | Mkfile.old 77 | dkms.conf 78 | ./dep.LuaCEmbed.h 79 | -------------------------------------------------------------------------------- /src/ALL/fdefine.ownership.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | 9 | void private_BearsslHttps_free_considering_ownership(void **value,bool *owner){ 10 | if(*owner){ 11 | BearsslHttps_free(*value); 12 | } 13 | *owner = false; 14 | *value = NULL; 15 | } 16 | 17 | 18 | void private_BearsslHttps_set_str_considering_ownership( 19 | char **dest, 20 | char *value, 21 | bool *owner, 22 | short ownership_mode 23 | ){ 24 | private_BearsslHttps_free_considering_ownership((void**)dest,owner); 25 | 26 | if(ownership_mode == BEARSSL_HTTPS_COPY){ 27 | *dest = private_BearsslHttps_strdup(value); 28 | *owner = true; 29 | } 30 | 31 | if(ownership_mode == BEARSSL_HTTPS_GET_OWNERSHIP){ 32 | *dest = value; 33 | *owner = true; 34 | } 35 | 36 | if(ownership_mode == BEARSSL_HTTPS_REFERENCE){ 37 | *dest = value; 38 | *owner = false; 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 OUI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/__unix__&&!__EMSCRIPTEN__/network/fdefine.socket.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if (defined(__unix__) || defined(__APPLE__)) && !defined(__EMSCRIPTEN__) 6 | 7 | static int private_BearHttps_socket_set_nonblocking(int sockfd) { 8 | int flags = fcntl(sockfd, F_GETFL, 0); 9 | return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); 10 | } 11 | 12 | static int private_BearHttps_socket_set_blocking(int sockfd) { 13 | int flags = fcntl(sockfd, F_GETFL, 0); 14 | return fcntl(sockfd, F_SETFL, flags & ~O_NONBLOCK); 15 | } 16 | 17 | static int private_BearHttps_socket_check_connect_error(int sockfd) { 18 | int error = 0; 19 | socklen_t len = sizeof(error); 20 | if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error != 0) { 21 | return -1; 22 | } 23 | return 0; 24 | } 25 | 26 | static int private_BearHttps_socket_check_connect_in_progress(int ret) { 27 | if (ret < 0 && errno != EINPROGRESS) { 28 | return -1; 29 | } 30 | return 0; 31 | } 32 | 33 | #endif -------------------------------------------------------------------------------- /src/ALL/config/macros.errors.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_declareB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | #define BEARSSL_HTTPS_FAILT_TO_START_UNISOCKET 1 9 | #define BEARSSL_HTTPS_INVALID_URL 2 10 | #define BEARSSL_HTTPS_IMPOSSIBLE_TO_OPEN_FILE 3 11 | #define BEARSSL_HTTPS_MUST_BE_IPV4 4 12 | #define BEARSSL_HTTPS_BODY_ITS_BINARY 5 13 | #define BEARSSL_HTTPS_IMPOSSIBLE_TO_READ_BODY 6 14 | #define BEARSSL_HTTPS_BODY_SIZE_ITS_BIGGER_THAN_LIMIT 7 15 | #define BEARSSL_HTTPS_ALOCATION_FAILED 8 16 | #define BEARSSL_HTTPS_BODY_ITS_NOT_A_VALID_JSON 9 17 | #define BEARSSL_HTTPS_FAILT_TO_CREATE_DNS_REQUEST 10 18 | #define BEARSSL_HTTPS_NO_DNS_PROVIDED 11 19 | #define BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET 12 20 | #define BEARSSL_HTTPS_INVALID_IPV4 12 21 | #define BEARSSL_HTTPS_FAILT_TO_CONNECT 13 22 | #define BEARSSL_HTTPS_UNKNOW_ERROR 14 23 | #define BEARSSL_HTTPS_INVALID_READ_CODE 15 24 | #define BEARSSL_HTTPS_INVALID_HTTP_RESPONSE 16 25 | #define BEARSSL_HTTPS_IMPOSSIBLE_TO_SEND_DATA 17 26 | #define BEARSSL_HTTPS_ERROR_FLUSHING 18 27 | #define BEARSSL_HTTPS_INVALID_HTTP_PROTOCOL 19 28 | #define BEARSSL_HTTPS_ERROR_READING_CHUNK 20 -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/response/typesD.response.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.typesC.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | typedef struct BearHttpsResponse{ 11 | int connection_file_descriptor; 12 | bool is_https; 13 | br_sslio_context ssl_io; 14 | br_ssl_client_context ssl_client; 15 | unsigned char bear_buffer[BR_SSL_BUFSIZE_BIDI]; 16 | br_x509_minimal_context certification_context; 17 | long max_body_size; 18 | unsigned char *raw_content; 19 | int error_code; 20 | private_BearHttpsHeaders *headers; 21 | long respnse_content_lenght; 22 | long body_start_index; 23 | unsigned char *body; 24 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 25 | cJSON *json_body; 26 | #endif 27 | 28 | long body_size; 29 | long body_readded_size; 30 | short body_read_mode; 31 | long extra_body_remaning_to_send; 32 | bool body_completed_read; 33 | int body_chunk_size; 34 | double body_realloc_factor; 35 | 36 | char *error_msg; 37 | int status_code; 38 | //http1.1 vars 39 | short http1_state; 40 | long http1_reaming_to_read; 41 | 42 | }BearHttpsResponse ; 43 | 44 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/request/typesC.request.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.typesB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | 11 | 12 | typedef struct BearHttpsRequest{ 13 | char *url; 14 | bool route_owner; 15 | int max_redirections; 16 | const char *custom_bear_dns; 17 | const char **known_ips; 18 | int known_ips_size; 19 | short http_protocol; 20 | BearHttpsClientDnsProvider *dns_providers; 21 | int total_dns_providers; 22 | bool must_be_ipv4; 23 | 24 | private_BearHttpsHeaders *headers; 25 | char method[30]; 26 | int port; 27 | 28 | int header_chunk_read_size; 29 | int header_chunk_reallocator_factor; 30 | 31 | int response_max_headers_size; 32 | 33 | br_x509_trust_anchor *trust_anchors; 34 | size_t trusted_anchors_size; 35 | long connection_timeout; 36 | 37 | 38 | short body_type; 39 | union{ 40 | private_BearHttpsBodyRawRequest body_raw; 41 | private_BearHttpsBodyRequestFile body_file; 42 | 43 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 44 | 45 | private_BearHttpsBodyJsonRequest body_json; 46 | #endif 47 | }; 48 | 49 | }BearHttpsRequest ; 50 | 51 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/fdefine.read_write.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | int private_BearHttpsResponse_write(BearHttpsResponse *self,unsigned char *bufer,long size){ 11 | if(BearHttpsResponse_error(self)){ 12 | return -1; 13 | } 14 | 15 | if(self->is_https){ 16 | return br_sslio_write_all(&self->ssl_io, bufer, size); 17 | } 18 | long sended = 0; 19 | while(sended < size){ 20 | long sended_now = Universal_send(self->connection_file_descriptor, bufer+sended, size-sended,0); 21 | if(sended_now < 0){ 22 | BearHttpsResponse_set_error(self,"error sending data",BEARSSL_HTTPS_IMPOSSIBLE_TO_SEND_DATA); 23 | return sended_now; 24 | } 25 | sended += sended_now; 26 | } 27 | return sended; 28 | } 29 | 30 | int private_BearHttpsResponse_recv(BearHttpsResponse *self,unsigned char *buffer,long size){ 31 | 32 | if(BearHttpsResponse_error(self)){ 33 | return -1; 34 | } 35 | if(self->is_https){ 36 | return br_sslio_read(&self->ssl_io, buffer, size); 37 | } 38 | return Universal_recv(self->connection_file_descriptor, buffer, size,0); 39 | 40 | } 41 | 42 | #endif -------------------------------------------------------------------------------- /src/ALL/headers/fdefine.headers.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | private_BearHttpsHeaders *private_newBearHttpsHeaders(){ 8 | private_BearHttpsHeaders *self = (private_BearHttpsHeaders *)BearsslHttps_allocate(sizeof(private_BearHttpsHeaders)); 9 | *self = (private_BearHttpsHeaders){0}; 10 | self->keyvals = (private_BearHttpsKeyVal **)BearsslHttps_allocate(0); 11 | return self; 12 | } 13 | 14 | void private_BearHttpsHeaders_add_keyval(private_BearHttpsHeaders *self, private_BearHttpsKeyVal *keyval){ 15 | self->keyvals = (private_BearHttpsKeyVal **)BearsslHttps_reallocate( 16 | self->keyvals, 17 | sizeof(private_BearHttpsKeyVal*) * (self->size + 1) 18 | 19 | ); 20 | self->keyvals[self->size] = keyval; 21 | self->size++; 22 | } 23 | 24 | void private_BearHttpsHeaders_free(private_BearHttpsHeaders *self){ 25 | for(int i = 0; i < self->size; i++){ 26 | private_BearHttpsKeyVal_free(self->keyvals[i]); 27 | } 28 | free(self->keyvals); 29 | free(self); 30 | } 31 | 32 | private_BearHttpsKeyVal * private_BearHttpsHeaders_get_key_val_by_index(private_BearHttpsHeaders *self,int index){ 33 | if(self->size <= index){ 34 | return NULL; 35 | } 36 | return self->keyvals[index]; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/ALL/keyval/fdefine.keyval.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | private_BearHttpsKeyVal *private_newBearHttpsKeyVal(){ 9 | private_BearHttpsKeyVal *self = (private_BearHttpsKeyVal *)BearsslHttps_allocate(sizeof(private_BearHttpsKeyVal)); 10 | *self = (private_BearHttpsKeyVal){0}; 11 | self->key = NULL; 12 | self->value = NULL; 13 | self->key_owner =false; 14 | self->value_owner = false; 15 | return self; 16 | } 17 | 18 | void private_BearHttpsKeyVal_set_key(private_BearHttpsKeyVal *self, char *key,short key_onwership_mode){ 19 | private_BearsslHttps_free_considering_ownership((void **)&self->key,&self->key_owner); 20 | private_BearsslHttps_set_str_considering_ownership(&self->key,key,&self->key_owner, key_onwership_mode); 21 | } 22 | 23 | void private_BearHttpsKeyVal_set_value(private_BearHttpsKeyVal *self, char *value,short value_onwership_mode){ 24 | private_BearsslHttps_free_considering_ownership((void **)&self->value,&self->value_owner); 25 | private_BearsslHttps_set_str_considering_ownership(&self->value,value,&self->value_owner,value_onwership_mode); 26 | } 27 | 28 | void private_BearHttpsKeyVal_free(private_BearHttpsKeyVal *self){ 29 | private_BearsslHttps_free_considering_ownership((void **)&self->key,&self->key_owner); 30 | private_BearsslHttps_free_considering_ownership((void **)&self->value,&self->value_owner); 31 | free(self); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/ALL/response/fdefine.body_read.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | const char *BearHttpsResponse_read_body_str(BearHttpsResponse *self){ 7 | 8 | if(BearHttpsResponse_error(self)){ 9 | return NULL; 10 | } 11 | const unsigned char *body = BearHttpsResponse_read_body(self); 12 | if(body == NULL){ 13 | return NULL; 14 | } 15 | 16 | //check if its a binary 17 | for(int i = 0; i < self->body_size; i++){ 18 | if(body[i] == '\0'){ 19 | BearHttpsResponse_set_error(self,"body is binary",BEARSSL_HTTPS_BODY_ITS_BINARY); 20 | BearsslHttps_free(self->body); 21 | self->body = NULL; 22 | return NULL; 23 | } 24 | } 25 | return (const char *)body; 26 | } 27 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 28 | const cJSON * BearHttpsResponse_read_body_json(BearHttpsResponse *self){ 29 | if(BearHttpsResponse_error(self)){ 30 | return NULL; 31 | } 32 | const char *body = BearHttpsResponse_read_body_str(self); 33 | if(body == NULL){ 34 | return NULL; 35 | } 36 | 37 | self->json_body = cJSON_Parse(body); 38 | free((void *)body); 39 | self->body = NULL; 40 | 41 | if(self->json_body == NULL){ 42 | BearHttpsResponse_set_error(self,"error parsing json",BEARSSL_HTTPS_BODY_ITS_NOT_A_VALID_JSON); 43 | return NULL; 44 | } 45 | return self->json_body; 46 | } 47 | #endif -------------------------------------------------------------------------------- /src/ALL/fdefine.extra.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | bool private_BearHttps_is_sanitize_key(const char *key,const char *sanitized,int sanitized_size){ 8 | long key_size = private_BearsslHttps_strlen(key); 9 | int comparation_size = 0; 10 | for(int i=0; i < key_size;i++){ 11 | char current = key[i]; 12 | if(current == ' ' || current == '\t' || current == '\n' || current == '\r'|| current == '-'|| current == '_'){ 13 | continue; 14 | } 15 | if(comparation_size > sanitized_size){ 16 | return false; 17 | } 18 | char current_lower = private_BearsslHttps_parse_char_to_lower(current); 19 | char sanitized_lower = private_BearsslHttps_parse_char_to_lower(sanitized[comparation_size]); 20 | 21 | if(current_lower != sanitized_lower){ 22 | return false; 23 | } 24 | comparation_size++; 25 | } 26 | if(comparation_size != sanitized_size){ 27 | return false; 28 | } 29 | return true; 30 | } 31 | 32 | char * private_BearHttps_format_vaarg(const char *expresion, va_list args){ 33 | 34 | va_list args_copy; 35 | va_copy(args_copy, args); 36 | long required_size = vsnprintf(NULL, 0,expresion,args_copy); 37 | va_end(args_copy); 38 | char *buffer = (char*)malloc(sizeof(char) * required_size + 2); 39 | vsnprintf(buffer,sizeof (char) * required_size+1,expresion,args); 40 | return buffer; 41 | } 42 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/response/fdefine.response.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | BearHttpsResponseNamespace newBearHttpsResponseNamespace(){ 10 | BearHttpsResponseNamespace self = {0}; 11 | self.read_body_chunck = BearHttpsResponse_read_body_chunck; 12 | self.read_body = BearHttpsResponse_read_body; 13 | self.read_body_str = BearHttpsResponse_read_body_str; 14 | self.get_status_code = BearHttpsResponse_get_status_code; 15 | self.get_body_size = BearHttpsResponse_get_body_size; 16 | self.get_headers_size = BearHttpsResponse_get_headers_size; 17 | self.get_header_value_by_index = BearHttpsResponse_get_header_value_by_index; 18 | self.get_header_value_by_key = BearHttpsResponse_get_header_value_by_key; 19 | self.get_header_key_by_index = BearHttpsResponse_get_header_key_by_index; 20 | self.get_header_value_by_sanitized_key = BearHttpsResponse_get_header_value_by_sanitized_key; 21 | self.set_max_body_size = BearHttpsResponse_set_max_body_size; 22 | self.set_body_read_props = BearHttpsResponse_set_body_read_props; 23 | self.error = BearHttpsResponse_error; 24 | self.get_error_msg = BearHttpsResponse_get_error_msg; 25 | self.get_error_code = BearHttpsResponse_get_error_code; 26 | self.free = BearHttpsResponse_free; 27 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 28 | self.read_body_json = BearHttpsResponse_read_body_json; 29 | #endif 30 | return self; 31 | 32 | } 33 | #endif -------------------------------------------------------------------------------- /darwindeps.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "gitrelease", 4 | "repo": "OUIsolutions/BearSslSingle-Unit", 5 | "file": "BearSSLSingleUnit.h", 6 | "tag": "0.0.3", 7 | "dest": "dependencies/BearSSLSingleUnit.h" 8 | }, 9 | { 10 | "type": "gitrelease", 11 | "repo": "OUIsolutions/BearSslSingle-Unit", 12 | "file": "BearSSLSingleUnit.c", 13 | "tag": "0.0.3", 14 | "dest": "dependencies/BearSSLSingleUnit.c" 15 | }, 16 | { 17 | "type": "url", 18 | "url": "https://raw.githubusercontent.com/DaveGamble/cJSON/refs/tags/v1.7.18/cJSON.c", 19 | "dest": "dependencies/cJSON.c" 20 | }, 21 | { 22 | "type": "url", 23 | "url": "https://raw.githubusercontent.com/DaveGamble/cJSON/refs/tags/v1.7.18/cJSON.h", 24 | "dest": "dependencies/cJSON.h" 25 | }, 26 | { 27 | "type": "gitrelease", 28 | "repo": "OUIsolutions/C2Wasm", 29 | "file": "c2wasm.c", 30 | "tag": "0.10.0", 31 | "dest": "dependencies/c2wasm.c" 32 | }, 33 | { 34 | "type": "gitrelease", 35 | "repo": "SamuelHenriqueDeMoraisVitrio/UniversalSocket", 36 | "file": "UniversalSocket.c", 37 | "tag": "v0.3.0", 38 | "dest": "dependencies/UniversalSocket.c" 39 | }, 40 | { 41 | "type": "gitrelease", 42 | "repo": "SamuelHenriqueDeMoraisVitrio/UniversalSocket", 43 | "file": "UniversalSocket.h", 44 | "tag": "v0.3.0", 45 | "dest": "dependencies/UniversalSocket.h" 46 | }, 47 | { 48 | "type": "gitrelease", 49 | "repo": "OUIsolutions/BearSSLTrustedAnchors", 50 | "file": "BearSSLTrustAnchors.c", 51 | "tag": "2025-8-6", 52 | "dest": "dependencies/BearSSLTrustAnchors.c" 53 | } 54 | ] -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/response/typesE.response.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.typesD.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | typedef struct BearHttpsResponseNamespace{ 9 | 10 | 11 | int (*read_body_chunck)(BearHttpsResponse *self,unsigned char *bufer,long size); 12 | const unsigned char *(*read_body)(BearHttpsResponse *self); 13 | const char *(*read_body_str)(BearHttpsResponse *self); 14 | 15 | 16 | int (*get_status_code)(BearHttpsResponse*self); 17 | int (*get_body_size)(BearHttpsResponse*self); 18 | 19 | int (*get_headers_size)(BearHttpsResponse*self); 20 | 21 | const char* (*get_header_value_by_index)(BearHttpsResponse*self,int index); 22 | 23 | const char* (*get_header_value_by_key)(BearHttpsResponse*self,const char *key); 24 | 25 | const char* (*get_header_key_by_index)(BearHttpsResponse*self,int index); 26 | 27 | const char* (*get_header_value_by_sanitized_key)(BearHttpsResponse*self,const char *key); 28 | 29 | void (*set_max_body_size)(BearHttpsResponse*self,long size); 30 | void (*set_body_read_props)(BearHttpsResponse*self,int chunk_size,double realloc_factor); 31 | 32 | 33 | bool (*error)(BearHttpsResponse*self); 34 | 35 | const char* (*get_error_msg)(BearHttpsResponse*self); 36 | 37 | int (*get_error_code)(BearHttpsResponse*self); 38 | 39 | void (*free)(BearHttpsResponse *self); 40 | 41 | 42 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 43 | const cJSON * (*read_body_json)(BearHttpsResponse *self); 44 | #endif 45 | } BearHttpsResponseNamespace; 46 | 47 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/request/fdefine.request.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url,short url_ownership_mode){ 10 | BearHttpsRequest *self = (BearHttpsRequest *)malloc(sizeof(BearHttpsRequest)); 11 | *self = (BearHttpsRequest){0}; 12 | self->max_redirections = BEARSSL_MAX_REDIRECTIONS; 13 | BearHttpsRequest_set_url_with_ownership_config(self,url,url_ownership_mode); 14 | self->headers = private_newBearHttpsHeaders(); 15 | self->body_type =PRIVATE_BEARSSL_NO_BODY; 16 | self->http_protocol = BEARSSL_HTTPS_HTTP1_0; 17 | self->header_chunk_read_size = BEARSSL_HEADER_CHUNK; 18 | self->header_chunk_reallocator_factor = BEARSSL_HEADER_REALLOC_FACTOR; 19 | self->connection_timeout = BEARSSL_TIMEOUT; 20 | private_BearsslHttps_strcpy(self->method,"GET"); 21 | return self; 22 | } 23 | void BearHttpsRequest_set_http_protocol(BearHttpsRequest *self ,int http_protocol){ 24 | self->http_protocol = http_protocol; 25 | } 26 | 27 | void BearHttpsRequest_set_known_ips(BearHttpsRequest *self , const char *known_ips[],int known_ips_size){ 28 | self->known_ips = known_ips; 29 | self->known_ips_size = known_ips_size; 30 | } 31 | 32 | 33 | void BearHttpsRequest_set_max_redirections(BearHttpsRequest *self ,int max_redirections){ 34 | self->max_redirections = max_redirections; 35 | } 36 | 37 | void BearHttpsRequest_set_dns_providers(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers){ 38 | self->dns_providers= dns_providers; 39 | self->total_dns_providers = total_dns_proviers; 40 | } 41 | 42 | void BearHttpsRequest_set_chunk_header_read_props(BearHttpsRequest *self ,int chunk_size,int max_chunk_size){ 43 | self->header_chunk_read_size = chunk_size; 44 | self->header_chunk_reallocator_factor = max_chunk_size; 45 | } 46 | 47 | void BearHttpsRequest_set_trusted_anchors(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size){ 48 | self->trust_anchors = trust_anchors; 49 | self->trusted_anchors_size = trusted_anchors_size; 50 | } 51 | 52 | 53 | #endif -------------------------------------------------------------------------------- /src/ALL/fdefine.str.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | long private_BearsslHttps_strlen(const char *str){ 9 | long size = 0; 10 | while(str[size] != '\0'){ 11 | size++; 12 | } 13 | return size; 14 | } 15 | int private_BearsslHttp_strcmp(const char *str1,const char *str2){ 16 | long size1 = private_BearsslHttps_strlen(str1); 17 | long size2 = private_BearsslHttps_strlen(str2); 18 | if(size1 != size2){ 19 | return 1; 20 | } 21 | for(long i = 0; i < size1; i++){ 22 | if(str1[i] != str2[i]){ 23 | return 1; 24 | } 25 | } 26 | return 0; 27 | } 28 | 29 | 30 | bool private_BearsslHttps_startswith(const char *str,const char *prefix){ 31 | long size = private_BearsslHttps_strlen(prefix); 32 | for(long i = 0; i < size; i++){ 33 | if(str[i] != prefix[i]){ 34 | return false; 35 | } 36 | } 37 | return true; 38 | } 39 | char * private_BearsslHttps_strdup(const char *str){ 40 | long size = private_BearsslHttps_strlen(str); 41 | char *new_str = (char *)BearsslHttps_allocate(size+1); 42 | for(long i = 0; i < size; i++){ 43 | new_str[i] = str[i]; 44 | } 45 | new_str[size] = '\0'; 46 | return new_str; 47 | } 48 | 49 | char * private_BearsslHttps_strcpy( char *dest,const char *str){ 50 | long size = private_BearsslHttps_strlen(str); 51 | for(long i = 0; i < size; i++){ 52 | dest[i] = str[i]; 53 | } 54 | return dest; 55 | } 56 | char * private_BearsslHttps_strndup(const char *str,int size){ 57 | char *new_str = (char *)BearsslHttps_allocate(size+1); 58 | for(int i = 0; i < size; i++){ 59 | new_str[i] = str[i]; 60 | } 61 | new_str[size] = 0; 62 | return new_str; 63 | } 64 | 65 | int private_BearsslHttps_indexof_from_point(const char *str,char c,int start){ 66 | long size = private_BearsslHttps_strlen(str); 67 | for(int i = start; i < size; i++){ 68 | if(str[i] == c){ 69 | return i; 70 | } 71 | } 72 | return -1; 73 | } 74 | 75 | char private_BearsslHttps_parse_char_to_lower(char c){ 76 | if(c >= 'A' && c <= 'Z'){ 77 | return c + 32; 78 | } 79 | return c; 80 | } 81 | -------------------------------------------------------------------------------- /docs/instalations/one_file.md: -------------------------------------------------------------------------------- 1 | 2 | This tutorial explains how to compile and use the single-file version of the BearHttpsClient library. 3 | 4 | ## Prerequisites 5 | 6 | - A C compiler (GCC, Clang, MSVC, or MinGW) 7 | - Basic knowledge of C programming and command-line operations 8 | 9 | ## Step 1: Download the Library 10 | 11 | Download the single-file version of the library from the official repository and save it as `BearHttpsClientOne.c` in your project directory. 12 | 13 | Using curl: 14 | ```bash 15 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClientOne.c -o BearHttpsClientOne.c 16 | ``` 17 | 18 | ## Step 2: Create Application Source File 19 | 20 | Create a file named `main.c` with the following content: 21 | 22 | ```c 23 | #include "BearHttpsClientOne.c" 24 | 25 | int main(){ 26 | BearHttpsRequest *request = newBearHttpsRequest("https://example.com"); 27 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 28 | 29 | if(BearHttpsResponse_error(response)){ 30 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 31 | BearHttpsRequest_free(request); 32 | BearHttpsResponse_free(response); 33 | return 1; 34 | } 35 | 36 | const char *body = BearHttpsResponse_read_body_str(response); 37 | if(BearHttpsResponse_error(response)){ 38 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 39 | BearHttpsRequest_free(request); 40 | BearHttpsResponse_free(response); 41 | return 1; 42 | } 43 | 44 | printf("Response body: %s\n", body); 45 | 46 | BearHttpsRequest_free(request); 47 | BearHttpsResponse_free(response); 48 | return 0; 49 | } 50 | ``` 51 | 52 | Your project directory structure should now contain: 53 | ``` 54 | BearHttpsClientOne.c 55 | main.c 56 | ``` 57 | 58 | ## Step 3: Compilation Instructions 59 | 60 | ### GCC Compiler 61 | ```bash 62 | gcc main.c -o main 63 | ./main 64 | ``` 65 | 66 | ### Clang Compiler 67 | ```bash 68 | clang main.c -o main 69 | ./main 70 | ``` 71 | 72 | ### Microsoft Visual C++ Compiler 73 | ```bash 74 | cl main.c /Fe:main.exe 75 | main.exe 76 | ``` 77 | 78 | ### MinGW Cross-Compiler 79 | ```bash 80 | i686-w64-mingw32-gcc main.c -o main.exe -lws2_32 81 | ./main.exe 82 | ``` 83 | 84 | ### Emscripten (WebAssembly) 85 | ```bash 86 | emcc main.c -o main.js -sASYNCIFY 87 | ``` 88 | 89 | For WebAssembly compilation details, refer to the WebAssembly tutorial documentation. 90 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/request/fdefine.request.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | 11 | BearHttpsRequestNamespace newBearHttpsRequestNamespace(){ 12 | BearHttpsRequestNamespace self = {0}; 13 | self.send_any_with_ownership_control = BearHttpsRequest_send_any_with_ownership_control; 14 | self.send_any = BearHttpsRequest_send_any; 15 | self.send_body_str_with_ownership_control = BearHttpsRequest_send_body_str_with_ownership_control; 16 | self.send_body_str = BearHttpsRequest_send_body_str; 17 | self.send_file_with_ownership_control = BearHttpsRequest_send_file_with_ownership_control; 18 | self.send_file = BearHttpsRequest_send_file; 19 | self.send_file_auto_detect_content_type = BearHttpsRequest_send_file_auto_detect_content_type; 20 | self.fetch = BearHttpsRequest_fetch; 21 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 22 | self.send_cJSON_with_ownership_control = BearHttpsRequest_send_cJSON_with_ownership_control; 23 | self.send_cJSON = BearHttpsRequest_send_cJSON; 24 | self.create_cJSONPayloadObject = BearHttpsRequest_create_cJSONPayloadObject; 25 | self.create_cJSONPayloadArray = BearHttpsRequest_create_cJSONPayloadArray; 26 | #endif 27 | self.newBearHttpsRequest_with_url_ownership_config = newBearHttpsRequest_with_url_ownership_config; 28 | self.newBearHttpsRequest =newBearHttpsRequest; 29 | self.newBearHttpsRequest_fmt = newBearHttpsRequest_fmt; 30 | self.set_url_with_ownership_config = BearHttpsRequest_set_url_with_ownership_config; 31 | self.set_url = BearHttpsRequest_set_url; 32 | self.set_known_ips = BearHttpsRequest_set_known_ips; 33 | self.add_header_with_ownership_config = BearHttpsRequest_add_header_with_ownership_config; 34 | self.add_header = BearHttpsRequest_add_header; 35 | self.add_header_fmt =BearHttpsRequest_add_header_fmt; 36 | self.set_method = BearHttpsRequest_set_method; 37 | self.set_max_redirections = BearHttpsRequest_set_max_redirections; 38 | self.set_dns_providers = BearHttpsRequest_set_dns_providers; 39 | self.set_chunk_header_read_props = BearHttpsRequest_set_chunk_header_read_props; 40 | self.set_trusted_anchors = BearHttpsRequest_set_trusted_anchors; 41 | 42 | self.represent = BearHttpsRequest_represent; 43 | self.free = BearHttpsRequest_free; 44 | return self; 45 | 46 | } 47 | #endif -------------------------------------------------------------------------------- /docs/instalations/precompiled.md: -------------------------------------------------------------------------------- 1 | 2 | This tutorial demonstrates how to install and compile the BearHttpsClient library using precompiled files. 3 | 4 | ## Step 1: Download Library Files 5 | Download the precompiled library files to your project directory: 6 | - [BearHttpsClient.c](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.c) 7 | - [BearHttpsClient.h](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.h) 8 | 9 | Using curl: 10 | ```bash 11 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.c -o BearHttpsClient.c 12 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.h -o BearHttpsClient.h 13 | ``` 14 | 15 | ## Step 2: Create Application File 16 | Create a file named `main.c` with the following content: 17 | ```c 18 | #include "BearHttpsClient.h" 19 | int main(){ 20 | BearHttpsRequest *request = newBearHttpsRequest("https://example.com"); 21 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 22 | if(BearHttpsResponse_error(response)){ 23 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 24 | BearHttpsRequest_free(request); 25 | BearHttpsResponse_free(response); 26 | return 1; 27 | } 28 | 29 | const char *body = BearHttpsResponse_read_body_str(response); 30 | if(BearHttpsResponse_error(response)){ 31 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 32 | BearHttpsRequest_free(request); 33 | BearHttpsResponse_free(response); 34 | return 1; 35 | } 36 | 37 | printf("Body: %s\n",body); 38 | BearHttpsRequest_free(request); 39 | BearHttpsResponse_free(response); 40 | 41 | return 0; 42 | } 43 | ``` 44 | 45 | Project directory structure: 46 | ``` 47 | BearHttpsClient.c 48 | BearHttpsClient.h 49 | main.c 50 | ``` 51 | 52 | ## Step 3: Compilation Instructions 53 | 54 | **GCC Compiler:** 55 | ```bash 56 | gcc -c BearHttpsClient.c -o BearHttpsClient.o 57 | gcc main.c BearHttpsClient.o -o main 58 | ./main 59 | ``` 60 | 61 | **Clang Compiler:** 62 | ```bash 63 | clang -c BearHttpsClient.c -o BearHttpsClient.o 64 | clang main.c BearHttpsClient.o -o main 65 | ./main 66 | ``` 67 | 68 | **Microsoft Visual C++ Compiler:** 69 | ```bash 70 | cl BearHttpsClient.c /c 71 | cl main.c BearHttpsClient.obj /Fe:main.exe 72 | main.exe 73 | ``` 74 | 75 | **MinGW Cross-Compiler:** 76 | ```bash 77 | i686-w64-mingw32-gcc -c BearHttpsClient.c -o BearHttpsClient.o 78 | i686-w64-mingw32-gcc main.c BearHttpsClient.o -o main.exe -lws2_32 79 | ./main.exe 80 | ``` 81 | 82 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/fdefine.body_read.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | const unsigned char *BearHttpsResponse_read_body(BearHttpsResponse *self) { 10 | if (BearHttpsResponse_error(self)) { 11 | return NULL; 12 | } 13 | 14 | if (self->body_completed_read) { 15 | return self->body; 16 | } 17 | 18 | long body_allocated = self->body_size > 0 ? self->body_size : self->body_chunk_size; 19 | if (self->body_read_mode == PRIVATE_BEARSSL_BY_CONTENT_LENGTH) { 20 | body_allocated = self->respnse_content_lenght + 2; 21 | } 22 | self->body = (unsigned char *)BearsslHttps_reallocate(self->body, body_allocated); 23 | if (self->body == NULL) { 24 | BearHttpsResponse_set_error(self, "error allocating memory", BEARSSL_HTTPS_ALOCATION_FAILED); 25 | return NULL; 26 | } 27 | 28 | 29 | unsigned char *buffer = self->body; 30 | long total_readded = 0; 31 | while (true) { 32 | 33 | 34 | 35 | if ((total_readded + self->body_chunk_size + 2) > body_allocated) { 36 | 37 | while(body_allocated < (total_readded+ self->body_chunk_size + 2)) { 38 | body_allocated *= self->body_realloc_factor; 39 | } 40 | 41 | if (self->max_body_size != -1 && body_allocated > self->max_body_size) { 42 | BearHttpsResponse_set_error(self, "body size is bigger than max body size", BEARSSL_HTTPS_BODY_SIZE_ITS_BIGGER_THAN_LIMIT); 43 | BearsslHttps_free(self->body); 44 | self->body = NULL; 45 | return NULL; 46 | } 47 | self->body = (unsigned char *)BearsslHttps_reallocate(self->body, body_allocated); 48 | if (self->body == NULL) { 49 | BearHttpsResponse_set_error(self, "error allocating memory", BEARSSL_HTTPS_ALOCATION_FAILED); 50 | return NULL; 51 | } 52 | buffer = self->body + total_readded; 53 | } 54 | 55 | // Lê usando a função chunck 56 | int readded = BearHttpsResponse_read_body_chunck(self, buffer, self->body_chunk_size); 57 | if(readded > 0){ 58 | buffer += readded; 59 | total_readded += readded; 60 | continue; 61 | } 62 | break; 63 | 64 | } 65 | 66 | self->body_size = self->body_readded_size; 67 | self->body_completed_read = true; 68 | return self->body; 69 | } 70 | 71 | 72 | #endif -------------------------------------------------------------------------------- /src/ALL/response/fdefine.response.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | int BearHttpsResponse_get_status_code(BearHttpsResponse*self){ 7 | if(BearHttpsResponse_error(self)){ 8 | return -1; 9 | } 10 | return self->status_code; 11 | } 12 | 13 | int BearHttpsResponse_get_body_size(BearHttpsResponse*self){ 14 | return self->body_size; 15 | } 16 | 17 | bool BearHttpsResponse_error(BearHttpsResponse*self){ 18 | return self->error_msg != NULL; 19 | } 20 | 21 | void BearHttpsResponse_set_error(BearHttpsResponse*self,const char *msg,int error_code){ 22 | self->error_msg = private_BearsslHttps_strdup(msg); 23 | self->error_code = error_code; 24 | } 25 | 26 | const char* BearHttpsResponse_get_error_msg(BearHttpsResponse*self){ 27 | return self->error_msg; 28 | } 29 | 30 | int BearHttpsResponse_get_error_code(BearHttpsResponse*self){ 31 | return self->error_code; 32 | } 33 | 34 | int BearHttpsResponse_get_headers_size(BearHttpsResponse*self){ 35 | return self->headers->size; 36 | } 37 | 38 | const char* BearHttpsResponse_get_header_value_by_index(BearHttpsResponse*self,int index){ 39 | private_BearHttpsKeyVal * key_vall = private_BearHttpsHeaders_get_key_val_by_index(self->headers,index); 40 | if(key_vall == NULL){ 41 | return NULL; 42 | } 43 | return key_vall->value; 44 | } 45 | const char* BearHttpsResponse_get_header_key_by_index(BearHttpsResponse*self,int index){ 46 | private_BearHttpsKeyVal * key_vall = private_BearHttpsHeaders_get_key_val_by_index(self->headers,index); 47 | if(key_vall == NULL){ 48 | return NULL; 49 | } 50 | return key_vall->key; 51 | } 52 | const char* BearHttpsResponse_get_header_value_by_key(BearHttpsResponse*self,const char *key){ 53 | for(int i = 0; i < self->headers->size;i++){ 54 | private_BearHttpsKeyVal * current_key_val = self->headers->keyvals[i]; 55 | if(private_BearsslHttp_strcmp(current_key_val->key,key) == 0){ 56 | return current_key_val->value; 57 | } 58 | } 59 | return NULL; 60 | } 61 | 62 | const char* BearHttpsResponse_get_header_value_by_sanitized_key(BearHttpsResponse*self,const char *key){ 63 | long key_size = private_BearsslHttps_strlen(key); 64 | for(int i = 0; i < self->headers->size;i++){ 65 | private_BearHttpsKeyVal * current_key_val = self->headers->keyvals[i]; 66 | if(private_BearHttps_is_sanitize_key(current_key_val->key,key,key_size)){ 67 | return current_key_val->value; 68 | } 69 | } 70 | return NULL; 71 | } 72 | -------------------------------------------------------------------------------- /docs/instalations/full_dir.md: -------------------------------------------------------------------------------- 1 | WThis tutorial explains how to compile and use the BearHttpsClient library from the full directory distribution. 2 | 3 | ## Step 1: Download and Extract the Library 4 | Download the BearHttpsClient library distribution from the releases page and extract it to your project directory. 5 | 6 | ```bash 7 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.zip -o BearHttpsClient.zip 8 | unzip BearHttpsClient.zip 9 | ``` 10 | 11 | After extraction, your project directory will contain: 12 | 13 | ``` 14 | BearHttpsClient/ 15 | ├── build/ 16 | ├── dependencies/ 17 | └── src/ 18 | ``` 19 | ## Step 2: Create Your Application 20 | Create your application file (main.c) in the project directory: 21 | 22 | ```c 23 | #include "src/one.c" 24 | 25 | int main(){ 26 | BearHttpsRequest *request = newBearHttpsRequest("https://example.com"); 27 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 28 | 29 | if(BearHttpsResponse_error(response)){ 30 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 31 | BearHttpsRequest_free(request); 32 | BearHttpsResponse_free(response); 33 | return 1; 34 | } 35 | 36 | const char *body = BearHttpsResponse_read_body_str(response); 37 | if(BearHttpsResponse_error(response)){ 38 | printf("Error: %s\n",BearHttpsResponse_get_error_msg(response)); 39 | BearHttpsRequest_free(request); 40 | BearHttpsResponse_free(response); 41 | return 1; 42 | } 43 | 44 | printf("Body: %s\n",body); 45 | BearHttpsRequest_free(request); 46 | BearHttpsResponse_free(response); 47 | return 0; 48 | } 49 | ``` 50 | 51 | Your project structure should now be: 52 | 53 | ``` 54 | BearHttpsClient/ 55 | ├── build/ 56 | ├── dependencies/ 57 | ├── src/ 58 | └── main.c 59 | ``` 60 | 61 | 62 | ## Step 3: Compilation 63 | 64 | The library can be compiled using various C compilers. The following compilation commands will build your application with the BearHttpsClient library. 65 | 66 | ### GCC Compilation 67 | ```bash 68 | gcc main.c -o main.out 69 | ./main.out 70 | ``` 71 | 72 | ### Clang Compilation 73 | ```bash 74 | clang main.c -o main.out 75 | ./main.out 76 | ``` 77 | 78 | ### Microsoft Visual Studio Compiler 79 | ```bash 80 | cl main.c /Fe:main.exe 81 | main.exe 82 | ``` 83 | 84 | ### MinGW Cross-Compilation 85 | ```bash 86 | i686-w64-mingw32-gcc main.c -o main.exe -lws2_32 87 | ./main.exe 88 | ``` 89 | 90 | ### Emscripten (WebAssembly) 91 | For WebAssembly compilation, refer to the WebAssembly tutorial documentation for detailed instructions. 92 | 93 | ```bash 94 | emcc main.c -o main.js -sASYNCIFY 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/response/fdefine.response.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | BearHttpsResponse *private_newBearHttpsResponse(){ 11 | BearHttpsResponse *self = (BearHttpsResponse *)malloc(sizeof(BearHttpsResponse)); 12 | *self = (BearHttpsResponse){0}; 13 | self->status_code = 0; 14 | self->headers = private_newBearHttpsHeaders(); 15 | self->max_body_size = -1; 16 | self->body_read_mode = PRIVATE_BEARSSL_BY_READ_ERROR; 17 | self->body_chunk_size = BEARSSL_BODY_CHUNK_SIZE; 18 | self->body_realloc_factor = BEARSSL_BODY_REALLOC_FACTOR; 19 | self->body = NULL; 20 | return self; 21 | } 22 | 23 | 24 | 25 | 26 | void private_BearHttpsResponse_start_bearssl_props(BearHttpsResponse *self, const char *hostname,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size) { 27 | self->is_https = true; 28 | if(trust_anchors && trusted_anchors_size > 0){ 29 | br_ssl_client_init_full(&self->ssl_client, &self->certification_context, trust_anchors, trusted_anchors_size); 30 | } 31 | else{ 32 | br_ssl_client_init_full(&self->ssl_client, &self->certification_context, TAs, TAs_NUM); 33 | 34 | } 35 | br_ssl_engine_set_all_flags(& self->ssl_client.eng, BR_OPT_TOLERATE_NO_CLIENT_AUTH); 36 | br_ssl_engine_set_buffer(&self->ssl_client.eng, self->bear_buffer, sizeof(self->bear_buffer), 1); 37 | 38 | br_ssl_client_reset(&self->ssl_client, hostname, 0); 39 | br_sslio_init(&self->ssl_io, &self->ssl_client.eng, private_BearHttps_sock_read, 40 | &self->connection_file_descriptor, 41 | private_BearHttps_sock_write, 42 | &self->connection_file_descriptor 43 | ); 44 | } 45 | 46 | 47 | void BearHttpsResponse_free(BearHttpsResponse *self){ 48 | Universal_close(self->connection_file_descriptor); 49 | if(self->is_https){ 50 | br_ssl_client_zero(&self->ssl_client); 51 | } 52 | private_BearHttpsHeaders_free(self->headers); 53 | if(self->raw_content){ 54 | free(self->raw_content); 55 | } 56 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 57 | if(self->json_body){ 58 | cJSON_Delete(self->json_body); 59 | } 60 | #endif 61 | if(self->body){ 62 | free(self->body); 63 | } 64 | if(self->error_msg){ 65 | free(self->error_msg); 66 | } 67 | 68 | free(self); 69 | 70 | } 71 | 72 | void BearHttpsResponse_set_max_body_size(BearHttpsResponse*self,long size){ 73 | self->max_body_size = size; 74 | } 75 | 76 | void BearHttpsResponse_set_body_read_props(BearHttpsResponse*self,int chunk_size,double realloc_factor){ 77 | self->body_chunk_size = chunk_size; 78 | self->body_realloc_factor = realloc_factor; 79 | } 80 | 81 | 82 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/namespace/request/typesE.request.h: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.typesD.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | typedef struct BearHttpsRequestNamespace{ 9 | 10 | void (*send_any_with_ownership_control)(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode); 11 | void (*send_any)(BearHttpsRequest *self,unsigned char *content, long size); 12 | void (*send_body_str_with_ownership_control)(BearHttpsRequest *self, char *content,short ownership_mode); 13 | void (*send_body_str)(BearHttpsRequest *self, char *content); 14 | void (*send_file_with_ownership_control)(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type); 15 | void (*send_file)(BearHttpsRequest *self,const char *path,const char *content_type); 16 | void (*send_file_auto_detect_content_type)(BearHttpsRequest *self, const char *path); 17 | 18 | BearHttpsResponse * (*fetch)(BearHttpsRequest *self); 19 | 20 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 21 | void (*send_cJSON_with_ownership_control)(BearHttpsRequest *self,cJSON *json,short ownership_mode); 22 | void (*send_cJSON)(BearHttpsRequest *self,cJSON *json); 23 | const cJSON * (*create_cJSONPayloadObject)(BearHttpsRequest *self); 24 | const cJSON * (*create_cJSONPayloadArray)(BearHttpsRequest *self); 25 | #endif 26 | 27 | BearHttpsRequest * (*newBearHttpsRequest_with_url_ownership_config)(char *url,short url_ownership_mode); 28 | BearHttpsRequest * (*newBearHttpsRequest)(const char *url); 29 | BearHttpsRequest * (*newBearHttpsRequest_fmt)(const char *url,...); 30 | void (*set_known_ips)(BearHttpsRequest *self ,const char *known_ips[],int known_ips_size); 31 | void (*set_url_with_ownership_config)(BearHttpsRequest *self , char *url,short url_ownership_mode); 32 | void (*set_url)(BearHttpsRequest *self ,const char *url); 33 | void (*add_header_with_ownership_config)(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner); 34 | void (*add_header)(BearHttpsRequest *self ,const char *key,const char *value); 35 | void (*add_header_fmt)(BearHttpsRequest *self ,const char *key,const char *format,...); 36 | void (*set_method)(BearHttpsRequest *self ,const char *method); 37 | void (*set_max_redirections)(BearHttpsRequest *self ,int max_redirections); 38 | void (*set_dns_providers)(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers); 39 | void (*set_chunk_header_read_props)(BearHttpsRequest *self ,int chunk_size,int max_chunk_size); 40 | void (*set_trusted_anchors)(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size); 41 | void (*represent)(BearHttpsRequest *self); 42 | void (*free)(BearHttpsRequest *self); 43 | 44 | 45 | } BearHttpsRequestNamespace; 46 | 47 | #endif -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/response/fdefine.read_body.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | 7 | unsigned char *BearHttpsResponse_read_body(BearHttpsResponse *self) { 8 | if (!self || !self->response) { 9 | return NULL; 10 | } 11 | 12 | if (self->body) { 13 | return self->body; 14 | } 15 | c2wasm_js_var array_buffer = await_c2wasm_call_object_prop(self->response, "arrayBuffer", -1); 16 | if (c2wasm_instance_of(array_buffer, c2wasm_error)) { 17 | // Obter a mensagem de erro do objeto JavaScript 18 | c2wasm_js_var error_message = c2wasm_get_object_prop_any(array_buffer, "message"); 19 | int size = c2wasm_get_var_string_len(error_message); 20 | char *error_message_str = (char *)malloc(size + 2); 21 | c2wasm_memcpy_string(error_message, 0, error_message_str, size); 22 | error_message_str[size] = '\0'; 23 | BearHttpsResponse_set_error(self, error_message_str, 1); 24 | free(error_message_str); 25 | return NULL; 26 | } 27 | 28 | long body_size = c2wasm_get_object_prop_long(array_buffer, "byteLength"); 29 | printf("body size: %ld\n", body_size); 30 | if (body_size <= 0) { 31 | // Corpo vazio 32 | self->body = (unsigned char*)malloc(1); 33 | self->body[0] = '\0'; 34 | self->body_size = 0; 35 | return self->body; 36 | } 37 | 38 | // Aloca memória para o corpo 39 | self->body = (unsigned char*)malloc(body_size + 1); 40 | if (!self->body) { 41 | BearHttpsResponse_set_error(self, "Memory allocation failed", 1); 42 | return NULL; 43 | } 44 | // Cria um Uint8Array para acessar os bytes 45 | c2wasm_js_var uint8_array = c2wasm_call_object_constructor(c2wasm_window, "Uint8Array", array_buffer); 46 | if (c2wasm_instance_of(uint8_array, c2wasm_error)) { 47 | // Obter a mensagem de erro do objeto JavaScript 48 | c2wasm_js_var error_message = c2wasm_get_object_prop_any(uint8_array, "message"); 49 | int size = c2wasm_get_var_string_len(error_message); 50 | char *error_message_str = (char *)malloc(size + 2); 51 | c2wasm_memcpy_string(error_message, 0, error_message_str, size); 52 | error_message_str[size] = '\0'; 53 | BearHttpsResponse_set_error(self, error_message_str, 1); 54 | free(error_message_str); 55 | free(self->body); 56 | self->body = NULL; 57 | return NULL; 58 | } 59 | 60 | // Copia os bytes do JavaScript para C 61 | for (long i = 0; i < body_size; i++) { 62 | self->body[i] = (unsigned char)c2wasm_get_array_long_by_index(uint8_array, i); 63 | } 64 | 65 | // Adiciona terminador null para compatibilidade com strings 66 | self->body[body_size] = '\0'; 67 | self->body_size = body_size; 68 | 69 | return self->body; 70 | } 71 | 72 | #endif -------------------------------------------------------------------------------- /devops.releasefier.lua: -------------------------------------------------------------------------------- 1 | local cachify = load_global_module("cachify") 2 | local shipyard = load_global_module("shipyard") 3 | 4 | 5 | 6 | function main() 7 | 8 | local project_name = "BearHttpsClient" 9 | local session = luaberrante.newTelegramSession({ 10 | token = get_prop("devops.validator.token"), 11 | id_chat = get_prop("devops.validator.chat_id") 12 | }, luabear.fetch) 13 | 14 | os.execute("git reset --hard origin/main") 15 | 16 | cachify.register_first({ 17 | sources = {"darwindeps.json"}, 18 | cache_name="darwindeps", 19 | cache_dir=".cachify" 20 | }) 21 | 22 | cachify.register_first({ 23 | sources = {"src","dependencies","darwinconf.lua","build"}, 24 | cache_name="release", 25 | cache_dir=".cachify" 26 | }) 27 | 28 | os.execute("git pull") 29 | 30 | os.execute("darwin update darwindeps.json") 31 | 32 | cachify.execute_config({ 33 | sources = {"darwindeps.json"}, 34 | callback = function() 35 | dtw.remove_any("dependencies") 36 | os.execute("darwin install darwindeps.json") 37 | os.execute("git add .") 38 | os.execute("git commit -m 'deps: update dependencies'") 39 | os.execute("git push") 40 | session.sendMessage({ text = "📦 Dependencies updated successfully on " .. project_name .. "! ✅" }) 41 | end, 42 | cache_name="darwindeps", 43 | cache_dir=".cachify", 44 | ignore_first = true 45 | }) 46 | 47 | cachify.execute_config({ 48 | sources = {"src","dependencies","darwinconf.lua","build"}, 49 | callback = function() 50 | print("executed callback for release") 51 | dtw.remove_any("release") 52 | shipyard.increment_replacer("release.json","PATCH_VERSION") 53 | os.execute("git add .") 54 | os.execute("git commit -m 'release: prepare new release'") 55 | os.execute("git push") 56 | 57 | 58 | 59 | session.sendMessage({ text = "🚀 Release prepared successfully on " .. project_name .. "! ✅" }) 60 | 61 | 62 | local ok = os.execute("darwin run_blueprint --target all") 63 | if not ok then 64 | session.sendMessage({ text = "❌ Error running blueprints on " .. project_name .. "!" }) 65 | return 66 | end 67 | 68 | local ok ,error = pcall(shipyard.generate_release_from_json,"release.json") 69 | 70 | if not ok then 71 | session.sendMessage({ text = "❌ Error generating release:\n" .. error }) 72 | return 73 | end 74 | 75 | os.execute("gh release view > release.log") 76 | local log = dtw.load_file("release.log") 77 | session.sendMessage({ text = "🎉 Release generated successfully on " .. project_name .. "! ✅\n\n📋 Release Details:\n" .. log }) 78 | end, 79 | cache_name="release", 80 | cache_dir=".cachify", 81 | ignore_first = true 82 | }) 83 | end 84 | main() -------------------------------------------------------------------------------- /src/__unix__&&!__EMSCRIPTEN__/network/fdefine.connect_host.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if (defined(__unix__) || defined(__APPLE__)) && !defined(__EMSCRIPTEN__) 6 | 7 | 8 | #if (defined(BEARSSL_USSE_GET_ADDRINFO) || defined(BEARSSL_HTTPS_MOCK_CJSON)) 9 | static int private_BearHttps_connect_host(BearHttpsRequest *self, BearHttpsResponse *response, const char *host, int port){ 10 | Universal_addrinfo hints = {0}; 11 | memset(&hints, 0, sizeof(hints)); 12 | 13 | hints.ai_family = PF_UNSPEC; 14 | hints.ai_socktype = UNI_SOCK_STREAM; 15 | 16 | char port_str[10]; 17 | snprintf(port_str,sizeof(port_str)-1, "%d", port); 18 | Universal_addrinfo *addr_info; 19 | int status = Universal_getaddrinfo(host, port_str, &hints, &addr_info); 20 | if (status != 0) { 21 | BearHttpsResponse_set_error(response, gai_strerror(status),BEARSSL_HTTPS_UNKNOW_ERROR); 22 | return -1; 23 | } 24 | 25 | int found_socket = -1; 26 | for (Universal_addrinfo *current_addr = addr_info; current_addr != NULL; current_addr = current_addr->ai_next) { 27 | found_socket = Universal_socket(current_addr->ai_family, current_addr->ai_socktype, current_addr->ai_protocol); 28 | 29 | if (found_socket < 0) { 30 | continue; 31 | } 32 | 33 | // Set socket to non-blocking mode 34 | int flags = fcntl(found_socket, F_GETFL, 0); 35 | fcntl(found_socket, F_SETFL, flags | O_NONBLOCK); 36 | 37 | int ret = Universal_connect(found_socket, current_addr->ai_addr, current_addr->ai_addrlen); 38 | if (ret < 0 && errno != EINPROGRESS) { 39 | Universal_close(found_socket); 40 | continue; 41 | } 42 | 43 | // Use select to wait for connection with timeout 44 | fd_set write_fds; 45 | FD_ZERO(&write_fds); 46 | FD_SET(found_socket, &write_fds); 47 | 48 | struct timeval timeout; 49 | timeout.tv_sec = 0; 50 | timeout.tv_usec = self->connection_timeout * BEARSSL_MILISECONDS_MULTIPLIER; 51 | 52 | ret = select(found_socket + 1, NULL, &write_fds, NULL, &timeout); 53 | if (ret <= 0) { 54 | Universal_close(found_socket); 55 | continue; 56 | } 57 | 58 | // Check if connection succeeded 59 | int error = 0; 60 | socklen_t len = sizeof(error); 61 | if (getsockopt(found_socket, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error != 0) { 62 | Universal_close(found_socket); 63 | continue; 64 | } 65 | 66 | // Set socket back to blocking mode 67 | fcntl(found_socket, F_SETFL, flags); 68 | break; 69 | } 70 | 71 | if (found_socket < 0) { 72 | BearHttpsResponse_set_error(response, "ERROR: failed to connect\n",BEARSSL_HTTPS_FAILT_TO_CONNECT); 73 | return -1; 74 | } 75 | Universal_freeaddrinfo(addr_info); 76 | return found_socket; 77 | } 78 | 79 | #endif 80 | 81 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/request/fdefine.body_send.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | void BearHttpsRequest_send_file_with_ownership_control(BearHttpsRequest *self, char *path,short ownership_mode,const char *content_type){ 9 | private_BearHttpsRequest_free_body(self); 10 | private_BearsslHttps_set_str_considering_ownership( 11 | &self->body_file.path, 12 | path, 13 | &self->body_file.onwer, 14 | ownership_mode); 15 | private_BearsslHttps_strcpy(self->body_file.content_type,content_type); 16 | self->body_type = PRIVATE_BEARSSL_BODY_FILE; 17 | } 18 | 19 | void BearHttpsRequest_send_file(BearHttpsRequest *self,const char *path,const char *content_type){ 20 | BearHttpsRequest_send_file_with_ownership_control(self,(char*)path,BEARSSL_DEFAULT_STRATEGY,content_type); 21 | } 22 | 23 | void BearHttpsRequest_send_file_auto_detect_content_type(BearHttpsRequest *self,const char *path){ 24 | 25 | char extension[100] = {0}; 26 | bool found = false; 27 | long path_size = private_BearsslHttps_strlen(path); 28 | //iterate in negative from path, to count the extension 29 | for(int i = path_size-1; i >= 0; i--){ 30 | if(path[i] == '.'){ 31 | //verify if the extension is bigger than 100 32 | if(path_size - i > 100){ 33 | break; 34 | } 35 | found = true; 36 | private_BearsslHttps_strcpy(extension,&path[i+1]); 37 | break; 38 | } 39 | } 40 | if(!found){ 41 | BearHttpsRequest_send_file(self,path,"application/octet-stream"); 42 | return; 43 | } 44 | const char *content_type = "application/octet-stream"; 45 | if(private_BearsslHttp_strcmp(extension,"txt") == 0){ 46 | content_type = "text/plain"; 47 | } 48 | else if(private_BearsslHttp_strcmp(extension,"png") == 0){ 49 | content_type = "image/png"; 50 | } 51 | else if(private_BearsslHttp_strcmp(extension,"jpg") == 0){ 52 | content_type = "image/jpg"; 53 | } 54 | else if(private_BearsslHttp_strcmp(extension,"jpeg") == 0){ 55 | content_type = "image/jpeg"; 56 | } 57 | else if(private_BearsslHttp_strcmp(extension,"gif") == 0){ 58 | content_type = "image/gif"; 59 | } 60 | else if(private_BearsslHttp_strcmp(extension,"pdf") == 0){ 61 | content_type = "application/pdf"; 62 | } 63 | else if(private_BearsslHttp_strcmp(extension,"html") == 0){ 64 | content_type = "text/html"; 65 | } 66 | else if(private_BearsslHttp_strcmp(extension,"css") == 0){ 67 | content_type = "text/css"; 68 | } 69 | else if(private_BearsslHttp_strcmp(extension,"js") == 0){ 70 | content_type = "application/javascript"; 71 | } 72 | else if(private_BearsslHttp_strcmp(extension,"json") == 0){ 73 | content_type = "application/json"; 74 | } 75 | else if(private_BearsslHttp_strcmp(extension,"xml") == 0){ 76 | content_type = "application/xml"; 77 | } 78 | 79 | BearHttpsRequest_send_file(self,path,content_type); 80 | 81 | } 82 | 83 | 84 | 85 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/requisition_props/fdefine.requisition_props.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | private_BearHttpsRequisitionProps * private_new_private_BearHttpsRequisitionProps(const char *url,int default_port){ 10 | int url_size = private_BearsslHttps_strlen(url); 11 | const short HTTP_START_SIZE = sizeof("http://")-1; 12 | const short HTTPS_START_SIZE = sizeof("https://")-1; 13 | 14 | 15 | private_BearHttpsRequisitionProps *self = (private_BearHttpsRequisitionProps *)malloc(sizeof(private_BearHttpsRequisitionProps)); 16 | *self = (private_BearHttpsRequisitionProps){0}; 17 | short start_size; 18 | 19 | //setuping defaults elements 20 | if(private_BearsslHttps_startswith(url,"http://")){ 21 | self->port = default_port ? default_port: 80; 22 | self->is_https = false; 23 | start_size = HTTP_START_SIZE; 24 | } 25 | 26 | else if(private_BearsslHttps_startswith(url,"https://")){ 27 | self->port = default_port ? default_port: 443; 28 | self->is_https = true; 29 | start_size = HTTPS_START_SIZE; 30 | } 31 | else{ 32 | self->port = default_port ? default_port: 80; 33 | self->is_https = false; 34 | start_size = 0; 35 | } 36 | 37 | //1000 //2000 38 | int end_host_name_and_start_of_route = private_BearsslHttps_indexof_from_point(url,'/',start_size); 39 | 40 | if(end_host_name_and_start_of_route == -1){ 41 | end_host_name_and_start_of_route = url_size; 42 | } 43 | self->hostname = private_BearsslHttps_strndup((url+start_size),end_host_name_and_start_of_route-start_size); 44 | 45 | long host_name_size = private_BearsslHttps_strlen(self->hostname); 46 | 47 | if(end_host_name_and_start_of_route == url_size){ 48 | self->route = private_BearsslHttps_strdup("/"); } 49 | else{ 50 | self->route = private_BearsslHttps_strndup((url+end_host_name_and_start_of_route),url_size-end_host_name_and_start_of_route+1); 51 | } 52 | 53 | //iterate over hostname to determine if its ipv4 54 | short total_dots = 0; 55 | bool only_numbers = true; 56 | for(int i = 0; i < host_name_size; i++){ 57 | if(self->hostname[i] == '.'){ 58 | total_dots++; 59 | continue; 60 | } 61 | if(self->hostname[i] == ':'){ 62 | break; 63 | } 64 | if(self->hostname[i] < '0' || self->hostname[i] > '9'){ 65 | only_numbers = false; 66 | break; 67 | } 68 | 69 | } 70 | 71 | if(total_dots == 3 && only_numbers){ 72 | self->is_ipv4 = true; 73 | } 74 | 75 | //detect if self.hostname its ipv4 76 | if(default_port == 0){ 77 | int start_port = private_BearsslHttps_indexof_from_point(self->hostname,':',0); 78 | if(start_port != -1){ 79 | 80 | self->hostname[start_port] = '\0'; 81 | self->port = atoi(self->hostname+start_port+1); 82 | } 83 | } 84 | 85 | return self; 86 | } 87 | 88 | void private_BearHttpsRequisitionProps_free(private_BearHttpsRequisitionProps *self){ 89 | BearsslHttps_free(self->hostname); 90 | BearsslHttps_free(self->route); 91 | BearsslHttps_free(self); 92 | } 93 | 94 | #endif -------------------------------------------------------------------------------- /src/ALL/StringArray/fdefine.StringArray.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | struct privateBearHttpsStringArray * newprivateBearHttpsStringArray(){ 7 | struct privateBearHttpsStringArray *self = ( privateBearHttpsStringArray*)malloc(sizeof(struct privateBearHttpsStringArray)); 8 | self->size = 0; 9 | 10 | self->strings = (char**)malloc(1); 11 | 12 | return self; 13 | } 14 | 15 | int privateBearHttpsStringArray_find_position( privateBearHttpsStringArray *self, const char *string){ 16 | for(int i = 0; i < self->size; i++){ 17 | if(strcmp(self->strings[i], string) == 0){ 18 | return i; 19 | } 20 | } 21 | return -1; 22 | } 23 | 24 | 25 | void privateBearHttpsStringArray_set_value( privateBearHttpsStringArray *self, int index, const char *value){ 26 | if(index < self->size && index >= 0){ 27 | int size = strlen(value); 28 | self->strings[index] = (char*)realloc(self->strings[index], size + 1); 29 | self->strings[index][size] = '\0'; 30 | strcpy(self->strings[index], value); 31 | } 32 | } 33 | void privateBearHttpsStringArray_append_getting_ownership( privateBearHttpsStringArray *self, char *string){ 34 | self->strings = (char**)realloc(self->strings, (self->size+ 1) * sizeof(char*)); 35 | self->strings[self->size] = string; 36 | self->size+=1; 37 | } 38 | 39 | // Function prototypes 40 | void privateBearHttpsStringArray_append( privateBearHttpsStringArray *self, const char *string){ 41 | 42 | self->strings = (char**)realloc(self->strings, (self->size+ 1) * sizeof(char*)); 43 | self->strings[self->size] = strdup(string); 44 | self->size+=1; 45 | } 46 | 47 | void privateBearHttpsStringArray_pop( privateBearHttpsStringArray *self, int position){ 48 | free(self->strings[position]); 49 | for(int i = position; i < self->size -1; i++){ 50 | self->strings[i] = self->strings[i+1]; 51 | } 52 | self->size-=1; 53 | } 54 | 55 | void privateBearHttpsStringArray_merge( privateBearHttpsStringArray *self, privateBearHttpsStringArray *other){ 56 | for(int i = 0; i < other->size; i++){ 57 | privateBearHttpsStringArray_append(self, other->strings[i]); 58 | } 59 | } 60 | 61 | 62 | void privateBearHttpsStringArray_represent( privateBearHttpsStringArray *self){ 63 | for(int i = 0; i < self->size; i++){ 64 | printf("%s\n", self->strings[i]); 65 | } 66 | } 67 | 68 | 69 | 70 | 71 | privateBearHttpsStringArray * privateBearHttpsStringArray_clone(privateBearHttpsStringArray *self){ 72 | privateBearHttpsStringArray *clone = newprivateBearHttpsStringArray(); 73 | for(int i = 0; i< self->size; i++){ 74 | privateBearHttpsStringArray_append(clone,self->strings[i]); 75 | } 76 | return clone; 77 | } 78 | 79 | char * privateprivateBearHttpsStringArray_append_if_not_included(privateBearHttpsStringArray *self,char *value){ 80 | long position=privateBearHttpsStringArray_find_position(self,value); 81 | if(position != -1){ 82 | free(value); 83 | return self->strings[position]; 84 | } 85 | privateBearHttpsStringArray_append_getting_ownership(self,value); 86 | return value; 87 | } 88 | void privateBearHttpsStringArray_free(struct privateBearHttpsStringArray *self){ 89 | for(int i = 0; i < self->size; i++){ 90 | free(self->strings[i]); 91 | } 92 | 93 | free(self->strings); 94 | free(self); 95 | } 96 | -------------------------------------------------------------------------------- /src/__EMSCRIPTEN__/request/fdefine.fetch.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if defined(__EMSCRIPTEN__) 6 | #include 7 | BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self){ 8 | 9 | c2wasm_js_var headers = c2wasm_create_object(); 10 | 11 | for(int i = 0; i < self->headers->size;i++){ 12 | private_BearHttpsKeyVal *key_val = self->headers->keyvals[i]; 13 | c2wasm_set_object_prop_string(headers, key_val->key, key_val->value); 14 | } 15 | c2wasm_js_var props = c2wasm_create_object(); 16 | c2wasm_set_object_prop_string(props, "method", self->method); 17 | c2wasm_set_object_prop_any(props, "headers", headers); 18 | if(self->body_type == PRIVATE_BEARSSL_BODY_JSON){ 19 | char *value = cJSON_Print(self->body_json.json); 20 | c2wasm_set_object_prop_string(props, "body", value); 21 | free(value); 22 | } 23 | if(self->body_type == PRIVATE_BEARSSL_BODY_RAW){ 24 | c2wasm_set_object_prop_string(props, "body", (char *)self->body_raw.value); 25 | } 26 | 27 | c2wasm_js_var args_to_cal = c2wasm_create_array(); 28 | c2wasm_append_array_string(args_to_cal, self->url); 29 | c2wasm_append_array_any(args_to_cal, props); 30 | BearHttpsResponse *response = private_newBearHttpsResponse(); 31 | response->response = await_c2wasm_call_object_prop(c2wasm_window, "fetch", args_to_cal); 32 | if(c2wasm_instance_of(response->response ,c2wasm_error)){ 33 | // Obter a mensagem de erro do objeto JavaScript 34 | c2wasm_js_var error_message = c2wasm_get_object_prop_any(response->response , "message"); 35 | int size = c2wasm_get_var_string_len(error_message); 36 | char *error_message_str = (char *)malloc(size + 2); 37 | c2wasm_memcpy_string(error_message,0,error_message_str,size); 38 | error_message_str[size] = '\0'; 39 | BearHttpsResponse_set_error(response, error_message_str, 1); 40 | free(error_message_str); 41 | return response; 42 | } 43 | 44 | 45 | response->status_code = (int)c2wasm_get_object_prop_long(response->response , "status"); 46 | c2wasm_js_var js_headers = c2wasm_get_object_prop_any(response->response , "headers"); 47 | c2wasm_js_var entries = c2wasm_call_object_prop(js_headers, "entries", -1); 48 | c2wasm_js_var array = c2wasm_get_object_prop_any(c2wasm_window,"Array"); 49 | c2wasm_js_var entries_array = c2wasm_call_object_prop(array,"from", entries); 50 | long size = c2wasm_get_array_size(entries_array); 51 | for (long i = 0; i < size; i++) { 52 | c2wasm_js_var entry = c2wasm_get_array_any_by_index(entries_array, i); 53 | private_BearHttpsKeyVal * key_obj = private_newBearHttpsKeyVal(); 54 | int key_size = c2wasm_get_array_string_size_by_index(entry,0); 55 | char *key = (char *)malloc(key_size + 2); 56 | c2wasm_array_memcpy_string(entry,0,0,key,key_size); 57 | key[key_size] = '\0'; 58 | 59 | 60 | int value_size = c2wasm_get_array_string_size_by_index(entry,1); 61 | char *value = (char *)malloc(value_size + 2); 62 | value[value_size] = '\0'; 63 | c2wasm_array_memcpy_string(entry,1,0,value,value_size); 64 | private_BearHttpsKeyVal_set_key(key_obj,key,BEARSSL_HTTPS_GET_OWNERSHIP); 65 | private_BearHttpsKeyVal_set_value(key_obj,value,BEARSSL_HTTPS_GET_OWNERSHIP); 66 | private_BearHttpsHeaders_add_keyval(response->headers,key_obj); 67 | } 68 | 69 | 70 | return response; 71 | } 72 | #endif -------------------------------------------------------------------------------- /src/ALL/request/request/fdefine.request.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | BearHttpsRequest * newBearHttpsRequest(const char *url){ 9 | return newBearHttpsRequest_with_url_ownership_config((char*)url,BEARSSL_DEFAULT_STRATEGY); 10 | } 11 | 12 | BearHttpsRequest * newBearHttpsRequest_fmt(const char *url,...){ 13 | va_list args; 14 | va_start(args,url); 15 | 16 | char *formmated = private_BearHttps_format_vaarg(url,args); 17 | va_end(args); 18 | if(formmated == NULL){ 19 | return NULL; 20 | } 21 | return newBearHttpsRequest_with_url_ownership_config(formmated,BEARSSL_HTTPS_GET_OWNERSHIP); 22 | } 23 | 24 | void BearHttpsRequest_set_url_with_ownership_config(BearHttpsRequest *self , char *url,short url_ownership_mode){ 25 | private_BearsslHttps_set_str_considering_ownership(&self->url,url,&self->route_owner,url_ownership_mode); 26 | 27 | } 28 | 29 | void BearHttpsRequest_set_url(BearHttpsRequest *self ,const char *url){ 30 | BearHttpsRequest_set_url_with_ownership_config(self,(char*)url,BEARSSL_DEFAULT_STRATEGY); 31 | } 32 | 33 | 34 | void BearHttpsRequest_add_header_with_ownership_config(BearHttpsRequest *self ,char *key,short key_ownership_mode,char *value,short value_owner){ 35 | //verify if the key already exists 36 | for(int i = 0; i < self->headers->size;i++){ 37 | private_BearHttpsKeyVal *key_val = self->headers->keyvals[i]; 38 | if(private_BearsslHttp_strcmp(key_val->key,key) == 0){ 39 | private_BearHttpsKeyVal_set_value(key_val,value,value_owner); 40 | return; 41 | } 42 | } 43 | 44 | private_BearHttpsKeyVal * key_obj = private_newBearHttpsKeyVal(); 45 | private_BearHttpsKeyVal_set_key(key_obj,key,key_ownership_mode); 46 | private_BearHttpsKeyVal_set_value(key_obj,value,value_owner); 47 | private_BearHttpsHeaders_add_keyval(self->headers,key_obj); 48 | } 49 | 50 | void BearHttpsRequest_add_header(BearHttpsRequest *self ,const char *key,const char *value){ 51 | BearHttpsRequest_add_header_with_ownership_config(self,(char*)key,BEARSSL_DEFAULT_STRATEGY,(char*)value,BEARSSL_DEFAULT_STRATEGY); 52 | } 53 | 54 | void BearHttpsRequest_add_header_fmt(BearHttpsRequest *self ,const char *key,const char *format,...){ 55 | va_list args; 56 | va_start(args,format); 57 | char *formmated = private_BearHttps_format_vaarg(format,args); 58 | va_end(args); 59 | if(formmated == NULL){ 60 | return; 61 | } 62 | BearHttpsRequest_add_header_with_ownership_config(self,(char*)key,BEARSSL_DEFAULT_STRATEGY,formmated,BEARSSL_HTTPS_GET_OWNERSHIP); 63 | } 64 | 65 | void BearHttpsRequest_set_method(BearHttpsRequest *self ,const char *method){ 66 | private_BearsslHttps_strcpy(self->method,method); 67 | } 68 | 69 | void BearHttpsRequest_represent(BearHttpsRequest *self){ 70 | printf("Route: %s\n",self->url); 71 | printf("Method: %s\n",self->method); 72 | printf("Headers:\n"); 73 | for(int i = 0; i < self->headers->size;i++){ 74 | private_BearHttpsKeyVal *key_val = self->headers->keyvals[i]; 75 | printf("\t%s: %s\n",key_val->key,key_val->value); 76 | } 77 | if(self->body_type == PRIVATE_BEARSSL_BODY_RAW){ 78 | printf("Body: %s\n",self->body_raw.value); 79 | } 80 | if(self->body_type == PRIVATE_BEARSSL_BODY_FILE){ 81 | printf("Body-File: %s\n",self->body_file.path); 82 | } 83 | } 84 | 85 | 86 | 87 | void BearHttpsRequest_free(BearHttpsRequest *self){ 88 | private_BearHttpsRequest_free_body(self); 89 | private_BearHttpsHeaders_free(self->headers); 90 | private_BearsslHttps_free_considering_ownership((void **)&self->url,&self->route_owner); 91 | free(self); 92 | } 93 | -------------------------------------------------------------------------------- /docs/instalations/build_from_scratch.md: -------------------------------------------------------------------------------- 1 | This tutorial explains how to build the BearHttpsClient library from scratch, creating all the release files. This process will compile the source code into ready-to-use library files that you can include in your own projects. 2 | 3 | ## Prerequisites 4 | 5 | Before starting, ensure you have the following installed on your system: 6 | - Git (for downloading the source code) 7 | - A terminal or command prompt 8 | - Internet connection (for downloading dependencies) 9 | - Linux, macOS, or Windows with WSL (this tutorial focuses on Linux commands) 10 | 11 | ## Step 1: Download the source code 12 | 13 | First, you need to obtain the BearHttpsClient source code from the GitHub repository. 14 | 15 | If you have Git installed, open a terminal and run the following command: 16 | ```bash 17 | git clone https://github.com/OUIsolutions/BearHttpsClient.git 18 | ``` 19 | 20 | If you don't have Git installed, you can: 21 | - Install Git using your system's package manager (e.g., `sudo apt install git` on Ubuntu) 22 | - Or download the source code as a ZIP file from the [GitHub repository](https://github.com/OUIsolutions/BearHttpsClient) and extract it 23 | 24 | ## Step 2: Navigate to the project directory 25 | 26 | After downloading, you need to enter the project folder. In your terminal, run: 27 | ```bash 28 | cd BearHttpsClient 29 | ``` 30 | 31 | This command changes your current directory to the BearHttpsClient folder where all the source files are located. 32 | 33 | ## Step 3: Install the Darwin build tool 34 | 35 | The BearHttpsClient library uses Darwin as its build system. Darwin is a tool that helps compile and package the library files. 36 | 37 | You need to install Darwin version 0.8.0 specifically. On Linux, you can install it with this command: 38 | ```bash 39 | curl -L https://github.com/OUIsolutions/Darwin/releases/download/0.8.0/darwin.out -o darwin.out && sudo chmod +x darwin.out && sudo mv darwin.out /usr/bin/darwin 40 | ``` 41 | 42 | This command does three things: 43 | 1. Downloads the Darwin executable 44 | 2. Makes it executable (`chmod +x`) 45 | 3. Moves it to `/usr/bin/` so you can run it from anywhere (`sudo mv`) 46 | 47 | Note: You may be prompted for your password when using `sudo`. 48 | 49 | For other operating systems, visit the [Darwin releases page](https://github.com/OUIsolutions/Darwin/releases/tag/0.8.0) and download the appropriate version for your system. 50 | 51 | ## Step 4: Build the library 52 | 53 | Now you can compile the library using Darwin. Make sure you're still in the BearHttpsClient directory and run: 54 | ```bash 55 | darwin run_blueprint 56 | ``` 57 | 58 | This command tells Darwin to: 59 | - Run the build blueprint (the build instructions) 60 | - Interpret the [**darwinconf.lua**](/darwinconf.lua) file to know how to compile the library 61 | 62 | The build process may take a few moments as it compiles all the source files and dependencies. 63 | 64 | ## Step 5: Verify the build output 65 | 66 | After the build completes successfully, Darwin will create a `release` folder containing the compiled library files: 67 | ``` 68 | release/ 69 | ├── BearHttpsClient.c 70 | ├── BearHttpsClient.h 71 | ├── BearHttpsClientOne.c 72 | └── BearHttpsClient.zip 73 | ``` 74 | 75 | ## Understanding the output files 76 | 77 | The build process creates several important files: 78 | 79 | - **BearHttpsClient.h**: The header file containing function declarations and type definitions. Include this file in your C projects. 80 | - **BearHttpsClient.c**: The main implementation file containing all the library code. Compile this with your project. 81 | - **BearHttpsClientOne.c**: A single-file version that combines both header and implementation. Use this if you prefer a single-file approach. 82 | - **BearHttpsClient.zip**: A compressed archive containing all the release files for easy distribution. 83 | 84 | -------------------------------------------------------------------------------- /src/ALL/request/fdefine.body_send.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | 6 | 7 | 8 | 9 | 10 | void private_BearHttpsRequest_free_body(BearHttpsRequest *self){ 11 | 12 | if(self->body_type == PRIVATE_BEARSSL_BODY_RAW){ 13 | private_BearsslHttps_free_considering_ownership( 14 | (void**)&self->body_raw.value,&self->body_raw.onwer); 15 | } 16 | if(self->body_type == PRIVATE_BEARSSL_BODY_FILE){ 17 | private_BearsslHttps_free_considering_ownership( 18 | (void**)&self->body_file.path, 19 | &self->body_file.onwer 20 | ); 21 | } 22 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 23 | 24 | if(self->body_type == PRIVATE_BEARSSL_BODY_JSON){ 25 | if(self->body_json.onwer){ 26 | cJSON_Delete(self->body_json.json); 27 | } 28 | 29 | 30 | } 31 | #endif 32 | self->body_type = PRIVATE_BEARSSL_NO_BODY; 33 | 34 | } 35 | 36 | void BearHttpsRequest_send_any_with_ownership_control(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode){ 37 | private_BearHttpsRequest_free_body(self); 38 | self->body_type = PRIVATE_BEARSSL_BODY_RAW; 39 | if(ownership_mode == BEARSSL_HTTPS_COPY){ 40 | self->body_raw.value = (unsigned char *)malloc(size+2); 41 | for(int i = 0; i < size; i++){ 42 | self->body_raw.value[i] = content[i]; 43 | } 44 | self->body_raw.value[size] = '\0'; 45 | self->body_raw.onwer = true; 46 | self->body_raw.size = size; 47 | } 48 | if(ownership_mode == BEARSSL_HTTPS_GET_OWNERSHIP){ 49 | self->body_raw.value = content; 50 | self->body_raw.onwer = true; 51 | self->body_raw.size = size; 52 | } 53 | if(ownership_mode == BEARSSL_HTTPS_REFERENCE){ 54 | self->body_raw.value = content; 55 | self->body_raw.onwer = false; 56 | self->body_raw.size = size; 57 | } 58 | 59 | } 60 | void BearHttpsRequest_send_any(BearHttpsRequest *self,unsigned char *content, long size){ 61 | BearHttpsRequest_send_any_with_ownership_control(self,content,size,BEARSSL_DEFAULT_STRATEGY); 62 | } 63 | 64 | void BearHttpsRequest_send_body_str_with_ownership_control(BearHttpsRequest *self, char *content,short ownership_mode){ 65 | BearHttpsRequest_send_any_with_ownership_control(self,(unsigned char *)content,private_BearsslHttps_strlen(content),ownership_mode); 66 | } 67 | 68 | 69 | void BearHttpsRequest_send_body_str(BearHttpsRequest *self, char *content){ 70 | BearHttpsRequest_send_any_with_ownership_control(self,(unsigned char *)content,private_BearsslHttps_strlen(content),BEARSSL_DEFAULT_STRATEGY); 71 | } 72 | 73 | 74 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 75 | 76 | void BearHttpsRequest_send_cJSON_with_ownership_control(BearHttpsRequest *self,cJSON *json,short ownership_mode){ 77 | private_BearHttpsRequest_free_body(self); 78 | self->body_type = PRIVATE_BEARSSL_BODY_JSON; 79 | if(ownership_mode == BEARSSL_HTTPS_COPY){ 80 | self->body_json.json = cJSON_Duplicate(json,true); 81 | self->body_json.onwer = true; 82 | 83 | } 84 | if(ownership_mode == BEARSSL_HTTPS_GET_OWNERSHIP){ 85 | self->body_json.json = json; 86 | self->body_json.onwer = true; 87 | } 88 | if(ownership_mode == BEARSSL_HTTPS_REFERENCE){ 89 | self->body_json.json = json; 90 | self->body_json.onwer = false; 91 | } 92 | } 93 | void BearHttpsRequest_send_cJSON(BearHttpsRequest *self,cJSON *json){ 94 | BearHttpsRequest_send_cJSON_with_ownership_control(self,json,BEARSSL_DEFAULT_STRATEGY); 95 | } 96 | 97 | const cJSON * BearHttpsRequest_create_cJSONPayloadObject(BearHttpsRequest *self){ 98 | cJSON *json = cJSON_CreateObject(); 99 | BearHttpsRequest_send_cJSON_with_ownership_control(self,json,BEARSSL_HTTPS_GET_OWNERSHIP); 100 | return json; 101 | } 102 | 103 | 104 | const cJSON * BearHttpsRequest_create_cJSONPayloadArray(BearHttpsRequest *self){ 105 | cJSON *json = cJSON_CreateArray(); 106 | BearHttpsRequest_send_cJSON_with_ownership_control(self,json,BEARSSL_HTTPS_GET_OWNERSHIP); 107 | return json; 108 | } 109 | 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /docs/dependencies.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### [BearSSL](https://bearssl.org/) 4 | BearSSL is a small, fast, portable, and embeddable implementation of the SSL/TLS protocol (including TLS 1.3) written in C. It is designed to be easy to understand, use, and integrate into your application. BearSSL is a free software project, and it is licensed under the MIT License. 5 | 6 | 7 | 8 | Copyright (c) 2016 Thomas Pornin 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining 11 | a copy of this software and associated documentation files (the 12 | "Software"), to deal in the Software without restriction, including 13 | without limitation the rights to use, copy, modify, merge, publish, 14 | distribute, sublicense, and/or sell copies of the Software, and to 15 | permit persons to whom the Software is furnished to do so, subject to 16 | the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 25 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 26 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | 30 | 31 | 32 | ### [Universal Socket](https://github.com/SamuelHenriqueDeMoraisVitrio/UniversalSocket) 33 | 34 | UniversalSocket is a cross-platform C socket library designed to simplify socket programming on both Linux and Windows platforms. This library abstracts the platform-specific details and provides a unified API for socket creation, communication, and error handling. 35 | 36 | It supports both IPv4 and IPv6 addresses, as well as TCP, UDP, and raw sockets. The library also allows for socket configuration using common socket options and handles typical socket operations like binding, listening, connecting, and accepting connections. 37 | 38 | MIT License 39 | 40 | Copyright (c) 2024 Samuel Henrique 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to deal 44 | in the Software without restriction, including without limitation the rights 45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 46 | copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all 50 | copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 58 | SOFTWARE. 59 | 60 | ### [CJSON](https://github.com/DaveGamble/cJSON) 61 | 62 | CJSON is a lightweight JSON parser written in C. It is designed to be easy to use, fast, and portable. The library provides functions for parsing JSON data, creating JSON objects, and manipulating JSON objects. It is suitable for use in embedded systems and other resource-constrained environments. 63 | 64 | 65 | Copyright (c) 2009-2017 Dave Gamble and cJSON contributors 66 | 67 | Permission is hereby granted, free of charge, to any person obtaining a copy 68 | of this software and associated documentation files (the "Software"), to deal 69 | in the Software without restriction, including without limitation the rights 70 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 71 | copies of the Software, and to permit persons to whom the Software is 72 | furnished to do so, subject to the following conditions: 73 | 74 | The above copyright notice and this permission notice shall be included in 75 | all copies or substantial portions of the Software. 76 | 77 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 78 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 79 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 80 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 81 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 82 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 83 | THE SOFTWARE. 84 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/fdefine.body_read_chunk.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | int BearHttpsResponse_read_body_chunck_http1(BearHttpsResponse *self,unsigned char *buffer,long size){ 8 | long remaning_to_read = size; 9 | while (true){ 10 | if(self->http1_state == PRIVATE_BEARHTTPS_COLLECTING_NUMBER){ 11 | char number_buffer[10] = {0}; 12 | bool number_buffer_filled = false; 13 | for(int i =0; i < 10;i++){ 14 | BearHttpsResponse_read_body_chunck_raw(self, (unsigned char*)number_buffer + i, 1); 15 | if(number_buffer[i] == '\r' && i > 0){ 16 | number_buffer[i] = 0; 17 | self->http1_reaming_to_read = strtol((const char*)number_buffer, NULL, 16); 18 | 19 | if(self->http1_reaming_to_read < 0){ 20 | BearHttpsResponse_set_error(self,"invalid http response",BEARSSL_HTTPS_INVALID_HTTP_RESPONSE); 21 | return -1; 22 | } 23 | if(self->http1_reaming_to_read == 0){ 24 | self->http1_state = PRIVATE_BEARHTTPS_COLLECTING_NUMBER; 25 | self->body_completed_read = true; 26 | return size - remaning_to_read; //return the size of the body readed 27 | } 28 | 29 | self->http1_state = PRIVATE_BEARHTTPS_READING_CHUNK; 30 | number_buffer_filled= true; 31 | char trash[2] = {0}; 32 | BearHttpsResponse_read_body_chunck_raw(self, (unsigned char*)trash, 1); 33 | break; 34 | } 35 | } 36 | 37 | if(!number_buffer_filled){ 38 | BearHttpsResponse_set_error(self,"invalid http response",BEARSSL_HTTPS_INVALID_HTTP_RESPONSE); 39 | return -1; 40 | } 41 | 42 | } 43 | if(self->http1_state == PRIVATE_BEARHTTPS_READING_CHUNK){ 44 | long read_size; 45 | if(remaning_to_read <= self->http1_reaming_to_read){ 46 | read_size = remaning_to_read; 47 | } 48 | 49 | if(remaning_to_read > self->http1_reaming_to_read){ 50 | read_size = self->http1_reaming_to_read; 51 | } 52 | 53 | long readded = BearHttpsResponse_read_body_chunck_raw(self, buffer, read_size); 54 | if(readded < 0){ 55 | BearHttpsResponse_set_error(self,"error reading body chunk",BEARSSL_HTTPS_ERROR_READING_CHUNK); 56 | return -1; 57 | } 58 | remaning_to_read -= readded; 59 | self->http1_reaming_to_read -= readded; 60 | if(self->http1_reaming_to_read == 0){ 61 | self->http1_state = PRIVATE_BEARHTTPS_COLLECTING_NUMBER; 62 | char trash[3] = {0}; 63 | BearHttpsResponse_read_body_chunck_raw(self, (unsigned char*)trash, 2); //read \r\n 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | return 0; 71 | } 72 | 73 | 74 | int BearHttpsResponse_read_body_chunck_raw(BearHttpsResponse *self,unsigned char *buffer,long size){ 75 | 76 | long total_prev_sended = 0; 77 | while (self->extra_body_remaning_to_send > 0) { 78 | if(total_prev_sended >= size){ 79 | return total_prev_sended; 80 | } 81 | buffer[total_prev_sended] = self->body[self->body_readded_size - self->extra_body_remaning_to_send]; 82 | self->extra_body_remaning_to_send-=1; 83 | total_prev_sended+=1; 84 | } 85 | 86 | long readded = private_BearHttpsResponse_recv(self,buffer+total_prev_sended,size-total_prev_sended); 87 | if(readded < 0){ 88 | return readded; 89 | } 90 | if(readded> 0){ 91 | self->body_readded_size+=readded; 92 | } 93 | int total_readded = readded + total_prev_sended; 94 | buffer[total_readded] = 0; 95 | return total_readded; 96 | 97 | } 98 | 99 | int BearHttpsResponse_read_body_chunck(BearHttpsResponse *self,unsigned char *buffer,long size){ 100 | if(BearHttpsResponse_error(self)){ 101 | return -1; 102 | } 103 | 104 | if(self->body_readded_size == self->respnse_content_lenght && self->body_read_mode == PRIVATE_BEARSSL_BY_CONTENT_LENGTH ){ 105 | return 0; 106 | } 107 | 108 | if(self->body_read_mode == PRIVATE_BEARSSL_BY_CHUNKED){ 109 | return BearHttpsResponse_read_body_chunck_http1(self,buffer,size); 110 | } 111 | 112 | return BearHttpsResponse_read_body_chunck_raw(self,buffer,size); 113 | } 114 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/network/fdefine.ipv4_connect.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | static int private_BearHttpsRequest_connect_ipv4(BearHttpsResponse *self, const char *ipv4_ip, int port,long connection_timeout) { 8 | int sockfd = Universal_socket(UNI_AF_INET, UNI_SOCK_STREAM, 0); 9 | if (sockfd < 0) { 10 | BearHttpsResponse_set_error(self,"ERROR: failed to create socket",BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET); 11 | return -1; 12 | } 13 | 14 | // Set socket to non-blocking mode 15 | if (private_BearHttps_socket_set_nonblocking(sockfd) < 0) { 16 | BearHttpsResponse_set_error(self,"ERROR: failed to set socket non-blocking",BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET); 17 | Universal_close(sockfd); 18 | return -1; 19 | } 20 | 21 | Universal_sockaddr_in server_addr; 22 | memset(&server_addr, 0, sizeof(server_addr)); 23 | server_addr.sin_family = UNI_AF_INET; 24 | server_addr.sin_port = Universal_htons(port); 25 | 26 | if (Universal_inet_pton(UNI_AF_INET, ipv4_ip, &server_addr.sin_addr) <= 0) { 27 | BearHttpsResponse_set_error(self,"ERROR: invalid address",BEARSSL_HTTPS_INVALID_IPV4); 28 | Universal_close(sockfd); 29 | return -1; 30 | } 31 | 32 | int ret = Universal_connect(sockfd, (Universal_sockaddr *)&server_addr, sizeof(server_addr)); 33 | if (private_BearHttps_socket_check_connect_in_progress(ret) < 0) { 34 | BearHttpsResponse_set_error(self,"ERROR: failed to connect",BEARSSL_HTTPS_FAILT_TO_CONNECT); 35 | Universal_close(sockfd); 36 | return -1; 37 | } 38 | 39 | // Use select to wait for connection with timeout 40 | fd_set write_fds; 41 | FD_ZERO(&write_fds); 42 | FD_SET(sockfd, &write_fds); 43 | 44 | struct timeval timeout; 45 | timeout.tv_sec = connection_timeout / 1000; 46 | timeout.tv_usec = (connection_timeout % 1000) * BEARSSL_MILISECONDS_MULTIPLIER; 47 | 48 | ret = select(sockfd + 1, NULL, &write_fds, NULL, &timeout); 49 | if (ret <= 0) { 50 | BearHttpsResponse_set_error(self,"ERROR: connection timeout or failed",BEARSSL_HTTPS_FAILT_TO_CONNECT); 51 | Universal_close(sockfd); 52 | return -1; 53 | } 54 | 55 | // Check if connection succeeded 56 | if (private_BearHttps_socket_check_connect_error(sockfd) < 0) { 57 | BearHttpsResponse_set_error(self,"ERROR: failed to connect",BEARSSL_HTTPS_FAILT_TO_CONNECT); 58 | Universal_close(sockfd); 59 | return -1; 60 | } 61 | 62 | // Set socket back to blocking mode 63 | if (private_BearHttps_socket_set_blocking(sockfd) < 0) { 64 | BearHttpsResponse_set_error(self,"ERROR: failed to set socket blocking",BEARSSL_HTTPS_FAILT_TO_CREATE_SOCKET); 65 | Universal_close(sockfd); 66 | return -1; 67 | } 68 | 69 | return sockfd; 70 | } 71 | 72 | 73 | static int private_BearHttpsRequest_connect_ipv4_no_error_raise( const char *ipv4_ip, int port,long connection_timeout) { 74 | int sockfd = Universal_socket(UNI_AF_INET, UNI_SOCK_STREAM, 0); 75 | if (sockfd < 0) { 76 | return -1; 77 | } 78 | 79 | // Set socket to non-blocking mode 80 | if (private_BearHttps_socket_set_nonblocking(sockfd) < 0) { 81 | Universal_close(sockfd); 82 | return -1; 83 | } 84 | 85 | Universal_sockaddr_in server_addr; 86 | memset(&server_addr, 0, sizeof(server_addr)); 87 | server_addr.sin_family = UNI_AF_INET; 88 | server_addr.sin_port = Universal_htons(port); 89 | 90 | if (Universal_inet_pton(UNI_AF_INET, ipv4_ip, &server_addr.sin_addr) <= 0) { 91 | Universal_close(sockfd); 92 | return -1; 93 | } 94 | int ret = Universal_connect(sockfd, (Universal_sockaddr *)&server_addr, sizeof(server_addr)); 95 | if (private_BearHttps_socket_check_connect_in_progress(ret) < 0) { 96 | Universal_close(sockfd); 97 | return -1; 98 | } 99 | 100 | // Use select to wait for connection with timeout 101 | fd_set write_fds; 102 | FD_ZERO(&write_fds); 103 | FD_SET(sockfd, &write_fds); 104 | 105 | struct timeval timeout; 106 | timeout.tv_sec = connection_timeout / 1000; 107 | timeout.tv_usec = (connection_timeout % 1000) * BEARSSL_MILISECONDS_MULTIPLIER; 108 | 109 | ret = select(sockfd + 1, NULL, &write_fds, NULL, &timeout); 110 | if (ret <= 0) { 111 | Universal_close(sockfd); 112 | return -1; 113 | } 114 | 115 | // Check if connection succeeded 116 | if (private_BearHttps_socket_check_connect_error(sockfd) < 0) { 117 | Universal_close(sockfd); 118 | return -1; 119 | } 120 | 121 | // Set socket back to blocking mode 122 | if (private_BearHttps_socket_set_blocking(sockfd) < 0) { 123 | Universal_close(sockfd); 124 | return -1; 125 | } 126 | 127 | return sockfd; 128 | } 129 | 130 | 131 | #endif -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/response/fdefine.http_parser.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | void private_BearHttpsResponse_parse_headers(BearHttpsResponse *self,int headers_end){ 11 | const short WAITING_FIRST_SPACE = 0; 12 | const short WAITING_STATUS_CODE = 1; 13 | const short WAITING_FIRST_LINE_TERMINATION = 3; 14 | const short COLECTING_KEY = 4; 15 | const short WAITING_END_KEY = 5; 16 | const short COLECTING_VAL = 6; 17 | const short WAITING_END_VAL = 7; 18 | short state = WAITING_FIRST_SPACE; 19 | private_BearHttpsKeyVal *current_key_vall = NULL; 20 | for(int i =3 ; i < headers_end;i++){ 21 | if(self->raw_content[i] == ' ' && state == WAITING_FIRST_SPACE){ 22 | state = WAITING_STATUS_CODE; 23 | continue; 24 | } 25 | if(self->raw_content[i] != ' ' && state == WAITING_STATUS_CODE){ 26 | self->status_code = atoi((const char*)self->raw_content + i); 27 | state = WAITING_FIRST_LINE_TERMINATION; 28 | continue; 29 | } 30 | if(self->raw_content[i] == '\n' && self->raw_content[i-1] =='\r' && state == WAITING_FIRST_LINE_TERMINATION){ 31 | state = COLECTING_KEY; 32 | continue; 33 | } 34 | if(state == COLECTING_KEY && self->raw_content[i] != ' '){ 35 | current_key_vall = private_newBearHttpsKeyVal(); 36 | private_BearHttpsKeyVal_set_key(current_key_vall,(char*)self->raw_content+i,BEARSSL_HTTPS_REFERENCE); 37 | state = WAITING_END_KEY; 38 | continue; 39 | } 40 | 41 | if(state == WAITING_END_KEY && self->raw_content[i] == ':'){ 42 | self->raw_content[i] = '\0'; 43 | state = COLECTING_VAL; 44 | continue; 45 | } 46 | if(state == COLECTING_VAL && self->raw_content[i] != ' '){ 47 | private_BearHttpsKeyVal_set_value(current_key_vall,(char*)self->raw_content+i,BEARSSL_HTTPS_REFERENCE); 48 | state = WAITING_END_VAL; 49 | continue; 50 | } 51 | 52 | if( self->raw_content[i-1] =='\r' && self->raw_content[i] == '\n' && state == WAITING_END_VAL){ 53 | self->raw_content[i-1] = '\0'; 54 | private_BearHttpsHeaders_add_keyval(self->headers,current_key_vall); 55 | current_key_vall = NULL; 56 | state = COLECTING_KEY; 57 | continue; 58 | } 59 | 60 | } 61 | 62 | const char *content_length = BearHttpsResponse_get_header_value_by_sanitized_key(self,"contentlength"); 63 | if(content_length != NULL){ 64 | self->body_read_mode = PRIVATE_BEARSSL_BY_CONTENT_LENGTH; 65 | self->respnse_content_lenght = atol(content_length); 66 | } 67 | const char *transfer_encoding = BearHttpsResponse_get_header_value_by_sanitized_key(self,"transferencoding"); 68 | if(transfer_encoding != NULL ){ 69 | if(private_BearsslHttp_strcmp(transfer_encoding,"chunked") == 0){ 70 | self->body_read_mode = PRIVATE_BEARSSL_BY_CHUNKED; 71 | } 72 | } 73 | 74 | } 75 | void private_BearHttpsResponse_read_til_end_of_headers_or_reach_limit( 76 | BearHttpsResponse *self, 77 | int chunk_size, 78 | double factor_headers_growth 79 | ){ 80 | 81 | 82 | self->raw_content = (unsigned char *)BearsslHttps_allocate(chunk_size+2); 83 | long content_allocated = chunk_size; 84 | long content_size = 0; 85 | while(true){ 86 | //apply the factor realloc 87 | while(content_size + chunk_size >= content_allocated -2 ){ 88 | 89 | content_allocated = (long)(content_allocated * factor_headers_growth); 90 | self->raw_content = (unsigned char*)BearsslHttps_reallocate(self->raw_content,content_allocated); 91 | } 92 | //we create a buff str , to allow 'append' into the content 93 | unsigned char *content_point = (self->raw_content +content_size); 94 | 95 | int readded = private_BearHttpsResponse_recv(self,content_point, chunk_size); 96 | if(readded == 0){ 97 | BearHttpsResponse_set_error(self,"invalid http response",BEARSSL_HTTPS_INVALID_HTTP_RESPONSE); 98 | return; 99 | 100 | } 101 | 102 | if(readded < 0){ 103 | char error_buff[100] ={0}; 104 | snprintf(error_buff,sizeof(error_buff),"invalid read code: %d",readded); 105 | BearHttpsResponse_set_error(self,error_buff,BEARSSL_HTTPS_INVALID_READ_CODE); 106 | return; 107 | } 108 | 109 | 110 | for(int i = 3; i < readded;i++){ 111 | if( 112 | content_point[i-3] == '\r' && 113 | content_point[i-2] == '\n' && 114 | content_point[i-1] == '\r' && 115 | content_point[i] == '\n' ) 116 | { 117 | 118 | self->body_start_index =content_size + i+1; 119 | self->body_size = ((content_size+readded) - self->body_start_index); 120 | self->extra_body_remaning_to_send = self->body_size; 121 | self->body_readded_size = self->body_size; 122 | self->body = (unsigned char*)BearsslHttps_allocate(self->body_size+2); 123 | memcpy(self->body,self->raw_content + self->body_start_index,self->body_size); 124 | self->body[self->body_size] = '\0'; 125 | 126 | private_BearHttpsResponse_parse_headers(self,content_size + i-1); 127 | return; 128 | } 129 | } 130 | content_size+=readded; 131 | 132 | } 133 | 134 | 135 | BearHttpsResponse_set_error(self,"invalid http response",BEARSSL_HTTPS_INVALID_HTTP_RESPONSE); 136 | 137 | 138 | } 139 | 140 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # BearHttpsClient 4 | ![C Logo](https://img.shields.io/badge/BearHttpsClient-0.6.0-blue?style=for-the-badge&logo=c) 5 | [![GitHub Release](https://img.shields.io/github/release/OUIsolutions/BearHttpsClient.svg?style=for-the-badge)](https://github.com/OUIsolutions/BearHttpsClient/releases) 6 | [![License](https://img.shields.io/badge/License-MIT-green.svg?style=for-the-badge)](https://github.com/OUIsolutions/BearHttpsClient/blob/main/LICENSE) 7 | ![Status](https://img.shields.io/badge/Status-Alpha-orange?style=for-the-badge) 8 | ![Platforms](https://img.shields.io/badge/Platforms-Windows%20|%20Linux%20|%20WebAssembly-lightgrey?style=for-the-badge) 9 | 10 |
11 | 12 | --- 13 | 14 | ## ⚠️ Important Notice 15 | 16 | > **This is alpha software!** Use at your own risk. While we're working hard to make it stable, bugs are expected. Perfect for learning and prototyping! 🧪 17 | 18 | --- 19 | 20 | ### Overview 21 | 22 | BearHttpsClient is a lightweight HTTP/HTTPS client library for C/C++ applications. It provides a streamlined interface for network communication, eliminating the complexity of traditional networking code: 23 | 24 | 1. **Specify the target URL** 25 | 2. **Retrieve the response** 26 | 3. **Process the data** 27 | 28 | This library is designed for developers who need to: 29 | - Download resources from remote servers 30 | - Communicate with web APIs 31 | - Retrieve data from online services 32 | - Implement HTTP/HTTPS functionality in applications 33 | 34 | ### Key Features 35 | 36 | - **HTTP & HTTPS support** - Secure communication with any web service 37 | - **Simplified integration** - Single-file inclusion option 38 | - **File transfer capabilities** - Efficient upload and download functionality 39 | - **API compatibility** - Built-in support for JSON and modern web services 40 | - **Cross-platform functionality** - Compatible with Windows, Linux, and WebAssembly 41 | - **Minimal dependencies** - No additional library installations required 42 | 43 | ### AI/LLM Integration 44 | 45 | Want to learn how to use BearHttpsClient with AI assistance? Download the [ai_doc.md](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/ai_doc.md) file and paste its contents to your preferred AI assistant (ChatGPT, Claude, Copilot, etc.) for interactive learning and code examples. 46 | 47 | --- 48 | 49 | ## Releases 50 | 51 | 52 | | **File** | **What is** | 53 | |---------------------------------------------------------------------------------------------------------------------|--------------------------------------------| 54 | |[BearHttpsClientOne.c](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClientOne.c) | A Amalgamation Containing all the Library | 55 | |[BearHttpsClient.zip](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.zip) | The Whole Project ziped in a dir | 56 | |[BearHttpsClient.c](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.c) | Project Definition | 57 | |[BearHttpsClient.h](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.h) | Project Header | 58 | |[ai_doc.md](https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/ai_doc.md) | AI/LLM Integration Documentation | 59 | 60 | ## Installations Tutorials 61 | | **Tutorial** | **Description** | 62 | |---------------------------------------------------------------|------------------------------------------------------ | 63 | | [OneFile](docs/instalations/one_file.md) | Single File Library Installation Guide (the most easy)| 64 | | [Precompiled](docs/instalations/precompiled.md) | Precompiled Library Installation Guide | 65 | | [Full Directory](docs/instalations/full_dir.md) | Full Directory Library Installation Guide | 66 | | [Build from Scratch](docs/instalations/build_from_scratch.md) | Building BearHttpsClient from Source Code | 67 | 68 | ## [Public API](docs/public_api.md) 69 | Click here [Public API](docs/public_api.md) to see the full list of public API functions. 70 | 71 | ## Usage Tutorials 72 | 73 | | **Tutorial** | **Description** | 74 | |-----------------------------------------------------------------|---------------------------------------------------------| 75 | | [Query Parameters](docs/tutorials/query_param.md) | Working with URL query parameters | 76 | | [Headers](docs/tutorials/headers.md) | Working with HTTP headers | 77 | | [Body Upload](docs/tutorials/body_upload.md) | Guide for uploading request bodies | 78 | | [REST API Consuming](docs/tutorials/rest_api_consuming.md) | Consuming RESTful web services | 79 | | [Network Configuration](docs/tutorials/network_configuration.md) | Configuring network settings | 80 | | [Memory and Limits](docs/tutorials/memory_and_limits.md) | Memory management and resource limits | 81 | | [Ownership System](docs/tutorials/ownership_system.md) | Understanding resource ownership | 82 | | [Web Assembly](docs/tutorials/web_assembly.md) | Using BearHttpsClient with WebAssembly | 83 | | [Creating a Visual Fetcher Site](docs/tutorials/creating_a_visual_fetcher_site.md) | Building a visual interface for data fetching using WebAssembly | 84 | 85 | ## 📄 License 86 | 87 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 88 | 89 | --- 90 | 91 | -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/network/fdefine.connect_host.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | #if (!defined(BEARSSL_USSE_GET_ADDRINFO) && !defined(BEARSSL_HTTPS_MOCK_CJSON)) 9 | static int private_BearHttps_connect_host(BearHttpsRequest *self, BearHttpsResponse *response, const char *host, int port){ 10 | 11 | 12 | if(strcmp(host,"localhost")==0){ 13 | return private_BearHttpsRequest_connect_ipv4(response,"0.0.0.0",port,self->connection_timeout); 14 | } 15 | for(int i = 0; i < self->known_ips_size;i++){ 16 | const char *ip = self->known_ips[i]; 17 | int sockfd = private_BearHttpsRequest_connect_ipv4_no_error_raise(ip,port,self->connection_timeout); 18 | if(sockfd < 0){ 19 | continue; 20 | } 21 | 22 | return sockfd; 23 | } 24 | 25 | for(int i = 0; i < BEARSSL_DNS_CACHE_SIZE;i++){ 26 | privateBearHttpsDnsCache *cache = &privateBearHttpsDnsCache_itens[i]; 27 | 28 | if(private_BearsslHttp_strcmp(cache->host,host) == 0){ 29 | int sockfd = private_BearHttpsRequest_connect_ipv4_no_error_raise(cache->ip,port,self->connection_timeout); 30 | if(sockfd < 0){ 31 | break; 32 | } 33 | return sockfd; 34 | } 35 | } 36 | 37 | BearHttpsClientDnsProvider *chosen_dns_providers = self->dns_providers ? self->dns_providers : privateBearHttpsProviders; 38 | int chosen_dns_providers_size = self->total_dns_providers ? self->total_dns_providers : privateBearHttpsProvidersSize; 39 | 40 | if(chosen_dns_providers_size == 0){ 41 | BearHttpsResponse_set_error(response,"ERROR: no dns providers\n",BEARSSL_HTTPS_NO_DNS_PROVIDED); 42 | return -1; 43 | } 44 | 45 | privateBearHttpsStringArray * already_testted = newprivateBearHttpsStringArray(); 46 | 47 | for(int i = 0; i < chosen_dns_providers_size;i++){ 48 | BearHttpsClientDnsProvider provider = chosen_dns_providers[i]; 49 | BearHttpsRequest *dns_request = newBearHttpsRequest_fmt("https://%s:%d%s?name=%s&type=A",provider.ip,provider.port, provider.route, host); 50 | //printf("used url %s\n",dns_request->url); 51 | dns_request->custom_bear_dns = provider.hostname; 52 | 53 | //these its require, otherwise can generate indirect recursion error if provider.ip its wrong 54 | dns_request->must_be_ipv4 = true; 55 | BearHttpsResponse *dns_response = BearHttpsRequest_fetch(dns_request); 56 | 57 | 58 | if(BearHttpsResponse_error(dns_response)){ 59 | BearHttpsRequest_free(dns_request); 60 | BearHttpsResponse_free(dns_response); 61 | continue; 62 | } 63 | 64 | 65 | const cJSON * body = BearHttpsResponse_read_body_json(dns_response); 66 | //printf("leu o body json: %s\n",cJSON_Print(body)); 67 | if(BearHttpsResponse_error(dns_response)){ 68 | const char *message = BearHttpsResponse_get_error_msg(dns_response); 69 | BearHttpsRequest_free(dns_request); 70 | BearHttpsResponse_free(dns_response); 71 | continue; 72 | } 73 | 74 | cJSON * answer = cJSON_GetObjectItem(body, "Answer"); 75 | if(answer == NULL){ 76 | BearHttpsRequest_free(dns_request); 77 | BearHttpsResponse_free(dns_response); 78 | continue; 79 | } 80 | long size = cJSON_GetArraySize(answer); 81 | if(size == 0){ 82 | BearHttpsRequest_free(dns_request); 83 | BearHttpsResponse_free(dns_response); 84 | continue; 85 | } 86 | for(int j = 0; j < size;j++){ 87 | cJSON * item = cJSON_GetArrayItem(answer,j); 88 | cJSON * data = cJSON_GetObjectItem(item, "data"); 89 | if(data == NULL){ 90 | continue; 91 | } 92 | const char * ipv4 = cJSON_GetStringValue(data); 93 | if(ipv4 == NULL){ 94 | continue; 95 | } 96 | if(privateBearHttpsStringArray_find_position(already_testted, ipv4) != -1){ 97 | continue; 98 | } 99 | privateBearHttpsStringArray_append(already_testted, ipv4); 100 | 101 | int sockfd = private_BearHttpsRequest_connect_ipv4_no_error_raise(ipv4,port,self->connection_timeout); 102 | if(sockfd < 0){ 103 | continue; 104 | } 105 | long host_size = private_BearsslHttps_strlen(host); 106 | long ip_size = private_BearsslHttps_strlen(ipv4); 107 | 108 | if(privateBearHttpsDnsCache_last_free_point >= BEARSSL_DNS_CACHE_SIZE){ 109 | privateBearHttpsDnsCache_last_free_point = 0; 110 | } 111 | 112 | if(host_size < BEARSSL_DNS_CACHE_HOST_SIZE && ip_size < BEARSSL_DNS_CACHE_IP_SIZE){ 113 | 114 | 115 | privateBearHttpsDnsCache* cache = &privateBearHttpsDnsCache_itens[privateBearHttpsDnsCache_last_free_point]; 116 | private_BearsslHttps_strcpy( cache->host,host); 117 | private_BearsslHttps_strcpy( cache->ip,ipv4); 118 | privateBearHttpsDnsCache_last_free_point++; 119 | } 120 | 121 | BearHttpsRequest_free(dns_request); 122 | BearHttpsResponse_free(dns_response); 123 | privateBearHttpsStringArray_free(already_testted); 124 | return sockfd; 125 | } 126 | BearHttpsRequest_free(dns_request); 127 | BearHttpsResponse_free(dns_response); 128 | } 129 | 130 | BearHttpsResponse_set_error(response,"ERROR: failed to create dns request",BEARSSL_HTTPS_FAILT_TO_CREATE_DNS_REQUEST); 131 | privateBearHttpsStringArray_free(already_testted); 132 | return -1; 133 | } 134 | 135 | 136 | #endif 137 | 138 | 139 | #endif -------------------------------------------------------------------------------- /docs/public_api.md: -------------------------------------------------------------------------------- 1 | 2 | # BearHttpsClient Public API Reference 3 | 4 | This document provides a comprehensive reference for all public API functions available in the BearHttpsClient library. The BearHttpsClient is a lightweight, secure HTTPS client library built on top of BearSSL, designed for making HTTP/HTTPS requests with full SSL/TLS support. 5 | 6 | The API is organized into logical groups covering request creation, configuration, body handling, execution, and response processing. Each function is documented with detailed usage examples and parameter descriptions. 7 | 8 | ## Summary of all Public API Functions 9 | 10 | | Function Name | Description | 11 | | ----------------------------------------------------------------------------------------------------------------------------------| ---------------------------------------------------------------------- | 12 | | **Request Creation Functions** | | 13 | | [newBearHttpsRequest](public_api/newBearHttpsRequest.md) | Creates a new HTTP request object with the specified URL | 14 | | [newBearHttpsRequest_with_url_ownership_config](public_api/newBearHttpsRequest_with_url_ownership_config.md) | Creates a new HTTP request object with URL ownership control | 15 | | [BearHttpsRequest_free](public_api/BearHttpsRequest_free.md) | Frees the memory allocated for a request object | 16 | | **Request Configuration Functions** | | 17 | | [BearHttpsRequest_add_header](public_api/BearHttpsRequest_add_header.md) | Adds a header to the HTTP request | 18 | | [BearHttpsRequest_add_header_fmt](public_api/BearHttpsRequest_add_header_fmt.md) | Adds headers to the request using a formatted string | 19 | | [BearHttpsRequest_set_chunk_header_read_props](public_api/BearHttpsRequest_set_chunk_header_read_props.md) | Configures chunk reading properties for response headers | 20 | | [BearHttpsRequest_set_dns_providers](public_api/BearHttpsRequest_set_dns_providers.md) | Sets custom DNS providers for resolving hostnames | 21 | | [BearHttpsRequest_set_known_ips](public_api/BearHttpsRequest_set_known_ips.md) | Sets a list of known IP addresses for the request's hostname | 22 | | [BearHttpsRequest_set_max_redirections](public_api/BearHttpsRequest_set_max_redirections.md) | Sets the maximum number of HTTP redirections to follow | 23 | | [BearHttpsRequest_set_trusted_anchors](public_api/BearHttpsRequest_set_trusted_anchors.md) | Sets custom trusted anchors (root certificates) for SSL/TLS validation | 24 | | **Request Body/Payload Functions** | | 25 | | [BearHttpsRequest_create_cJSONPayloadArray](public_api/BearHttpsRequest_create_cJSONPayloadArray.md) | Creates a new cJSON array for building JSON array payloads | 26 | | [BearHttpsRequest_create_cJSONPayloadObject](public_api/BearHttpsRequest_create_cJSONPayloadObject.md) | Creates a new cJSON object for building JSON payloads | 27 | | [BearHttpsRequest_send_any](public_api/BearHttpsRequest_send_any.md) | Sends binary data as the request body (default ownership) | 28 | | [BearHttpsRequest_send_any_with_ownership_control](public_api/BearHttpsRequest_send_any_with_ownership_control.md) | Sends binary data as the request body with ownership control | 29 | | [BearHttpsRequest_send_body_str](public_api/BearHttpsRequest_send_body_str.md) | Sends a string as the request body (default ownership) | 30 | | [BearHttpsRequest_send_body_str_with_ownership_control](public_api/BearHttpsRequest_send_body_str_with_ownership_control.md) | Sends a string as the request body with ownership control | 31 | | [BearHttpsRequest_send_cJSON](public_api/BearHttpsRequest_send_cJSON.md) | Sends a cJSON object as the request body (default ownership) | 32 | | [BearHttpsRequest_send_cJSON_with_ownership_control](public_api/BearHttpsRequest_send_cJSON_with_ownership_control.md) | Sends a cJSON object as the request body with ownership control | 33 | | **Request Execution Functions** | | 34 | | [BearHttpsRequest_fetch](public_api/BearHttpsRequest_fetch.md) | Executes the HTTP request and returns the response | 35 | | **Response Handling Functions** | | 36 | | [BearHttpsResponse_error](public_api/BearHttpsResponse_error.md) | Checks if an error occurred during the HTTP request | 37 | | [BearHttpsResponse_free](public_api/BearHttpsResponse_free.md) | Frees the memory allocated for a response object | 38 | | [BearHttpsResponse_get_error_code](public_api/BearHttpsResponse_get_error_code.md) | Gets a numeric error code if an error occurred | 39 | | [BearHttpsResponse_get_error_msg](public_api/BearHttpsResponse_get_error_msg.md) | Gets a human-readable error message if an error occurred | 40 | | [BearHttpsResponse_get_status_code](public_api/BearHttpsResponse_get_status_code.md) | Gets the HTTP status code from the response | 41 | | **Response Body Functions** | | 42 | | [BearHttpsResponse_get_body_size](public_api/BearHttpsResponse_get_body_size.md) | Gets the size of the response body in bytes | 43 | | [BearHttpsResponse_read_body_str](public_api/BearHttpsResponse_read_body_str.md) | Reads the response body as a null-terminated string | 44 | | [BearHttpsResponse_read_body_json](public_api/BearHttpsResponse_read_body_json.md) | Reads and parses the response body as a JSON object | 45 | | **Response Header Functions** | | 46 | | [BearHttpsResponse_get_headers_size](public_api/BearHttpsResponse_get_headers_size.md) | Gets the number of headers in the HTTP response | 47 | | [BearHttpsResponse_get_header_key_by_index](public_api/BearHttpsResponse_get_header_key_by_index.md) | Gets the key (name) of a response header by its index position | 48 | | [BearHttpsResponse_get_header_value_by_index](public_api/BearHttpsResponse_get_header_value_by_index.md) | Gets the value of a response header by its index position | 49 | | [BearHttpsResponse_get_header_value_by_key](public_api/BearHttpsResponse_get_header_value_by_key.md) | Gets the value of a response header by its key (case-sensitive) | 50 | | [BearHttpsResponse_get_header_value_by_sanitized_key](public_api/BearHttpsResponse_get_header_value_by_sanitized_key.md) | Gets the value of a response header by its key (case-insensitive) | -------------------------------------------------------------------------------- /docs/ai_doc.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | single file mode 3 | ```bash 4 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClientOne.c -o BearHttpsClientOne.c 5 | ``` 6 | # Basic Usage 7 | ```c 8 | #include "BearHttpsClient.h" 9 | // DO NOT include any other headers - they are already bundled in BearHttpsClient 10 | 11 | int main(){ 12 | BearHttpsRequest *request = newBearHttpsRequest("https://example.com/"); 13 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 14 | if(BearHttpsResponse_error(response)){ 15 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 16 | } else { 17 | printf("Response Status Code: %d\n", BearHttpsResponse_get_status_code(response)); 18 | const char *body = BearHttpsResponse_read_body_str(response); 19 | if(body != NULL){ 20 | printf("Response Body: %s\n", body); 21 | } 22 | } 23 | BearHttpsRequest_free(request); 24 | BearHttpsResponse_free(response); 25 | return 0; 26 | } 27 | ``` 28 | ## Pre-Compiling the lib 29 | ```bash 30 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.c -o BearHttpsClient.c 31 | curl -L https://github.com/OUIsolutions/BearHttpsClient/releases/download/0.6.0/BearHttpsClient.h -o BearHttpsClient.h 32 | gcc -c BearHttpsClient.c -o BearHttpsClient.o 33 | gcc main.c BearHttpsClient.o -o main.out 34 | ``` 35 | ### include on Precompiled mode 36 | ```c 37 | #include "BearHttpsClient.h" 38 | // DO NOT include any other headers - they are already bundled in BearHttpsClient 39 | ``` 40 | 41 | ### MinGW Cross-Compiler 42 | ```bash 43 | i686-w64-mingw32-gcc main.c -o main.exe -lws2_32 44 | ./main.exe 45 | ``` 46 | ## Gcc Compilation (linux) 47 | ```bash 48 | gcc main.c BearHttpsClient.o -o main.out 49 | ``` 50 | 51 | # Onefile Mode 52 | ```c 53 | #include "BearHttpsClientOne.c" 54 | // DO NOT include any other headers - they are already bundled in BearHttpsClientOne.c 55 | ``` 56 | ## Onefile Compilation (linux) 57 | ```bash 58 | gcc main.c -o main.out 59 | ``` 60 | ## Onefile Compilation (windows) 61 | ```bash 62 | i686-w64-mingw32-gcc main.c -o main.exe -lws2_32 63 | ``` 64 | 65 | # Public API 66 | 67 | ## IMPORTANT: All dependencies are already bundled - DO NOT include these headers manually: 68 | ``` 69 | ❌ DO NOT INCLUDE: 70 | - cJSON.h 71 | - string.h 72 | - stdio.h 73 | - stdint.h 74 | - stdlib.h 75 | - ctype.h 76 | - arpa/inet.h 77 | - netinet/in.h 78 | - sys/socket.h 79 | - sys/types.h 80 | - netdb.h 81 | - unistd.h 82 | - errno.h 83 | - winsock2.h 84 | - ws2tcpip.h 85 | - windows.h 86 | ``` 87 | 88 | # 🚨 CRITICAL NULL CHECK ENFORCEMENT 🚨 89 | 90 | ## MANDATORY: Always check for NULL before using any return values 91 | **All cJSON and header response functions can return NULL. You MUST check for NULL before accessing any returned values.** 92 | 93 | ### ⚠️ Functions that can return NULL: 94 | - `BearHttpsResponse_read_body_json()` - Can return NULL if JSON parsing fails 95 | - `BearHttpsResponse_get_header_value_by_index()` - Can return NULL if index is invalid 96 | - `BearHttpsResponse_get_header_key_by_index()` - Can return NULL if index is invalid 97 | - `BearHttpsResponse_get_header_value_by_key()` - Can return NULL if key doesn't exist 98 | - `BearHttpsResponse_get_header_value_by_sanitized_key()` - Can return NULL if key doesn't exist 99 | - `BearHttpsResponse_read_body_str()` - Can return NULL if body is empty or invalid 100 | 101 | ### ✅ ALWAYS use this pattern: 102 | ```c 103 | // For JSON responses 104 | const cJSON *json = BearHttpsResponse_read_body_json(response); 105 | if(json != NULL) { 106 | // Safe to use json 107 | } else { 108 | // Handle NULL case 109 | } 110 | 111 | // For headers 112 | const char *header_value = BearHttpsResponse_get_header_value_by_key(response, "Content-Type"); 113 | if(header_value != NULL) { 114 | printf("Content-Type: %s\n", header_value); 115 | } else { 116 | printf("Header not found\n"); 117 | } 118 | 119 | // For body string 120 | const char *body = BearHttpsResponse_read_body_str(response); 121 | if(body != NULL) { 122 | printf("Body: %s\n", body); 123 | } else { 124 | printf("No body or invalid body\n"); 125 | } 126 | ``` 127 | 128 | # IMPORTANT: All cJSON Returns are consts, you should not free them manually. 129 | # IMPORTANT: Assign all cJSON* returns to const cJSON* variables, otherwise you will get a compiler warning 130 | 131 | 132 | **These are automatically included when you include BearHttpsClient.c, BearHttpsClient.h or BearHttpsClientOne.c** 133 | 134 | ### Ownership Modes 135 | 136 | ```c 137 | BEARSSL_HTTPS_REFERENCE = 0 // keeps the reference of the item passed to the function 138 | BEARSSL_HTTPS_GET_OWNERSHIP = 1 // takes the ownership of the item passed to the function and free it when not needed anymore 139 | BEARSSL_HTTPS_COPY = 2 // makes a copy of the item passed to the function 140 | BEARSSL_DEFAULT_STRATEGY = BEARSSL_HTTPS_COPY // default strategy for string parameters 141 | ``` 142 | 143 | ### Dns Providers sample 144 | ```c 145 | BearHttpsClientDnsProvider providers[] = { 146 | { 147 | .hostname = "dns.google.com", 148 | .route = "/resolve", 149 | .ip = "8.8.8.8", 150 | .port = 443 151 | }, 152 | { 153 | .hostname = "dns.nextdns.io", 154 | .route = "/dns-query", 155 | .ip = "217.146.9.93", 156 | .port = 443 157 | } 158 | }; 159 | ``` 160 | 161 | ### Known IPs sample 162 | ```c 163 | const char *known_ips[] = { 164 | "93.184.216.34", // Primary IP 165 | "93.184.216.35" // Backup IP 166 | }; 167 | int known_ips_count = sizeof(known_ips) / sizeof(const char*); 168 | ``` 169 | 170 | ### Request Struct 171 | ```c 172 | typedef struct BearHttpsRequest BearHttpsRequest; 173 | BearHttpsRequest * newBearHttpsRequest(const char *url); 174 | // Headers 175 | void BearHttpsRequest_add_header(BearHttpsRequest *self ,const char *key,const char *value); 176 | void BearHttpsRequest_add_header_fmt(BearHttpsRequest *self ,const char *key,const char *format,...); 177 | 178 | BearHttpsRequest * newBearHttpsRequest_with_url_ownership_config(char *url,short url_ownership_mode); 179 | void BearHttpsRequest_set_known_ips(BearHttpsRequest *self , const char *known_ips[],int known_ips_size); 180 | void BearHttpsRequest_set_max_redirections(BearHttpsRequest *self ,int max_redirections); 181 | void BearHttpsRequest_set_dns_providers(BearHttpsRequest *self ,BearHttpsClientDnsProvider *dns_providers,int total_dns_proviers); 182 | void BearHttpsRequest_set_chunk_header_read_props(BearHttpsRequest *self ,int chunk_size,int max_chunk_size); 183 | void BearHttpsRequest_set_trusted_anchors(BearHttpsRequest *self ,br_x509_trust_anchor *trust_anchors, size_t trusted_anchors_size); 184 | // Body Send 185 | 186 | void BearHttpsRequest_send_any_with_ownership_control(BearHttpsRequest *self,unsigned char *content, long size,short ownership_mode); 187 | void BearHttpsRequest_send_any(BearHttpsRequest *self,unsigned char *content, long size); 188 | void BearHttpsRequest_send_body_str_with_ownership_control(BearHttpsRequest *self, char *content,short ownership_mode); 189 | void BearHttpsRequest_send_body_str(BearHttpsRequest *self, char *content); 190 | //memory of request 191 | 192 | void BearHttpsRequest_send_cJSON_with_ownership_control(BearHttpsRequest *self,cJSON *json,short ownership_mode); 193 | void BearHttpsRequest_send_cJSON(BearHttpsRequest *self,cJSON *json); 194 | const cJSON * BearHttpsRequest_create_cJSONPayloadObject(BearHttpsRequest *self); 195 | const cJSON * BearHttpsRequest_create_cJSONPayloadArray(BearHttpsRequest *self); 196 | BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self); 197 | 198 | void BearHttpsRequest_free(BearHttpsRequest *self); 199 | ``` 200 | 201 | ### Response Struct 202 | ```c 203 | typedef struct BearHttpsResponse BearHttpsResponse; 204 | BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self); 205 | int BearHttpsResponse_get_status_code(BearHttpsResponse*self); 206 | int BearHttpsResponse_get_body_size(BearHttpsResponse*self); 207 | bool BearHttpsResponse_error(BearHttpsResponse*self); 208 | const char* BearHttpsResponse_get_error_msg(BearHttpsResponse*self); 209 | int BearHttpsResponse_get_error_code(BearHttpsResponse*self); 210 | int BearHttpsResponse_get_headers_size(BearHttpsResponse*self); 211 | const char* BearHttpsResponse_get_header_value_by_index(BearHttpsResponse*self,int index); 212 | const char* BearHttpsResponse_get_header_key_by_index(BearHttpsResponse*self,int index); 213 | const char* BearHttpsResponse_get_header_value_by_key(BearHttpsResponse*self,const char *key); 214 | const char* BearHttpsResponse_get_header_value_by_sanitized_key(BearHttpsResponse*self,const char *key); 215 | const char* BearHttpsResponse_read_body_str(BearHttpsResponse *self); 216 | const cJSON * BearHttpsResponse_read_body_json(BearHttpsResponse *self); 217 | ``` -------------------------------------------------------------------------------- /src/!__EMSCRIPTEN__/request/fdefine.fetch.c: -------------------------------------------------------------------------------- 1 | //silver_chain_scope_start 2 | //mannaged by silver chain: https://github.com/OUIsolutions/SilverChain 3 | #include "../../imports/imports.dep_defineB.h" 4 | //silver_chain_scope_end 5 | #if !defined(__EMSCRIPTEN__) 6 | 7 | 8 | 9 | 10 | 11 | BearHttpsResponse * BearHttpsRequest_fetch(BearHttpsRequest *self){ 12 | 13 | BearHttpsResponse *response = NULL; 14 | 15 | int uni_start = Universal_start_all(); 16 | if (uni_start != 0) { 17 | BearHttpsResponse_set_error(response, "failt to start unisocket",BEARSSL_HTTPS_FAILT_TO_START_UNISOCKET); 18 | return response; 19 | } 20 | 21 | //we start at -1 , because the first conection its not consider a redirection 22 | for(int i = -1; i < self->max_redirections;i++){ 23 | 24 | 25 | response = private_newBearHttpsResponse(); 26 | private_BearHttpsRequisitionProps *requisition_props = private_new_private_BearHttpsRequisitionProps( 27 | self->url, 28 | self->port 29 | ); 30 | if(requisition_props == NULL){ 31 | BearHttpsResponse_set_error(response, "invalid url",BEARSSL_HTTPS_INVALID_URL); 32 | return response; 33 | } 34 | 35 | if(requisition_props->is_ipv4){ 36 | response->connection_file_descriptor = private_BearHttpsRequest_connect_ipv4( 37 | response, 38 | requisition_props->hostname, 39 | requisition_props->port, 40 | self->connection_timeout 41 | ); 42 | } 43 | //these function its used on the private_BearHttpsRequest_connect_host and if returns these 44 | //means that the dns its wrong formatted 45 | if(requisition_props->is_ipv4 == false && self->must_be_ipv4){ 46 | BearHttpsResponse_set_error(response, "must be ipv4",BEARSSL_HTTPS_MUST_BE_IPV4); 47 | private_BearHttpsRequisitionProps_free(requisition_props); 48 | return response; 49 | } 50 | 51 | if(requisition_props->is_ipv4 == false){ 52 | response->connection_file_descriptor =private_BearHttps_connect_host( 53 | self, 54 | response, 55 | requisition_props->hostname, 56 | requisition_props->port 57 | ); 58 | } 59 | 60 | if(response->connection_file_descriptor < 0){ 61 | private_BearHttpsRequisitionProps_free(requisition_props); 62 | return response; 63 | } 64 | 65 | if(requisition_props->is_https){ 66 | 67 | const char *chosen_host = self->custom_bear_dns ? self->custom_bear_dns : requisition_props->hostname; 68 | private_BearHttpsResponse_start_bearssl_props(response,chosen_host,self->trust_anchors,self->trusted_anchors_size); 69 | } 70 | private_BearHttpsResponse_write(response, (unsigned char*)self->method, private_BearsslHttps_strlen(self->method)); 71 | private_BearHttpsResponse_write(response, (unsigned char*)" ", 1); 72 | private_BearHttpsResponse_write(response, (unsigned char*)requisition_props->route, private_BearsslHttps_strlen(requisition_props->route)); 73 | char start_msg[100] ={0}; 74 | if(self->http_protocol == BEARSSL_HTTPS_HTTP1_0){ 75 | snprintf(start_msg, sizeof(start_msg) - 1, " HTTP/1.0\r\nHost: "); 76 | } else if(self->http_protocol == BEARSSL_HTTPS_HTTP1_1){ 77 | snprintf(start_msg, sizeof(start_msg) - 1, " HTTP/1.1\r\nHost: "); 78 | } else { 79 | BearHttpsResponse_set_error(response, "invalid http protocol",BEARSSL_HTTPS_INVALID_HTTP_PROTOCOL); 80 | private_BearHttpsRequisitionProps_free(requisition_props); 81 | return response; 82 | } 83 | 84 | 85 | 86 | private_BearHttpsResponse_write(response, (unsigned char*)start_msg, private_BearsslHttps_strlen(start_msg)); 87 | private_BearHttpsResponse_write(response, (unsigned char*)requisition_props->hostname, private_BearsslHttps_strlen(requisition_props->hostname)); 88 | private_BearHttpsResponse_write(response, (unsigned char*)"\r\n", 2); 89 | 90 | 91 | for (int i = 0; i < self->headers->size; i++) { 92 | private_BearHttpsKeyVal *keyval = self->headers->keyvals[i]; 93 | private_BearHttpsResponse_write(response, (unsigned char*)keyval->key, private_BearsslHttps_strlen(keyval->key)); 94 | private_BearHttpsResponse_write(response, (unsigned char*)": ", 2); 95 | private_BearHttpsResponse_write(response, (unsigned char*)keyval->value, private_BearsslHttps_strlen(keyval->value)); 96 | private_BearHttpsResponse_write(response, (unsigned char*)"\r\n", 2); 97 | } 98 | 99 | if(self->body_type ==PRIVATE_BEARSSL_BODY_RAW){ 100 | char content_length[100]; 101 | snprintf(content_length,sizeof(content_length)-1,"Content-Length: %ld\r\n\r\n",self->body_raw.size); 102 | private_BearHttpsResponse_write(response,(unsigned char*)content_length,strlen(content_length)); 103 | private_BearHttpsResponse_write(response,self->body_raw.value,self->body_raw.size); 104 | } 105 | if(BearHttpsResponse_error(response)){ 106 | private_BearHttpsRequisitionProps_free(requisition_props); 107 | return response; 108 | } 109 | 110 | if(self->body_type == PRIVATE_BEARSSL_BODY_FILE){ 111 | 112 | FILE *file = fopen(self->body_file.path,"rb"); 113 | 114 | if(file == NULL){ 115 | BearHttpsResponse_set_error(response, "impssible to open file",BEARSSL_HTTPS_IMPOSSIBLE_TO_OPEN_FILE); 116 | private_BearHttpsRequisitionProps_free(requisition_props); 117 | return response; 118 | } 119 | char content_type[200]; 120 | snprintf(content_type,sizeof(content_type)-1, "Content-Type: %s\r\n",self->body_file.content_type); 121 | private_BearHttpsResponse_write(response,(unsigned char*)content_type,strlen(content_type)); 122 | 123 | fseek(file, 0, SEEK_END); 124 | long size = ftell(file); 125 | fseek(file, 0, SEEK_SET); 126 | char content_length[100]; 127 | sprintf(content_length,"Content-Length: %ld\r\n\r\n",size); 128 | private_BearHttpsResponse_write(response,(unsigned char*)content_length,strlen(content_length)); 129 | 130 | unsigned char send_buff[BEARSSL_BODY_CHUNK_SIZE]; 131 | while (1) { 132 | size_t read_size = fread(send_buff, 1, BEARSSL_BODY_CHUNK_SIZE, file); 133 | if (read_size == 0) { 134 | break; 135 | } 136 | private_BearHttpsResponse_write(response, send_buff, read_size); 137 | } 138 | fclose(file); 139 | 140 | } 141 | 142 | #ifndef BEARSSL_HTTPS_MOCK_CJSON 143 | if(self->body_type == PRIVATE_BEARSSL_BODY_JSON){ 144 | const char *content_type = "Content-Type: application/json\r\n"; 145 | private_BearHttpsResponse_write(response,(unsigned char*)content_type,strlen(content_type)); 146 | char * dumped = cJSON_Print(self->body_json.json); 147 | long dumped_size = private_BearsslHttps_strlen(dumped); 148 | char content_length[100]; 149 | sprintf(content_length,"Content-Length: %ld\r\n\r\n",dumped_size); 150 | private_BearHttpsResponse_write(response,(unsigned char*)content_length,strlen(content_length)); 151 | private_BearHttpsResponse_write(response,(unsigned char*)dumped,dumped_size); 152 | BearsslHttps_free(dumped); 153 | } 154 | 155 | #endif 156 | if(self->body_type == PRIVATE_BEARSSL_NO_BODY){ 157 | private_BearHttpsResponse_write(response, (unsigned char*)"\r\n", 2); 158 | } 159 | 160 | 161 | if(requisition_props->is_https){ 162 | if(br_sslio_flush(&response->ssl_io)){ 163 | BearHttpsResponse_set_error(response, "error flushing",BEARSSL_HTTPS_ERROR_FLUSHING); 164 | private_BearHttpsRequisitionProps_free(requisition_props); 165 | return response; 166 | } 167 | 168 | } 169 | 170 | private_BearHttpsResponse_read_til_end_of_headers_or_reach_limit(response,self->header_chunk_read_size,self->header_chunk_reallocator_factor); 171 | 172 | if(BearHttpsResponse_error(response)){ 173 | private_BearHttpsRequisitionProps_free(requisition_props); 174 | return response; 175 | } 176 | private_BearHttpsRequisitionProps_free(requisition_props); 177 | const int REDIRECT_CODEES[] = {301,302,303,307,308}; 178 | bool is_redirect = false; 179 | for(int i = 0; i < sizeof(REDIRECT_CODEES)/sizeof(int);i++){ 180 | if(response->status_code == REDIRECT_CODEES[i]){ 181 | is_redirect = true; 182 | break; 183 | } 184 | } 185 | 186 | if(is_redirect && i < self->max_redirections -1){ 187 | const char *location = BearHttpsResponse_get_header_value_by_sanitized_key(response,"location"); 188 | if(location == NULL){ 189 | return response; 190 | } 191 | BearHttpsRequest_set_url_with_ownership_config(self,(char*)location,BEARSSL_HTTPS_COPY ); 192 | BearHttpsResponse_free(response); 193 | response = NULL; 194 | continue; 195 | } 196 | // ends the loop and returns the last response 197 | break; 198 | } 199 | 200 | return response; 201 | } 202 | 203 | #endif -------------------------------------------------------------------------------- /docs/tutorials/headers.md: -------------------------------------------------------------------------------- 1 | # Working with HTTP Headers - Beginner's Guide 2 | 3 | HTTP headers are key-value pairs that provide additional information about the request or response. This tutorial will show you how to send headers with your requests and read headers from responses using BearHttpsClient. 4 | 5 | ## Sending Headers with Requests 6 | 7 | ### Adding Simple Headers 8 | 9 | To add headers to your request, use the `BearHttpsRequest_add_header()` function: 10 | 11 | ```c 12 | #include "BearHttpsClientOne.c" 13 | 14 | int main() { 15 | BearHttpsRequest *request = newBearHttpsRequest("https://httpbin.org/headers"); 16 | 17 | // Add custom headers 18 | BearHttpsRequest_add_header(request, "User-Agent", "MyApp/1.0"); 19 | BearHttpsRequest_add_header(request, "Accept", "application/json"); 20 | BearHttpsRequest_add_header(request, "Authorization", "Bearer your-token-here"); 21 | 22 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 23 | 24 | if(BearHttpsResponse_error(response)) { 25 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 26 | } else { 27 | const char *body = BearHttpsResponse_read_body_str(response); 28 | if(body != NULL) { 29 | printf("Response: %s\n", body); 30 | } 31 | } 32 | 33 | BearHttpsRequest_free(request); 34 | BearHttpsResponse_free(response); 35 | return 0; 36 | } 37 | ``` 38 | 39 | ### Adding Headers with Formatted Values 40 | 41 | You can also add headers with formatted values using `BearHttpsRequest_add_header_fmt()`: 42 | 43 | ```c 44 | #include "BearHttpsClientOne.c" 45 | 46 | int main() { 47 | BearHttpsRequest *request = newBearHttpsRequest("https://httpbin.org/headers"); 48 | 49 | int user_id = 12345; 50 | const char *session_token = "abc123xyz"; 51 | 52 | // Add formatted headers 53 | BearHttpsRequest_add_header_fmt(request, "X-User-ID", "%d", user_id); 54 | BearHttpsRequest_add_header_fmt(request, "X-Session", "session_%s", session_token); 55 | BearHttpsRequest_add_header_fmt(request, "X-Timestamp", "%ld", time(NULL)); 56 | 57 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 58 | 59 | if(!BearHttpsResponse_error(response)) { 60 | const char *body = BearHttpsResponse_read_body_str(response); 61 | if(body != NULL) { 62 | printf("Response: %s\n", body); 63 | } 64 | } 65 | 66 | BearHttpsRequest_free(request); 67 | BearHttpsResponse_free(response); 68 | return 0; 69 | } 70 | ``` 71 | 72 | ## Reading Headers from Responses 73 | 74 | ### Getting All Headers 75 | 76 | You can iterate through all response headers: 77 | 78 | ```c 79 | #include "BearHttpsClientOne.c" 80 | 81 | int main() { 82 | BearHttpsRequest *request = newBearHttpsRequest("https://httpbin.org/response-headers"); 83 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 84 | 85 | if(!BearHttpsResponse_error(response)) { 86 | int headers_count = BearHttpsResponse_get_headers_size(response); 87 | printf("Response has %d headers:\n", headers_count); 88 | 89 | for(int i = 0; i < headers_count; i++) { 90 | const char *key = BearHttpsResponse_get_header_key_by_index(response, i); 91 | const char *value = BearHttpsResponse_get_header_value_by_index(response, i); 92 | 93 | // ALWAYS check for NULL! 94 | if(key != NULL && value != NULL) { 95 | printf("%s: %s\n", key, value); 96 | } 97 | } 98 | } else { 99 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 100 | } 101 | 102 | BearHttpsRequest_free(request); 103 | BearHttpsResponse_free(response); 104 | return 0; 105 | } 106 | ``` 107 | 108 | ### Getting Specific Headers by Name 109 | 110 | To get a specific header value by its name: 111 | 112 | ```c 113 | #include "BearHttpsClientOne.c" 114 | 115 | int main() { 116 | BearHttpsRequest *request = newBearHttpsRequest("https://httpbin.org/json"); 117 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 118 | 119 | if(!BearHttpsResponse_error(response)) { 120 | // Get specific headers - ALWAYS check for NULL! 121 | const char *content_type = BearHttpsResponse_get_header_value_by_key(response, "Content-Type"); 122 | if(content_type != NULL) { 123 | printf("Content-Type: %s\n", content_type); 124 | } else { 125 | printf("Content-Type header not found\n"); 126 | } 127 | 128 | const char *server = BearHttpsResponse_get_header_value_by_key(response, "Server"); 129 | if(server != NULL) { 130 | printf("Server: %s\n", server); 131 | } else { 132 | printf("Server header not found\n"); 133 | } 134 | 135 | const char *content_length = BearHttpsResponse_get_header_value_by_key(response, "Content-Length"); 136 | if(content_length != NULL) { 137 | printf("Content-Length: %s\n", content_length); 138 | } 139 | } 140 | 141 | BearHttpsRequest_free(request); 142 | BearHttpsResponse_free(response); 143 | return 0; 144 | } 145 | ``` 146 | 147 | ### Using Sanitized Header Keys 148 | 149 | HTTP headers are case-insensitive, so you can use sanitized keys: 150 | 151 | ```c 152 | #include "BearHttpsClientOne.c" 153 | 154 | int main() { 155 | BearHttpsRequest *request = newBearHttpsRequest("https://httpbin.org/json"); 156 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 157 | 158 | if(!BearHttpsResponse_error(response)) { 159 | // These should all work the same way: 160 | const char *content_type1 = BearHttpsResponse_get_header_value_by_sanitized_key(response, "content-type"); 161 | const char *content_type2 = BearHttpsResponse_get_header_value_by_sanitized_key(response, "CONTENT-TYPE"); 162 | const char *content_type3 = BearHttpsResponse_get_header_value_by_sanitized_key(response, "Content-Type"); 163 | 164 | if(content_type1 != NULL) { 165 | printf("Content-Type (lowercase): %s\n", content_type1); 166 | } 167 | if(content_type2 != NULL) { 168 | printf("Content-Type (uppercase): %s\n", content_type2); 169 | } 170 | if(content_type3 != NULL) { 171 | printf("Content-Type (mixed case): %s\n", content_type3); 172 | } 173 | } 174 | 175 | BearHttpsRequest_free(request); 176 | BearHttpsResponse_free(response); 177 | return 0; 178 | } 179 | ``` 180 | 181 | ## Common Use Cases 182 | 183 | ### Authentication Headers 184 | 185 | ```c 186 | // Bearer token authentication 187 | BearHttpsRequest_add_header(request, "Authorization", "Bearer your-jwt-token"); 188 | 189 | // API key authentication 190 | BearHttpsRequest_add_header(request, "X-API-Key", "your-api-key"); 191 | 192 | // Basic authentication (base64 encoded username:password) 193 | BearHttpsRequest_add_header(request, "Authorization", "Basic dXNlcjpwYXNz"); 194 | ``` 195 | 196 | ### Content Type Headers 197 | 198 | ```c 199 | // For JSON data 200 | BearHttpsRequest_add_header(request, "Content-Type", "application/json"); 201 | 202 | // For form data 203 | BearHttpsRequest_add_header(request, "Content-Type", "application/x-www-form-urlencoded"); 204 | 205 | // For file uploads 206 | BearHttpsRequest_add_header(request, "Content-Type", "multipart/form-data"); 207 | ``` 208 | 209 | ### Custom Application Headers 210 | 211 | ```c 212 | // Custom tracking headers 213 | BearHttpsRequest_add_header(request, "X-Request-ID", "unique-request-id"); 214 | BearHttpsRequest_add_header(request, "X-Client-Version", "1.2.3"); 215 | BearHttpsRequest_add_header(request, "X-Platform", "Linux"); 216 | ``` 217 | 218 | ## Important Notes 219 | 220 | ⚠️ **CRITICAL**: Always check for NULL when reading headers! 221 | - `BearHttpsResponse_get_header_value_by_key()` can return NULL 222 | - `BearHttpsResponse_get_header_value_by_sanitized_key()` can return NULL 223 | - `BearHttpsResponse_get_header_key_by_index()` can return NULL 224 | - `BearHttpsResponse_get_header_value_by_index()` can return NULL 225 | 226 | ✅ **Best Practices**: 227 | - Always validate NULL returns before using header values 228 | - Use meaningful header names that follow HTTP conventions 229 | - Don't include sensitive information in custom headers unless necessary 230 | - Remember that header names are case-insensitive 231 | 232 | ## Complete Example: API Client with Headers 233 | 234 | ```c 235 | #include "BearHttpsClientOne.c" 236 | 237 | int main() { 238 | BearHttpsRequest *request = newBearHttpsRequest("https://jsonplaceholder.typicode.com/posts/1"); 239 | 240 | // Add common headers 241 | BearHttpsRequest_add_header(request, "User-Agent", "BearHttpsClient-Tutorial/1.0"); 242 | BearHttpsRequest_add_header(request, "Accept", "application/json"); 243 | BearHttpsRequest_add_header(request, "Accept-Language", "en-US,en;q=0.9"); 244 | 245 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 246 | 247 | if(!BearHttpsResponse_error(response)) { 248 | printf("Status Code: %d\n", BearHttpsResponse_get_status_code(response)); 249 | 250 | // Check response headers 251 | const char *content_type = BearHttpsResponse_get_header_value_by_key(response, "Content-Type"); 252 | if(content_type != NULL) { 253 | printf("Response Content-Type: %s\n", content_type); 254 | } 255 | 256 | const char *server = BearHttpsResponse_get_header_value_by_key(response, "Server"); 257 | if(server != NULL) { 258 | printf("Server: %s\n", server); 259 | } 260 | 261 | // Read the response body 262 | const char *body = BearHttpsResponse_read_body_str(response); 263 | if(body != NULL) { 264 | printf("\nResponse Body:\n%s\n", body); 265 | } 266 | } else { 267 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 268 | } 269 | 270 | BearHttpsRequest_free(request); 271 | BearHttpsResponse_free(response); 272 | return 0; 273 | } 274 | ``` 275 | 276 | This tutorial covers the essential aspects of working with HTTP headers in BearHttpsClient. Remember to always check for NULL returns and follow HTTP header conventions for the best results! 277 | -------------------------------------------------------------------------------- /docs/tutorials/query_param.md: -------------------------------------------------------------------------------- 1 | # Query Parameters Tutorial 2 | 3 | ## Introduction 4 | 5 | Query parameters are a fundamental part of HTTP requests that allow you to pass additional data to a server through the URL. This tutorial will guide you through handling query parameters using the BearHttpsClient library in C, showing you how to build URLs with query parameters for different use cases. 6 | 7 | ## Prerequisites 8 | 9 | Before starting this tutorial, ensure you have: 10 | - Basic knowledge of C programming 11 | - Understanding of HTTP requests and URLs 12 | - BearHttpsClient library properly set up in your project 13 | 14 | ## What are Query Parameters? 15 | 16 | Query parameters are key-value pairs appended to a URL after a question mark (`?`), separated by ampersands (`&`). They provide a way to send additional information to the server without using the request body. 17 | 18 | **URL Structure with Query Parameters:** 19 | ``` 20 | https://api.example.com/search?q=programming&limit=10&sort=date 21 | ``` 22 | 23 | In this example: 24 | - `q=programming` - search query 25 | - `limit=10` - maximum number of results 26 | - `sort=date` - sorting preference 27 | 28 | ## Building URLs with Query Parameters 29 | 30 | ### Simple Example: Single Parameter 31 | 32 | ```c 33 | #include "BearHttpsClientOne.c" 34 | 35 | int main() { 36 | // Simple search with one parameter 37 | char url[256]; 38 | const char *search_term = "C programming"; 39 | 40 | // Build URL with query parameter 41 | snprintf(url, sizeof(url), "https://api.github.com/search/repositories?q=%s", search_term); 42 | 43 | BearHttpsRequest *request = newBearHttpsRequest(url); 44 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 45 | 46 | if(BearHttpsResponse_error(response)) { 47 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 48 | } else { 49 | printf("Status Code: %d\n", BearHttpsResponse_get_status_code(response)); 50 | const char *body = BearHttpsResponse_read_body_str(response); 51 | if(body != NULL) { 52 | printf("Response received successfully\n"); 53 | } 54 | } 55 | 56 | BearHttpsRequest_free(request); 57 | BearHttpsResponse_free(response); 58 | return 0; 59 | } 60 | ``` 61 | 62 | ### Advanced Example: Multiple Parameters 63 | 64 | ```c 65 | #include "BearHttpsClientOne.c" 66 | 67 | // Helper function to URL encode special characters 68 | void simple_url_encode(const char *input, char *output, size_t output_size) { 69 | size_t input_len = strlen(input); 70 | size_t output_pos = 0; 71 | 72 | for (size_t i = 0; i < input_len && output_pos < output_size - 1; i++) { 73 | char c = input[i]; 74 | if (c == ' ') { 75 | if (output_pos < output_size - 3) { 76 | strcpy(output + output_pos, "%20"); 77 | output_pos += 3; 78 | } 79 | } else if (c == '&') { 80 | if (output_pos < output_size - 3) { 81 | strcpy(output + output_pos, "%26"); 82 | output_pos += 3; 83 | } 84 | } else if (c == '=') { 85 | if (output_pos < output_size - 3) { 86 | strcpy(output + output_pos, "%3D"); 87 | output_pos += 3; 88 | } 89 | } else { 90 | output[output_pos++] = c; 91 | } 92 | } 93 | output[output_pos] = '\0'; 94 | } 95 | 96 | int main() { 97 | // Build URL with multiple query parameters 98 | char url[512]; 99 | char encoded_query[128]; 100 | 101 | const char *search_query = "machine learning"; 102 | const char *language = "python"; 103 | int per_page = 5; 104 | const char *sort = "stars"; 105 | 106 | // Encode the search query 107 | simple_url_encode(search_query, encoded_query, sizeof(encoded_query)); 108 | 109 | // Build complete URL with multiple parameters 110 | snprintf(url, sizeof(url), 111 | "https://api.github.com/search/repositories?q=%s+language:%s&per_page=%d&sort=%s", 112 | encoded_query, language, per_page, sort); 113 | 114 | printf("Requesting URL: %s\n", url); 115 | 116 | BearHttpsRequest *request = newBearHttpsRequest(url); 117 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 118 | 119 | if(BearHttpsResponse_error(response)) { 120 | printf("Error: %s\n", BearHttpsResponse_get_error_msg(response)); 121 | } else { 122 | printf("Status Code: %d\n", BearHttpsResponse_get_status_code(response)); 123 | 124 | // Parse JSON response 125 | const cJSON *json = BearHttpsResponse_read_body_json(response); 126 | if(json != NULL) { 127 | const cJSON *total_count = cJSON_GetObjectItem(json, "total_count"); 128 | const cJSON *items = cJSON_GetObjectItem(json, "items"); 129 | 130 | if(total_count != NULL && cJSON_IsNumber(total_count)) { 131 | printf("Total repositories found: %d\n", total_count->valueint); 132 | } 133 | 134 | if(items != NULL && cJSON_IsArray(items)) { 135 | int array_size = cJSON_GetArraySize(items); 136 | printf("Showing %d repositories:\n\n", array_size); 137 | 138 | for(int i = 0; i < array_size; i++) { 139 | const cJSON *repo = cJSON_GetArrayItem(items, i); 140 | if(repo != NULL) { 141 | const cJSON *name = cJSON_GetObjectItem(repo, "name"); 142 | const cJSON *stars = cJSON_GetObjectItem(repo, "stargazers_count"); 143 | const cJSON *description = cJSON_GetObjectItem(repo, "description"); 144 | 145 | if(name != NULL && cJSON_IsString(name)) { 146 | printf("%d. %s", i + 1, name->valuestring); 147 | } 148 | if(stars != NULL && cJSON_IsNumber(stars)) { 149 | printf(" ⭐ %d", stars->valueint); 150 | } 151 | if(description != NULL && cJSON_IsString(description)) { 152 | printf("\n %s", description->valuestring); 153 | } 154 | printf("\n\n"); 155 | } 156 | } 157 | } 158 | } else { 159 | const char *body = BearHttpsResponse_read_body_str(response); 160 | if(body != NULL) { 161 | printf("Raw response: %s\n", body); 162 | } 163 | } 164 | } 165 | 166 | BearHttpsRequest_free(request); 167 | BearHttpsResponse_free(response); 168 | return 0; 169 | } 170 | ``` 171 | 172 | ## Common Query Parameter Use Cases 173 | 174 | ### 1. Pagination 175 | ```c 176 | // Example: Fetch page 2 with 10 items per page 177 | char url[256]; 178 | int page = 2; 179 | int limit = 10; 180 | snprintf(url, sizeof(url), "https://api.example.com/users?page=%d&limit=%d", page, limit); 181 | ``` 182 | 183 | ### 2. Filtering 184 | ```c 185 | // Example: Filter users by status and role 186 | char url[256]; 187 | const char *status = "active"; 188 | const char *role = "admin"; 189 | snprintf(url, sizeof(url), "https://api.example.com/users?status=%s&role=%s", status, role); 190 | ``` 191 | 192 | ### 3. Sorting 193 | ```c 194 | // Example: Sort results by creation date in descending order 195 | char url[256]; 196 | const char *sort_by = "created_at"; 197 | const char *order = "desc"; 198 | snprintf(url, sizeof(url), "https://api.example.com/posts?sort=%s&order=%s", sort_by, order); 199 | ``` 200 | 201 | ### 4. Search with Filters 202 | ```c 203 | // Example: Search with multiple filters 204 | char url[512]; 205 | char encoded_search[128]; 206 | const char *search_term = "web development"; 207 | const char *category = "tutorials"; 208 | int min_rating = 4; 209 | 210 | simple_url_encode(search_term, encoded_search, sizeof(encoded_search)); 211 | snprintf(url, sizeof(url), 212 | "https://api.example.com/content?search=%s&category=%s&min_rating=%d", 213 | encoded_search, category, min_rating); 214 | ``` 215 | 216 | ## Best Practices 217 | 218 | ### 1. Always URL Encode Special Characters 219 | Special characters in query parameters must be properly encoded: 220 | - Space becomes `%20` 221 | - `&` becomes `%26` 222 | - `=` becomes `%3D` 223 | - `+` becomes `%2B` 224 | 225 | ### 2. Handle NULL Values Safely 226 | ```c 227 | const cJSON *json = BearHttpsResponse_read_body_json(response); 228 | if(json != NULL) { 229 | // Safe to process JSON 230 | const cJSON *item = cJSON_GetObjectItem(json, "key"); 231 | if(item != NULL && cJSON_IsString(item)) { 232 | printf("Value: %s\n", item->valuestring); 233 | } 234 | } else { 235 | printf("Failed to parse JSON response\n"); 236 | } 237 | ``` 238 | 239 | ### 3. Check Response Status 240 | ```c 241 | if(BearHttpsResponse_error(response)) { 242 | printf("Request failed: %s\n", BearHttpsResponse_get_error_msg(response)); 243 | return 1; 244 | } 245 | 246 | int status_code = BearHttpsResponse_get_status_code(response); 247 | if(status_code != 200) { 248 | printf("HTTP Error: %d\n", status_code); 249 | return 1; 250 | } 251 | ``` 252 | 253 | ### 4. Limit URL Length 254 | URLs have practical length limits (usually around 2048 characters). For very long parameter lists, consider using POST requests instead. 255 | 256 | ## Real-World Example: Weather API 257 | 258 | ```c 259 | #include "BearHttpsClientOne.c" 260 | 261 | int fetch_weather(const char *city, const char *api_key) { 262 | char url[512]; 263 | char encoded_city[128]; 264 | 265 | // URL encode the city name 266 | simple_url_encode(city, encoded_city, sizeof(encoded_city)); 267 | 268 | // Build URL with query parameters 269 | snprintf(url, sizeof(url), 270 | "https://api.openweathermap.org/data/2.5/weather?q=%s&appid=%s&units=metric", 271 | encoded_city, api_key); 272 | 273 | BearHttpsRequest *request = newBearHttpsRequest(url); 274 | BearHttpsResponse *response = BearHttpsRequest_fetch(request); 275 | 276 | if(BearHttpsResponse_error(response)) { 277 | printf("Error fetching weather: %s\n", BearHttpsResponse_get_error_msg(response)); 278 | BearHttpsRequest_free(request); 279 | BearHttpsResponse_free(response); 280 | return 1; 281 | } 282 | 283 | const cJSON *json = BearHttpsResponse_read_body_json(response); 284 | if(json != NULL) { 285 | const cJSON *main = cJSON_GetObjectItem(json, "main"); 286 | const cJSON *weather_array = cJSON_GetObjectItem(json, "weather"); 287 | 288 | if(main != NULL) { 289 | const cJSON *temp = cJSON_GetObjectItem(main, "temp"); 290 | const cJSON *humidity = cJSON_GetObjectItem(main, "humidity"); 291 | 292 | printf("Weather in %s:\n", city); 293 | if(temp != NULL && cJSON_IsNumber(temp)) { 294 | printf("Temperature: %.1f°C\n", temp->valuedouble); 295 | } 296 | if(humidity != NULL && cJSON_IsNumber(humidity)) { 297 | printf("Humidity: %d%%\n", humidity->valueint); 298 | } 299 | } 300 | 301 | if(weather_array != NULL && cJSON_IsArray(weather_array)) { 302 | const cJSON *weather = cJSON_GetArrayItem(weather_array, 0); 303 | if(weather != NULL) { 304 | const cJSON *description = cJSON_GetObjectItem(weather, "description"); 305 | if(description != NULL && cJSON_IsString(description)) { 306 | printf("Condition: %s\n", description->valuestring); 307 | } 308 | } 309 | } 310 | } 311 | 312 | BearHttpsRequest_free(request); 313 | BearHttpsResponse_free(response); 314 | return 0; 315 | } 316 | 317 | int main() { 318 | const char *api_key = "your_api_key_here"; 319 | const char *city = "New York"; 320 | 321 | fetch_weather(city, api_key); 322 | return 0; 323 | } 324 | ``` 325 | 326 | ## Conclusion 327 | 328 | Query parameters are essential for building flexible and powerful HTTP requests. With BearHttpsClient, you can easily construct URLs with query parameters for various use cases like searching, filtering, pagination, and API configuration. Remember to always: 329 | 330 | 1. URL encode special characters 331 | 2. Check for NULL returns from JSON parsing functions 332 | 3. Validate HTTP response status codes 333 | 4. Handle errors gracefully 334 | 335 | This knowledge will help you effectively consume REST APIs and build robust C applications that interact with web services. 336 | --------------------------------------------------------------------------------