Tip of the day: Check out Special users on how to give trusted users/bots more rights without making them IRCOp.

Dev:URL API

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

You can do web requests from a module, for example a HTTPS callout to receive some JSON.

Below we explain how to do this. Behind the scenes UnrealIRCd keeps things safe, even if the server is REHASHed between starting the request and receiving the response (and your module is reloaded) things will still work properly and you will still receive the response.

Registering your callback

In your MOD_INIT() use RegisterApiCallbackWebResponse() to register your response handler:

/* Forward declaration */
void my_download_complete(OutgoingWebRequest *request, OutgoingWebResponse *response);

MOD_INIT()
{
[..]
        RegisterApiCallbackWebResponse(modinfo->handle, "my_download_complete", my_download_complete);
        return MOD_SUCCESS;
}

Doing the web request

Create an OutgoingWebRequest struct and then fill in members. You must set ->apicallback to the name of the api callback that you registered in MOD_INIT above.

Example:

OutgoingWebRequest *w = safe_alloc(sizeof(OutgoingWebRequest));
safe_strdup(w->url, cfg.url);
w->http_method = HTTP_METHOD_GET;
safe_strdup(w->apicallback, "cbl_download_complete");
url_start_async(w);

You can also set more fields before you call url_start_async, for example setting w->callback_data if you need to keep track of different requests.

For all fields, see OutgoingWebRequest in include/struct.h, viewable online here

Receiving the web response

Here is where your my_download_complete comes into play. In this example we expect to receive a JSON response, which we try to parse.

See also docs for OutgoingWebRequest and OutgoingWebResponse to see all struct members of request and response.

void my_download_complete(OutgoingWebRequest *request, OutgoingWebResponse *response)
{
    json_t *result;
    json_error_t jerr;

    if (response->errorbuf || !response->memory)
    {
        unreal_log(ULOG_INFO, "mymod", "MYMOD_BAD_RESPONSE", NULL,
                   "Error while trying to check $url: $error",
                   log_data_string("url", request->url),
                   log_data_string("error", response->errorbuf ? response->errorbuf : "No data (body) returned"));
        return;
    }

    // result->memory contains all the data of the web response, in our case
    // we assume it is a JSON response, so we are going to parse it.
    // If you were expecting BINARY data then you can still use result->memory
    // but then have a look at the length in result->memory_len.
    result = json_loads(response->memory, JSON_REJECT_DUPLICATES, &jerr);
    if (!result)
    {
        unreal_log(ULOG_INFO, "mymod", "MYMOD_BAD_RESPONSE", NULL,
                   "Error while trying to check $url: JSON parse error",
                   log_data_string("url", request->url));
        return;
    }

    // Now do something useful with the json in 'result'. For how to work
    // with json objects, see the Jansson API documentation at
    // https://jansson.readthedocs.io/en/latest/ e.g. json_object_get().
    // There are also UnrealIRCd specific functions (to make things easier)
    // such as json_object_get_string(), json_object_get_integer(),
    // json_object_get_boolean().

    // Finally, free 'result' and return
    json_decref(result);
}