Repository navigation
Production Examples
This page is for presenting actual working LibQurl code from around different projects I've used it in.
These aren't intended to be stand alone tutorial examples. Rather, they demonstrate a spectrum of complex problems solved in various ways using the LibQurl interfaces.
This briefly probes a repo to decide if we should bother executing the rest of a build script.
Code
;determine the latest SQLite3MultipleCiphers source code
;this is done before creating the first cmd window to prevent flashes if there's nothing to do
useragent := "LibQurl/1.2.0 (probably)"
curl.SetOpt("USERAGENT", useragent) ;github freaks out if you lack useragent
url := "https://api.github.com/repos/utelle/SQLite3MultipleCiphers/releases/latest"
curl.SetOpt("URL", url)
curl.Sync()
mcObj := JSON.Load(curl.GetLastBody())
currentMcVersion := mcObj["tag_name"]
currentMcName := mcObj["name"]
buildIni := A_ScriptDir "\build.ini"
savedMcVersion := IniRead(buildIni, "build", "savedMcVersion", 0)
savedSqlarVersion := IniRead(buildIni, "build", "savedSqlarVersion", 0)
If (currentMcVersion = savedMcVersion)
&& (currentMcVersion = savedSqlarVersion)
ExitAppA simple demonstration of an API's initial token exchange from stored values.
Code
;navigating Blizzard's OAuth2 nonsense
client := IniRead(A_ScriptDir "\auth\auth.ini","auth","Hearthstone_Client")
secret := IniRead(A_ScriptDir "\auth\auth.ini","auth","Hearthstone_Secret")
url := "https://oauth.battle.net/token"
curl.SetOpt("URL",url)
curl.SetOpt("USERNAME",client)
curl.SetOpt("PASSWORD",secret)
curl.SetHeaders(Map("Content-Type","application/x-www-form-urlencoded"))
curl.SetPost("grant_type=client_credentials")
curl.Sync()
auth := JSON.load(curl.GetLastBody())This demonstrates releasing LibQurl’s file handle so a subsequent tool (certutil) can acquire the exclusive access it demands. The transfer is also capped to allow usable bandwidth in other browsing as this operates in the background.
Code
If !FileExist(path) {
;acquire the zst
console.log("Downloading " record["filename"] " [" download_index "/" procArr.Length "]")
url := domain "/" record["variant"] "/" record["filename"]
curl.SetOpt("URL", url)
curl.SetOpt("MAX_RECV_SPEED_LARGE", 8000000)
curl.WriteToFile(path)
curl.Sync()
curl.GetLastBody("File").Close() ;certutil complains
}Particularly complex example. Uses a mime_handle to build an outgoing form then plucks many values from the response state for return back to the caller.
Code
Api_Facebook_PublishVideoPost(page_id, page_access_token, video_init_obj, valMassObj) {
this.log.add("Facebook: requesting video publish.")
easy_handle := this.curl.EasyInit()
url := intentUrl := "https://graph.facebook.com/v26.0/" page_id "/video_reels"
this.curl.SetOpt("URL", url, easy_handle)
; Peep(video_init_obj)
mime_handle := this.curl.MimeInit(easy_handle)
this.curl.AttachMimePart("video_id", video_init_obj["video_id"], mime_handle)
this.curl.AttachMimePart("upload_phase", "finish", mime_handle)
this.curl.AttachMimePart("video_state", "PUBLISHED", mime_handle)
this.curl.AttachMimePart("description", valMassObj["validMass"], mime_handle)
this.curl.AttachMimePart("access_token", page_access_token, mime_handle)
this.curl.Sync(easy_handle)
httpCode := this.curl.GetLastStatus(easy_handle)
responseHeaders := this.curl.GetLastHeaders(, easy_handle)
responsePayload := this.curl.GetLastBody(, easy_handle)
redirectUrl := this.curl.GetInfo("EFFECTIVE_URL", easy_handle)
this.curl.MimeCleanup(mime_handle)
this.curl.EasyCleanup(easy_handle)
if httpCode != 200 {
reason := "Facebook: failed to publish video."
this.log.add(reason)
valPostObj := this.valPost("fail", reason
, intentUrl, intentHeaders ??= Null(), intentPayload ??= Null()
, redirectUrl, httpCode, responseHeaders, responsePayload
, retVal := Null())
Peep(valPostObj)
return valPostObj
}
; jsonObj := Json.Load(responsePayload)
retVal := video_init_obj["video_id"]
valPostObj := this.valPost("pass", "OK"
, intentUrl, intentHeaders ??= Null(), intentPayload ??= Null()
, redirectUrl, httpCode, responseHeaders, responsePayload
, retVal)
; Peep(valPostObj)
return valPostObj
}Another particularly complex example. This one sequentially uploads pictures to the Bluesky servers. Then, in the same loop, the server's response to each picture is embedded in an inherited message object used by the caller.
Code
Api_Bluesky_Upload_Image_Blobs(clonedThumbs, outObj) { ;uploads images to server + embed to outObj
;attach embed map
outObj["record"]["embed"] := Map(
"$type", "app.bsky.embed.images",
"images", mediaArr := []
)
;prepare to upload
easy_handle := this.curl.init()
url := intentUrl := "https://bsky.social/xrpc/com.atproto.repo.uploadBlob"
this.curl.SetOpt("URL", url, easy_handle)
accessJwt := this.auth["Bluesky"]["accessJwt"]
headerObj := Map("Authorization", "Bearer " accessJwt)
;intentUrlArr := [] ;static url
intentHeadersArr := []
intentPayloadArr := []
redirectUrlArr := []
httpCodeArr := []
responsePayloadArr := []
responseHeadersArr := []
for k, v in clonedThumbs {
;stage images
mime_type := this.curl.SetPost(FileOpen(v.path, "r"), easy_handle)
intentPayloadArr.Push(FileOpen(v.path, "r"))
;set mime_type header
headerObj["Content-Type"] := mime_type
this.curl.SetHeaders(headerObj, easy_handle)
intentHeadersArr.push(headerObj)
;execute
this.log.Add("Bluesky: uploading " v.relpath)
this.curl.Sync(easy_handle)
; MsgBox this.curl.GetLastBody(, easy_handle)
;extract validator params
httpCode := this.curl.GetLastStatus(easy_handle)
responseHeaders := this.curl.GetLastHeaders(, easy_handle)
responsePayload := this.curl.GetLastBody(, easy_handle)
redirectUrl := this.curl.GetInfo("EFFECTIVE_URL", easy_handle)
responseHeadersArr.push(responseHeaders)
responsePayloadArr.Push(responsePayload)
httpCodeArr.Push(httpCode)
redirectUrlArr.Push(redirectUrl)
;extract ref data
blobObj := JSON.Load(responsePayload)
bLink := blobObj["blob"]["ref"]["$link"]
bmimeType := blobObj["blob"]["mimeType"]
bSize := blobObj["blob"]["size"]
;build the ref package
pushMap := Map(
"alt", "", ;todo - ALT scanning
"image", Map(
"$type", "blob",
"ref", Map("$link", bLink),
"mimeType", bmimeType,
"size", bSize
),
"aspectRatio", Map(
"width", v.width + 0,
"height", v.height + 0
)
)
; msgbox A_Clipboard := this.curl.PrintObj(pushMap)
;attach to outObj
mediaArr.Push(pushMap)
}
this.curl.EasyCleanup(easy_handle)
reason := "Bluesky: all media uploaded"
valPostObj := this.valPost("pass", reason
, intentUrl, intentHeadersArr, intentPayloadArr
, redirectUrlArr, httpCodeArr, responseHeadersArr, responsePayloadArr
, retVal := Null())
}Foundations
Operations
- Download Modes
- Setting and Listing Options
- Setting and Inspecting Headers
- POST and Upload
- Multiple Easy Handles
- Async and Multi Interface
- URL Construction
- Share Interface
- MIME and Multipart
- Raw Send and Receive
- Pause and Resume
- WebSocket
- SSL Sessions
- Debug and Diagnostics
API Reference
- Easy Handle Reference
- Multi Handle Reference
- Share Handle Reference
- MIME Handle Reference
- URL Handle Reference
- Utility Methods Reference
- WebSocket Reference
Code Snippets