Releases: Qriist/LibQurl
LibQurl v1.2.0
This update features a slew of enhancements and fixes primarily aimed at smoothing API interactions.
- Added
DecodeJwt()to return an unobfuscatedMapof the input JWT token. DecodeBase64()accepts a third parameter to mark the input as Base64URL, which will do a couple extra pre-transformations before decoding as Base64.Timestamp()now accepts a parameter to return multiple common internet standard formats.- Acceptable paramaters:
Readable,SQL,ODBC,RFC 3339,Unix,asctime,RFC 1123,RFC 2822,FILETIME,EXIF, andRFC 850. See that method for output examples.
- Acceptable paramaters:
SetPost()now returns the input's mimetype. This is useful for persnickety servers demanding an exactContent-Typeto be reported in the headers.- Due to a behavioral quirk in libmagic, json data examined in memory is reported as
text/plain. However, since passing an Object/Map/Array always results in a dumped json being staged, there is a specific override for that group which returnsapplication/json.
- Due to a behavioral quirk in libmagic, json data examined in memory is reported as
SetPost()now explicitly sets CUSTOMREQUEST to POST. This fixed a bug where POSTs would fail after GETs were sent after POSTs were sent.- ...yeah that was as dumb as you might imagine to track down.
- Fixed
SetPost()unintentionally assigning POST data to the default handle ClearPost()now also zeros libcurl's UPLOAD flag.ClearPost()now explicitly sets CUSTOMREQUEST to GET for more intuitive behavior in mixed-request usage.
LibQurl v1.1.1
Fixed a dependency typo that affected fresh installs (but not upgrades) of the library.
LibQurl v1.1.0
Just a small update today. This version includes one new wrapped function introduced in the latest libcurl as well as enhanced error handling.
- Added
GetMultiInfo()for gathering basic job stats on a givenmulti_handle. - Added error handling to all dll calls to around ~30 core functions. Many already had this handling but now they all do!
- As a reminder, an info snapshot of any discovered errors are pushed into the
curl.caughtErrorsarray.
- As a reminder, an info snapshot of any discovered errors are pushed into the
- Fixed an improperly set callback variable for file uploads in
SetPost(). - Fixed an incorrect
easy_handlelookup inAttachMimeAsPart().
The error handling in particular should be useful in a production project as there's an enormous amount of program state information captured whenever libcurl flags an issue.
LibQurl v1.0.0
This version sees a whole slew of enhancements that include better MIME tracking, websocket interactions, and the option to enable libcurl's debug data. In fact, nearly the entirety of libcurl has now been wrapped! More on that after the patch notes.
- Added
GetMimeType()for identifying the mime type of any arbitrary input. This is the same text string that would be auto-sent as part of a mime upload, exposed as a one-shot operation. - Added tracking for nested
mime_handles. - Added better tracking for
mime_parts, including when that part is a nestedmime_handle. - Using
MimeCleanup()on a nestedmime_handlewill return now harmlessly. - Added
GetOpt(),MultiGetOpt(), andShareOpt()to return whatever LibQurl is tracking for the given option on a given handle.- Options that haven't yet been set will return a
Nulltype instead ofunset. This is to simplifyType()checks and error handling when querying tracked data.
- Options that haven't yet been set will return a
- Added
ExportSSLs()andImportSSLs() - Added
EnableDebug()to enable verbose logging on the giveneasy_handle. - Use
PollDebug()to get a formated report of debug data.- Body and ssl data is currently filtered from the report. I'll enhance the handling if somebody has a need for it.
- Added
ConfigureDebug()to set the verbosity level of the debug report. This can be called either before or afterEnableDebug(), but must be called before any transfers have been intiated. - Added
Timestamp()to get a pre-formatted, sortable UTC timestamp.- Example:
2025-07-27 15:36:07.746
- Example:
- Added
WebSocketConvert()to convert a giveneasy_handleto a websocket connection. - Added
WebSocketSend()andWebSocketRecieve()for handling websocket data. As usual, pretty much all of AHK's normal data types are acceptable inputs.- These are both explicitly synchronous operations. Their underlying operations are a little different because they do not use the write callback provided to
curl_easy_perform. - Additionally, the websocket functions were particularly fickle to wrap. Please be sure to provide feedback if something breaks as I do not have a good use case to test against.
- These are both explicitly synchronous operations. Their underlying operations are a little different because they do not use the write callback provided to
- Added
SetWebSocketFrameSize()to have the library automatically split large outgoing frames of data into as many partial frames as required to send the entire input. The threshold is set pereasy_handleand defaults to 14kb.- Note that the full un-split size is reported in the first partial frame, and some servers will still use that to reject uploads above a given size threshold. It is on the user to understand the constraints of the system they are connecting to.
- Added the
initMemMapoptional parameter. If set, this map will be used to pass advanced usage callback pointers to curl's loading routine.- I recommend not setting
initMemMapunless you know what you're doing.
- I recommend not setting
- Removed
SetOpts()as there's just way too many options (300+) to try to account for, each with different types of returns and varied processing exceptions. I'd be fighting the design of everything else I've written to try to make it work. - While not used by LibQurl itself,
curl.exeis now included alongside the rest of the generated binaries as it will make errors related to a specific version easier to track down. - Fixed an incorrect parameter name in the
GetInfosignature.
As I said above, almost all of libcurl has now been tended to; there's only two more sections of code worth wrapping. Both of those may or may not happen for similar reasons.
The first is the pair of pushheader functions. While parsing the function data would be easy enough, these require a public (read: accessible) persistent remote server connection that also sends push requests on command. Without that, I can't write sensible logic. Put simply, I don't have a test case to build against.
The second set of functions is the multi_socket system. Implementing the self-driving timer mechanisms shouldn't be overly difficult and I plan to eventually upgrade LibQurl's current multi interface to use it. (Or, at least, offer that mode alongside what's now available.) However, as with the pushheader dilemma, the more advanced functionality of merging and driving user-provided sockets with those generated by libcurl is off the table until I have a test case to build a sensible implementation against. Some local testing of the current Async() implementation has revealed that it scales to at least 250 concurrent transfers without a significant drop in performance - plenty performant for virtually everything except the most demanding servers.
With those caveats in mind, I don't anticipate any major LibQurl interface changes from here on out, so I feel comfortable bumping to a full production-worthy version.
Lastly, a couple additional notes about what's coming up next.
There's already error handling on the most important parts of the library, but I intended to enhance the coverage so that LibQurl gives a full proper trace where ever something gets invoked. I also want to put a little effort into eliminating unneccesarry pointer chasing during the various callback routines since I know for sure there's a bit of optimization to be gained there after some slight refactoring.
As both of these are sweeping under-the-hood enhancements with no immediately discernable effect on the library's operations, I felt it reasonable enough to get this release out first.
LibQurl v0.94.0
There are two main features in this update, both of which deal directly with the handling of transfer data.
- Enabled proper chunked uploads with
SetPost(), meaning large file transfers don't need to reside entirely in memory for the duration of the upload.- MIME uploads already did this natively but libcurl required building a custom callback function for basic POSTs for some reason.
- Added
WriteToMagic()for file downloads. This is a hybrid mode that starts out identical toWriteToMem()but will automagically flush to disk and act asWriteToFile()when a defined size threshold is reached.- The default flush threshold is 50mb. The method's first parameter adjusts to whatever size is provided.
- Any flushed files get saved to
A_Temp "\LibQurl\"with a name based on timestamp and file handle. All temp files are deleted when the class goes through its exit routine, though its (hopefully) designed so that multiple running scripts won't interfere with each other's temp files. - For plain text,
GetLastBody()handles this new method without any implementation modifications. If you need to work with binary data from this method, useType(curl.GetLastBody("Object"))to determine if you should use Buffer or File calls. - My personal intended use case of the Magic mode is with REST APIs that don't paginate bulk requests. This provides the speed benefits of Memory mode while protecting the script (and system) against unpredictable payload size spikes.
- Several major improvements to the build script, including integrating it into the release generation script.
LibQurl v0.93.0
This release mainly sees quality of life enhancements to dealing with transfer data.
- Added
EncodeBase64()/DecodeBase64()methodsEncodeBase64()will accept all the usual inputs to output a Base64 stringDecodeBase64()returns a decoded string by default, or an optional raw buffer
- Added
GetLastStatus()to quickly check aneasy_handle's last HTTP status code - Added real time progress checking methods
GetProgress()returns a Map with the raw byte values for further processing- The convenice methods
DownloadPercentandUploadPercentwill return the giveneasy_handle's completion% rounded to 2 decimals
- Fixed 3 default assignments that were missed in the last release's mass change
LibQurl v0.92.0
Major breaking functionality change in this release: athough default handles are still created for ease of use, additional handles are no longer switched to automatically.
The reason for this is I discovered that there was a sort of scoping problem where AHK would treat different instances of the class as having the same pool of dll data, presumably because Windows only loads the dll once. Fortunately, curl and LibQurl are both well equipped to handle this behavior by defining different handle pools; the class just required a change to keep from stepping on itself.
Other enhancements and fixes include:
- Wrapped libmagic for use in POST and MIME operations, eliminating the clunky commandline wrap
- Added
ClearPost()to properly yeet POST data from aneasy_handle - Memory buffers now auto-expand as data comes in, instead of spawning with a fixed size
- Allowed memory buffers to truncate to final download size (there were sometimes trailing binary zeroes)
- Added
StrCompare()to allow usage of libcurl's portable string comparison functions - removed a redundant string->buffer operation
- removed a deprecated variable in
EasyInit()
LibQurl v0.91.0
Small bugfix release.
- Fixed two instances of an incorrect global declaration.
- Yet another attempt at fixing autoload from common install patterns.
LibQurl v0.90.0
Added most of the rest of the MIME functions. These mostly focus on server-specified formatting requirements.
What's new in this release:
- Added
MimeTreatPartAsFile(). This tells the server that it should consider thatmime_partas a file with the given file name. - Added
AttachMimeAsPart(). This allows you to embed an entire othermime_handleas a singlemime_part. Because there's no way to undo this action, LibQurl will stop tracking the embeddedmime_handleand any subsequent calls to thatmime_handlewill throw an error. Also, using this function after using the embeddedmime_handlein a transfer will fail; you have to rebuild the entire structure from scratch in order to embed. - Added
MimePartEncoder()/SetMimePartHeaders(). These are difficult to get feedback on without a server specifically designed to echo these low-level aspects. While libcurl reports no error, I currently have no proper test case to verify against. - Allowed
SetHeaders()/SetMimePartHeaders()and custom header inputs to also accept Objects (in addition to Arrays and Maps).
LibQurl v0.89.0
This update wraps the most important parts of curl's MIME api. Which is to say, those functions that are immediately required to push data. Read the patch notes carefully to understand how it works.
What's new in this release:
- Added
MimeInit(), which accepts (or defaults to) aneasy_handle, and returns amime_handle.- While
EasyInit()creates some initial mime-related variables when called,MimeInit()is never called automatically due to how its mere inclusion modifies outgoing data. Thus, unlike with other handles, it is on the user to explicitly callMimeInit()to generate a defaultmime_handle. - Per curl's design,
mime_handles are attached to that specificeasy_handlefor its lifetime. As such, a givenmime_handlewill only ever modify theeasy_handleit was created with.
- While
- Added
AttachMimePart()to add content to amime_handle. This will create themime_part, set its name, pass thepartContentdata to libcurl, auto-set the mimetype using magic numbers, and return themime_partfor further processing. The underlying methods are publicly available but their explicit use is discouraged to ensure consistency.- As with similar methods, you can pass almost anything for
partContent: String, Integer, Object, Map, Array, Buffer, and FileObjects are all uploaded appropriately.
- As with similar methods, you can pass almost anything for
- Added
MimeCleanup(). This will safely close out the givenmime_handleand all associatedmime_parts. - Fixed finding the libcurl dll from an Aris installation.
NOTE: Incidentally, the magic numbers which determine mimetype come from a Windows build of Unix's file command. While this works flawlessly, it is somewhat inefficient because of the need to temporarily dump variables to disk (though FileObjects are unaffected). My intention is to come back at a later date and incorporate file's underlying library, libmagic. It's just low priority due to having a technically working solution.