babelouest / ulfius

Web Framework to build REST APIs, Webservices or any HTTP endpoint in C language. Can stream large amount of data, integrate JSON data with Jansson, and create websocket services
https://babelouest.github.io/ulfius
GNU Lesser General Public License v2.1
1.09k stars 181 forks source link

Using HTTPS for REST calls #278

Open DanujaSW opened 2 months ago

DanujaSW commented 2 months ago

Hi,

I have set up the function below to send a HTTP GET request to a REST endpoint. May I know if libulfius supports REST calls via HTTPS?

If so, may I have some guidance on how this can be implemented?

Thanks

Function:

char* get_update(void) {
    struct _u_request request;
    struct _u_response response;
    json_t *json_response;
    char *json_str = NULL;

    //Initialize the request and response structures
    ulfius_init_request(&request);
    ulfius_init_response(&response);

    //Set the HTTP method and URL
    request.http_verb = strdup("GET");
    request.http_url = strdup(UPDATE_URL);

    //send the HTTP request
    if (ulfius_send_http_request(&request, &response) == U_OK) {
        if (response.status == 200) {
            json_error_t error;
            json_response = ulfius_get_json_body_response(&response, &error);
            if (json_response) {
                //obtain the JSON response
                json_str = json_dumps(json_response, JSON_INDENT(2));
                //Decrese reference count of JSON object to free memory
                json_decref(json_response);
            }
            else {
                fprintf(stderr,"Error parsing JSON response: %s\n", error.text);
                json_str = "ERROR";
            }
        }
        else {
            fprintf(stderr, "HTTP request failed with status %d\n", response.status);
        }
    }
    else {
        json_str = "ERROR";
        fprintf(stderr, "Error sending HTTP request\n");
    }

    //Clean up 
    ulfius_clean_request(&request);
    ulfius_clean_response(&response);

    //Free the memory allocated by strdup
    free(request.http_verb);
    free(request.http_url);

    return json_str;

}
babelouest commented 2 months ago

Hello @DanujaSW ,

It's a guess but it could be because your https service uses an invalid certificate (self-signed certificate for example). You can disable this check by setting request.check_server_certificate to 0.

To help you with more verbose information, you can enable yder logs in your program. Look at the request_example/client.c for more send request examples.

I also suggest using ulfius_set_request_properties for readability:

struct _u_request request;
ulfius_init_request(&request);
if (ulfius_set_request_properties(&request, U_OPT_HTTP_VERB, "GET", U_OPT_HTTP_URL, UPDATE_URL, U_OPT_CHECK_SERVER_CERTIFICATE, 0, U_OPT_NONE) == U_OK) {
  // Send the request, then parse the response
} else {
  // Error on ulfius_set_request_properties
}
DanujaSW commented 2 months ago

Hi @babelouest ,

Thank you for the clarification.

The function that I provided initially works for an HTTP request. So would the process to convert it to work with HTTPS requests be the following:

  1. Change my current HTTP URL #define POLICY_UPDATE_URL "http://server-address/policy-update" to be an HTTPS URL #define POLICY_UPDATE_URL "https://server-address/policy-update"
  2. Add in the CA certificate of the server to my system
  3. Set U_OPT_CHECK_SERVER_CERTIFICATE to 1 in ulfius_set_request_properties()

Is this the process that I need to follow or would there be any additional steps needed?

babelouest commented 2 months ago

I don't know about your system configuration so I won't assume it will work or not. The process you mention at least is worth a try, but I don't know if this would fix your issue.

But the option U_OPT_CHECK_SERVER_CERTIFICATE is set to 1 by default so you don't have to specify it unless you previously set it to 0.

You can also dig deeper by testing with libcurl (which ulfius' out request is based on) to master your requests parameters and response.

DanujaSW commented 2 months ago

Thank you for the advice. I will make some changes using the approaches you suggested and let you know how it goes