CURLOPT_HSTSREADFUNCTION(3)
π CURLOPT_HSTSREADFUNCTION π
okay so bestie, this one is from the Library Functions Manual and it's literally all about feeding your HSTS hosts into libcurl with your own lil callback π no cap.
β¨ NAME β¨
CURLOPT_HSTSREADFUNCTION β the read callback for HSTS hosts, aka the glow-up your HSTS cache deserves π
πΈ SYNOPSIS πΈ
#include <curl/curl.h>
struct curl_hstsentry {
char *name;
size_t namelen;
unsigned int includeSubDomains:1;
char expire[18]; /* YYYYMMDD HH:MM:SS [null-terminated] */
};
CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *sts, void *clientp);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HSTSREADFUNCTION, hstsread);
π¦ DESCRIPTION π¦
Pass a pointer to your callback function, exactly like the prototype up there shows you π
So this callback gets called by libcurl repeatedly when it populates the in-memory HSTS cache. Like, it's not a one-and-done thing β libcurl keeps coming back for more, and honestly? iconic behavior.
Set the clientp argument with the CURLOPT_HSTSREADDATA(3) option β or it's just NULL, no pressure π«Ά
When this callback is invoked, the sts pointer points to a populated struct. Here's your checklist, bestie:
- Copy the hostname to
name(no longer thannamelenbytes). Make it null-terminated β¨ - Set
includeSubDomainstoTRUEorFALSE - Set
expireto a date stamp, or a zero length string for forever
β οΈ heads up: a wrong date stamp format might cause the name to not get accepted. so like, format it right the first time fr π
The callback should return CURLSTS_OK if it returns a name and is prepared to be called again (for another host), or CURLSTS_DONE if it has no entry to return. It can also return CURLSTS_FAIL to signal error. Returning CURLSTS_FAIL stops the transfer from being performed and makes CURLE_ABORTED_BY_CALLBACK get returned. so like, that's the nuclear option, use it with intention π
π¨ and listen β this option does not enable HSTS. you need to use CURLOPT_HSTS_CTRL(3) to do that. don't skip that step bestie, otherwise you're just out here doing nothing π
π DEFAULT π
NULL β no callback. literally nobody home π
π PROTOCOLS π
This functionality affects http only. that's it. that's the whole vibe check.
β EXAMPLE β
struct priv {
void *custom;
};
static CURLSTScode hsts_cb(CURL *easy, struct curl_hstsentry *sts,
void *clientp)
{
/* populate the struct as documented */
return CURLSTS_OK;
}
int main(void)
{
CURL *curl = curl_easy_init();
if(curl) {
struct priv my_stuff;
CURLcode result;
/* set HSTS read callback */
curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hsts_cb);
/* pass in suitable argument to the callback */
curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &my_stuff);
result = curl_easy_perform(curl);
}
}
see how the CURLOPT_HSTSREADDATA gets the &my_stuff? that's the clientp babe, that's how it finds its way back to you π«Ά
π AVAILABILITY π
Added in curl 7.74.0 β so if you're on anything older than that, it's giving before-our-time, sorry bestie π
π RETURN VALUE π
This returns CURLE_OK. slay. no drama, no surprises, just good vibes β¨
π₯ SEE ALSO π₯
go read those next, iykyk π
later bestie π¦ β this gem's from libcurl, dated 2026-10-12, and it ate, no crumbs. mwah π
π¦ where this page comes from
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- fedora 44: libcurl-devel 8.18.0-14.fc44 Β· curl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms