Skip to content

Instantly share code, notes, and snippets.

@anonymous1184
Last active January 27, 2025 15:15
Show Gist options
  • Save anonymous1184/e6062286ac7f4c35b612d3a53535cc2a to your computer and use it in GitHub Desktop.
Save anonymous1184/e6062286ac7f4c35b612d3a53535cc2a to your computer and use it in GitHub Desktop.
WinHttpRequest.ahk
#Requires AutoHotkey v1.1
; Version: 2023.07.05.2
; https://gist.github.com/e6062286ac7f4c35b612d3a53535cc2a
; Usage and examples: https://redd.it/mcjj4s
; Testing: http://httpbin.org/ | http://httpbun.org/ | http://ptsv2.com/
WinHttpRequest(oOptions := "") {
return new WinHttpRequest(oOptions)
}
class WinHttpRequest extends WinHttpRequest.Functor {
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
;#region: Meta
__New(oOptions := "") {
static HTTPREQUEST_PROXYSETTING_DEFAULT := 0, HTTPREQUEST_PROXYSETTING_DIRECT := 1, HTTPREQUEST_PROXYSETTING_PROXY := 2, EnableCertificateRevocationCheck := 18, SslErrorIgnoreFlags := 4, SslErrorFlag_Ignore_All := 13056, SecureProtocols := 9, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 := 8192, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 := 2048, UserAgentString := 0
if (!IsObject(oOptions)) {
oOptions := {}
}
if (!oOptions.HasKey("Proxy") || !oOptions.Proxy) {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_DEFAULT)
} else if (oOptions.Proxy = "DIRECT") {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_DIRECT)
} else {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY, oOptions.Proxy)
}
if (oOptions.HasKey("Revocation")) {
this.whr.Option[EnableCertificateRevocationCheck] := !!oOptions.Revocation
} else {
this.whr.Option[EnableCertificateRevocationCheck] := true
}
if (oOptions.HasKey("SslError")) {
if (oOptions.SslError = false) {
this.whr.Option[SslErrorIgnoreFlags] := SslErrorFlag_Ignore_All
}
}
if (!oOptions.HasKey("TLS")) {
this.whr.Option[SecureProtocols] := WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
} else {
this.whr.Option[SecureProtocols] := oOptions.TLS
}
if (oOptions.HasKey("UA")) {
this.whr.Option[UserAgentString] := oOptions.UA
}
}
;#endregion
;#region: Static
EncodeUri(sUri) {
return this._EncodeDecode(sUri, true, false)
}
EncodeUriComponent(sComponent) {
return this._EncodeDecode(sComponent, true, true)
}
DecodeUri(sUri) {
return this._EncodeDecode(sUri, false, false)
}
DecodeUriComponent(sComponent) {
return this._EncodeDecode(sComponent, false, true)
}
ObjToQuery(oData) {
if (!IsObject(oData)) {
return oData
}
out := ""
for key, val in oData {
out .= this._EncodeDecode(key, true, true) "="
out .= this._EncodeDecode(val, true, true) "&"
}
return RTrim(out, "&")
}
QueryToObj(sData) {
if (IsObject(sData)) {
return sData
}
sData := LTrim(sData, "?")
obj := {}
for _, part in StrSplit(sData, "&") {
pair := StrSplit(part, "=", "", 2)
key := this._EncodeDecode(pair[1], false, true)
val := this._EncodeDecode(pair[2], false, true)
obj[key] := val
}
return obj
}
;#endregion
;#region: Public
Request(sMethod, sUrl, mBody := "", oHeaders := false, oOptions := false) {
if (this.whr = "") {
throw Exception("Not initialized.", -1)
}
sMethod := Format("{:U}", sMethod) ; CONNECT not supported
if !(sMethod ~= "^(DELETE|GET|HEAD|OPTIONS|PATCH|POST|PUT|TRACE)$") {
throw Exception("Invalid HTTP verb.", -1, sMethod)
}
if !(sUrl := Trim(sUrl)) {
throw Exception("Empty URL.", -1)
}
if (!IsObject(oHeaders)) {
oHeaders := {}
}
if (!IsObject(oOptions)) {
oOptions := {}
}
if (sMethod = "POST") {
multi := oOptions.HasKey("Multipart") ? !!oOptions.Multipart : false
this._Post(mBody, oHeaders, multi)
} else if (sMethod = "GET" && mBody) {
sUrl := RTrim(sUrl, "&")
sUrl .= InStr(sUrl, "?") ? "&" : "?"
sUrl .= WinHttpRequest.ObjToQuery(mBody)
mBody := ""
}
this.whr.Open(sMethod, sUrl, true)
for key, val in oHeaders {
this.whr.SetRequestHeader(key, val)
}
this.whr.Send(mBody)
this.whr.WaitForResponse()
if (oOptions.HasKey("Save")) {
target := RegExReplace(oOptions.Save, "^\h*\*\h*", "", forceSave)
if (this.whr.Status = 200 || forceSave) {
this._Save(target)
}
return this.whr.Status
}
out := new WinHttpRequest._Response()
out.Headers := this._Headers()
out.Status := this.whr.Status
out.Text := this._Text(oOptions.HasKey("Encoding") ? oOptions.Encoding : "")
return out
}
;#endregion
;#region: Private
static _doc := ""
_EncodeDecode(Text, bEncode, bComponent) {
if (this._doc = "") {
this._doc := ComObjCreate("HTMLFile")
this._doc.write("<meta http-equiv='X-UA-Compatible' content='IE=Edge'>")
}
action := (bEncode ? "en" : "de") "codeURI" (bComponent ? "Component" : "")
return ObjBindMethod(this._doc.parentWindow, action).Call(Text)
}
_Headers() {
headers := this.whr.GetAllResponseHeaders()
headers := RTrim(headers, "`r`n")
out := {}
for _, line in StrSplit(headers, "`n", "`r") {
pair := StrSplit(line, ":", " ", 2)
out[pair[1]] := pair[2]
}
return out
}
_Mime(Extension) {
if (WinHttpRequest.MIME.HasKey(Extension)) {
return WinHttpRequest.MIME[Extension]
}
return "application/octet-stream"
}
_MultiPart(ByRef Body) {
static LMEM_ZEROINIT := 64, EOL := "`r`n"
this._memLen := 0
this._memPtr := DllCall("LocalAlloc", "UInt", LMEM_ZEROINIT, "UInt", 1)
boundary := "----------WinHttpRequest-" A_NowUTC A_MSec
for field, value in Body {
this._MultiPartAdd(boundary, EOL, field, value)
}
this._MultipartStr("--" boundary "--" EOL)
Body := ComObjArray(0x11, this._memLen)
pvData := NumGet(ComObjValue(Body) + 8 + A_PtrSize, "Ptr")
DllCall("RtlMoveMemory", "Ptr", pvData, "Ptr", this._memPtr, "UInt", this._memLen)
DllCall("LocalFree", "Ptr", this._memPtr)
return boundary
}
_MultiPartAdd(Boundary, EOL, Field, Value) {
if (!IsObject(Value)) {
str := "--" Boundary
str .= EOL
str .= "Content-Disposition: form-data; name=""" Field """"
str .= EOL
str .= EOL
str .= Value
str .= EOL
this._MultipartStr(str)
return
}
for _, path in Value {
SplitPath path, filename, , ext
str := "--" Boundary
str .= EOL
str .= "Content-Disposition: form-data; name=""" Field """; filename=""" filename """"
str .= EOL
str .= "Content-Type: " this._Mime(ext)
str .= EOL
str .= EOL
this._MultipartStr(str)
this._MultipartFile(path)
this._MultipartStr(EOL)
}
}
_MultipartFile(Path) {
static LHND := 66
try {
oFile := FileOpen(Path, 0x0)
} catch {
throw Exception("Couldn't open file for reading.", -1, Path)
}
this._memLen += oFile.Length
this._memPtr := DllCall("LocalReAlloc", "Ptr", this._memPtr, "UInt", this._memLen, "UInt", LHND)
oFile.RawRead(this._memPtr + this._memLen - oFile.length, oFile.length)
}
_MultipartStr(Text) {
static LHND := 66
size := StrPut(Text, "UTF-8") - 1
this._memLen += size
this._memPtr := DllCall("LocalReAlloc", "Ptr", this._memPtr, "UInt", this._memLen, "UInt", LHND)
StrPut(Text, this._memPtr + this._memLen - size, size, "UTF-8")
}
_Post(ByRef Body, ByRef Headers, bMultipart) {
isMultipart := 0
for _, value in Body {
isMultipart += !!IsObject(value)
}
if (isMultipart || bMultipart) {
Body := WinHttpRequest.QueryToObj(Body)
boundary := this._MultiPart(Body)
Headers["Content-Type"] := "multipart/form-data; boundary=""" boundary """"
} else {
Body := WinHttpRequest.ObjToQuery(Body)
if (!Headers.HasKey("Content-Type")) {
Headers["Content-Type"] := "application/x-www-form-urlencoded"
}
}
}
_Save(Path) {
arr := this.whr.ResponseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize, "Ptr")
length := arr.MaxIndex() + 1
FileOpen(Path, 0x1).RawWrite(pData + 0, length)
}
_Text(Encoding) {
response := ""
try response := this.whr.ResponseText
if (response = "" || Encoding != "") {
try {
arr := this.whr.ResponseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize, "Ptr")
length := arr.MaxIndex() + 1
response := StrGet(pData, length, Encoding)
}
}
return response
}
class Functor {
__Call(Method, Parameters*) {
return this.Request(Method, Parameters*)
}
}
class _Response {
Json {
get {
method := Json.HasKey("parse") ? "parse" : "Load"
oJson := ObjBindMethod(Json, method, this.Text).Call()
ObjRawSet(this, "Json", oJson)
return oJson
}
}
}
;#endregion
class MIME {
static 7z := "application/x-7z-compressed"
static gif := "image/gif"
static jpg := "image/jpeg"
static json := "application/json"
static png := "image/png"
static zip := "application/zip"
}
}
#Requires AutoHotkey v2.0
; Version: 2023.07.05.2
; https://gist.github.com/e6062286ac7f4c35b612d3a53535cc2a
; Usage and examples: https://redd.it/mcjj4s
; Testing: http://httpbin.org/ | http://httpbun.org/ | http://ptsv2.com/
class WinHttpRequest extends WinHttpRequest.Functor {
whr := ComObject("WinHttp.WinHttpRequest.5.1")
;#region: Meta
__New(oOptions := "") {
static HTTPREQUEST_PROXYSETTING_DEFAULT := 0, HTTPREQUEST_PROXYSETTING_DIRECT := 1, HTTPREQUEST_PROXYSETTING_PROXY := 2, EnableCertificateRevocationCheck := 18, SslErrorIgnoreFlags := 4, SslErrorFlag_Ignore_All := 13056, SecureProtocols := 9, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 := 8192, WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 := 2048, UserAgentString := 0
if (!IsObject(oOptions)) {
oOptions := Map()
}
if (!oOptions.Has("Proxy") || !oOptions["Proxy"]) {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_DEFAULT)
} else if (oOptions["Proxy"] = "DIRECT") {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_DIRECT)
} else {
this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY, oOptions["Proxy"])
}
if (oOptions.Has("Revocation")) {
this.whr.Option[EnableCertificateRevocationCheck] := !!oOptions["Revocation"]
} else {
this.whr.Option[EnableCertificateRevocationCheck] := true
}
if (oOptions.Has("SslError")) {
if (oOptions["SslError"] = false) {
this.whr.Option[SslErrorIgnoreFlags] := SslErrorFlag_Ignore_All
}
}
if (!oOptions.Has("TLS")) {
this.whr.Option[SecureProtocols] := WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
} else {
this.whr.Option[SecureProtocols] := oOptions["TLS"]
}
if (oOptions.Has("UA")) {
this.whr.Option[UserAgentString] := oOptions["UA"]
}
}
;#endregion
;#region: Static
static EncodeUri(sUri) {
return this._EncodeDecode(sUri, true, false)
}
static EncodeUriComponent(sComponent) {
return this._EncodeDecode(sComponent, true, true)
}
static DecodeUri(sUri) {
return this._EncodeDecode(sUri, false, false)
}
static DecodeUriComponent(sComponent) {
return this._EncodeDecode(sComponent, false, true)
}
static ObjToQuery(oData) {
if (!IsObject(oData)) {
return oData
}
out := ""
for key, val in oData {
out .= this._EncodeDecode(key, true, true) "="
out .= this._EncodeDecode(val, true, true) "&"
}
return RTrim(out, "&")
}
static QueryToObj(sData) {
if (IsObject(sData)) {
return sData
}
sData := LTrim(sData, "?")
obj := Map()
for _, part in StrSplit(sData, "&") {
pair := StrSplit(part, "=", "", 2)
key := this._EncodeDecode(pair[1], false, true)
val := this._EncodeDecode(pair[2], false, true)
obj[key] := val
}
return obj
}
;#endregion
;#region: Public
Request(sMethod, sUrl, mBody := "", oHeaders := false, oOptions := false) {
if (this.whr = "") {
throw Error("Not initialized.", -1)
}
sMethod := Format("{:U}", sMethod) ; CONNECT not supported
if !(sMethod ~= "^(DELETE|GET|HEAD|OPTIONS|PATCH|POST|PUT|TRACE)$") {
throw Error("Invalid HTTP verb.", -1, sMethod)
}
if !(sUrl := Trim(sUrl)) {
throw Error("Empty URL.", -1)
}
if (!IsObject(oHeaders)) {
oHeaders := Map()
}
if (!IsObject(oOptions)) {
oOptions := Map()
}
if (sMethod = "POST") {
multi := oOptions.Has("Multipart") ? !!oOptions["Multipart"] : false
this._Post(&mBody, &oHeaders, multi)
} else if (sMethod = "GET" && mBody) {
sUrl := RTrim(sUrl, "&")
sUrl .= InStr(sUrl, "?") ? "&" : "?"
sUrl .= WinHttpRequest.ObjToQuery(mBody)
mBody := ""
}
this.whr.Open(sMethod, sUrl, true)
for key, val in oHeaders {
this.whr.SetRequestHeader(key, val)
}
this.whr.Send(mBody)
this.whr.WaitForResponse()
if (oOptions.Has("Save")) {
target := RegExReplace(oOptions["Save"], "^\h*\*\h*", "", &forceSave)
if (this.whr.Status = 200 || forceSave) {
this._Save(target)
}
return this.whr.Status
}
out := WinHttpRequest._Response()
out.Headers := this._Headers()
out.Status := this.whr.Status
out.Text := this._Text(oOptions.Has("Encoding") ? oOptions["Encoding"] : "")
return out
}
;#endregion
;#region: Private
static _doc := ""
static _EncodeDecode(Text, bEncode, bComponent) {
if (this._doc = "") {
this._doc := ComObject("HTMLFile")
this._doc.write("<meta http-equiv='X-UA-Compatible' content='IE=Edge'>")
}
action := (bEncode ? "en" : "de") "codeURI" (bComponent ? "Component" : "")
return ObjBindMethod(this._doc.parentWindow, action).Call(Text)
}
_Headers() {
headers := this.whr.GetAllResponseHeaders()
headers := RTrim(headers, "`r`n")
out := Map()
for _, line in StrSplit(headers, "`n", "`r") {
pair := StrSplit(line, ":", " ", 2)
out.Set(pair*)
}
return out
}
_Mime(Extension) {
if (WinHttpRequest.MIME.HasProp(Extension)) {
return WinHttpRequest.MIME.%Extension%
}
return "application/octet-stream"
}
_MultiPart(&Body) {
static LMEM_ZEROINIT := 64, EOL := "`r`n"
this._memLen := 0
this._memPtr := DllCall("LocalAlloc", "UInt", LMEM_ZEROINIT, "UInt", 1)
boundary := "----------WinHttpRequest-" A_NowUTC A_MSec
for field, value in Body {
this._MultiPartAdd(boundary, EOL, field, value)
}
this._MultipartStr("--" boundary "--" EOL)
Body := ComObjArray(0x11, this._memLen)
pvData := NumGet(ComObjValue(Body) + 8 + A_PtrSize, "Ptr")
DllCall("RtlMoveMemory", "Ptr", pvData, "Ptr", this._memPtr, "UInt", this._memLen)
DllCall("LocalFree", "Ptr", this._memPtr)
return boundary
}
_MultiPartAdd(Boundary, EOL, Field, Value) {
if (!IsObject(Value)) {
str := "--" Boundary
str .= EOL
str .= "Content-Disposition: form-data; name=`"" Field "`""
str .= EOL
str .= EOL
str .= Value
str .= EOL
this._MultipartStr(str)
return
}
for _, path in Value {
SplitPath(path, &filename, , &ext)
str := "--" Boundary
str .= EOL
str .= "Content-Disposition: form-data; name=`"" Field "`"; filename=`"" filename "`""
str .= EOL
str .= "Content-Type: " this._Mime(ext)
str .= EOL
str .= EOL
this._MultipartStr(str)
this._MultipartFile(path)
this._MultipartStr(EOL)
}
}
_MultipartFile(Path) {
static LHND := 66
try {
oFile := FileOpen(Path, 0x0)
} catch {
throw Error("Couldn't open file for reading.", -1, Path)
}
this._memLen += oFile.Length
this._memPtr := DllCall("LocalReAlloc", "Ptr", this._memPtr, "UInt", this._memLen, "UInt", LHND)
oFile.RawRead(this._memPtr + this._memLen - oFile.length, oFile.length)
}
_MultipartStr(Text) {
static LHND := 66
size := StrPut(Text, "UTF-8") - 1
this._memLen += size
this._memPtr := DllCall("LocalReAlloc", "Ptr", this._memPtr, "UInt", this._memLen, "UInt", LHND)
StrPut(Text, this._memPtr + this._memLen - size, size, "UTF-8")
}
_Post(&Body, &Headers, bMultipart) {
isMultipart := 0
for _, value in Body {
isMultipart += !!IsObject(value)
}
if (isMultipart || bMultipart) {
Body := WinHttpRequest.QueryToObj(Body)
boundary := this._MultiPart(&Body)
Headers["Content-Type"] := "multipart/form-data; boundary=`"" boundary "`""
} else {
Body := WinHttpRequest.ObjToQuery(Body)
if (!Headers.Has("Content-Type")) {
Headers["Content-Type"] := "application/x-www-form-urlencoded"
}
}
}
_Save(Path) {
arr := this.whr.ResponseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize, "Ptr")
length := arr.MaxIndex() + 1
FileOpen(Path, 0x1).RawWrite(pData + 0, length)
}
_Text(Encoding) {
response := ""
try response := this.whr.ResponseText
if (response = "" || Encoding != "") {
try {
arr := this.whr.ResponseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize, "Ptr")
length := arr.MaxIndex() + 1
response := StrGet(pData, length, Encoding)
}
}
return response
}
class Functor {
/* _H v2.0.2 adds Object.Prototype.Get() breaking
GET verb's dynamic call, this is a workaround. */
GET(Parameters*) {
return this.Request("GET", Parameters*)
}
__Call(Method, Parameters) {
return this.Request(Method, Parameters*)
}
}
class _Response {
Json {
get {
method := HasMethod(JSON, "parse") ? "parse" : "Load"
oJson := ObjBindMethod(JSON, method, this.Text).Call()
this.DefineProp("Json", { Value: oJson })
return oJson
}
}
}
;#endregion
class MIME {
static 7z := "application/x-7z-compressed"
static gif := "image/gif"
static jpg := "image/jpeg"
static json := "application/json"
static png := "image/png"
static zip := "application/zip"
}
}
--- WinHttpRequest.ahk
+++ WinHttpRequest-deprecated.ahk
@@ -1 +1 @@
-#Requires AutoHotkey v2.0
+#Requires AutoHotkey v1.1
@@ -7,0 +8,4 @@
+WinHttpRequest(oOptions := "") {
+ return new WinHttpRequest(oOptions)
+}
+
@@ -10 +14 @@
- whr := ComObject("WinHttp.WinHttpRequest.5.1")
+ whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
@@ -17 +21 @@
- oOptions := Map()
+ oOptions := {}
@@ -19 +23 @@
- if (!oOptions.Has("Proxy") || !oOptions["Proxy"]) {
+ if (!oOptions.HasKey("Proxy") || !oOptions.Proxy) {
@@ -21 +25 @@
- } else if (oOptions["Proxy"] = "DIRECT") {
+ } else if (oOptions.Proxy = "DIRECT") {
@@ -24 +28 @@
- this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY, oOptions["Proxy"])
+ this.whr.SetProxy(HTTPREQUEST_PROXYSETTING_PROXY, oOptions.Proxy)
@@ -26,2 +30,2 @@
- if (oOptions.Has("Revocation")) {
- this.whr.Option[EnableCertificateRevocationCheck] := !!oOptions["Revocation"]
+ if (oOptions.HasKey("Revocation")) {
+ this.whr.Option[EnableCertificateRevocationCheck] := !!oOptions.Revocation
@@ -31,2 +35,2 @@
- if (oOptions.Has("SslError")) {
- if (oOptions["SslError"] = false) {
+ if (oOptions.HasKey("SslError")) {
+ if (oOptions.SslError = false) {
@@ -36 +40 @@
- if (!oOptions.Has("TLS")) {
+ if (!oOptions.HasKey("TLS")) {
@@ -39 +43 @@
- this.whr.Option[SecureProtocols] := oOptions["TLS"]
+ this.whr.Option[SecureProtocols] := oOptions.TLS
@@ -41,2 +45,2 @@
- if (oOptions.Has("UA")) {
- this.whr.Option[UserAgentString] := oOptions["UA"]
+ if (oOptions.HasKey("UA")) {
+ this.whr.Option[UserAgentString] := oOptions.UA
@@ -49 +53 @@
- static EncodeUri(sUri) {
+ EncodeUri(sUri) {
@@ -53 +57 @@
- static EncodeUriComponent(sComponent) {
+ EncodeUriComponent(sComponent) {
@@ -57 +61 @@
- static DecodeUri(sUri) {
+ DecodeUri(sUri) {
@@ -61 +65 @@
- static DecodeUriComponent(sComponent) {
+ DecodeUriComponent(sComponent) {
@@ -65 +69 @@
- static ObjToQuery(oData) {
+ ObjToQuery(oData) {
@@ -77 +81 @@
- static QueryToObj(sData) {
+ QueryToObj(sData) {
@@ -82 +86 @@
- obj := Map()
+ obj := {}
@@ -97 +101 @@
- throw Error("Not initialized.", -1)
+ throw Exception("Not initialized.", -1)
@@ -101 +105 @@
- throw Error("Invalid HTTP verb.", -1, sMethod)
+ throw Exception("Invalid HTTP verb.", -1, sMethod)
@@ -104 +108 @@
- throw Error("Empty URL.", -1)
+ throw Exception("Empty URL.", -1)
@@ -107 +111 @@
- oHeaders := Map()
+ oHeaders := {}
@@ -110 +114 @@
- oOptions := Map()
+ oOptions := {}
@@ -113,2 +117,2 @@
- multi := oOptions.Has("Multipart") ? !!oOptions["Multipart"] : false
- this._Post(&mBody, &oHeaders, multi)
+ multi := oOptions.HasKey("Multipart") ? !!oOptions.Multipart : false
+ this._Post(mBody, oHeaders, multi)
@@ -127,2 +131,2 @@
- if (oOptions.Has("Save")) {
- target := RegExReplace(oOptions["Save"], "^\h*\*\h*", "", &forceSave)
+ if (oOptions.HasKey("Save")) {
+ target := RegExReplace(oOptions.Save, "^\h*\*\h*", "", forceSave)
@@ -134 +138 @@
- out := WinHttpRequest._Response()
+ out := new WinHttpRequest._Response()
@@ -137 +141 @@
- out.Text := this._Text(oOptions.Has("Encoding") ? oOptions["Encoding"] : "")
+ out.Text := this._Text(oOptions.HasKey("Encoding") ? oOptions.Encoding : "")
@@ -146 +150 @@
- static _EncodeDecode(Text, bEncode, bComponent) {
+ _EncodeDecode(Text, bEncode, bComponent) {
@@ -148 +152 @@
- this._doc := ComObject("HTMLFile")
+ this._doc := ComObjCreate("HTMLFile")
@@ -158 +162 @@
- out := Map()
+ out := {}
@@ -161 +165 @@
- out.Set(pair*)
+ out[pair[1]] := pair[2]
@@ -167,2 +171,2 @@
- if (WinHttpRequest.MIME.HasProp(Extension)) {
- return WinHttpRequest.MIME.%Extension%
+ if (WinHttpRequest.MIME.HasKey(Extension)) {
+ return WinHttpRequest.MIME[Extension]
@@ -173 +177 @@
- _MultiPart(&Body) {
+ _MultiPart(ByRef Body) {
@@ -193 +197 @@
- str .= "Content-Disposition: form-data; name=`"" Field "`""
+ str .= "Content-Disposition: form-data; name=""" Field """"
@@ -202 +206 @@
- SplitPath(path, &filename, , &ext)
+ SplitPath path, filename, , ext
@@ -205 +209 @@
- str .= "Content-Disposition: form-data; name=`"" Field "`"; filename=`"" filename "`""
+ str .= "Content-Disposition: form-data; name=""" Field """; filename=""" filename """"
@@ -221 +225 @@
- throw Error("Couldn't open file for reading.", -1, Path)
+ throw Exception("Couldn't open file for reading.", -1, Path)
@@ -236 +240 @@
- _Post(&Body, &Headers, bMultipart) {
+ _Post(ByRef Body, ByRef Headers, bMultipart) {
@@ -243,2 +247,2 @@
- boundary := this._MultiPart(&Body)
- Headers["Content-Type"] := "multipart/form-data; boundary=`"" boundary "`""
+ boundary := this._MultiPart(Body)
+ Headers["Content-Type"] := "multipart/form-data; boundary=""" boundary """"
@@ -247 +251 @@
- if (!Headers.Has("Content-Type")) {
+ if (!Headers.HasKey("Content-Type")) {
@@ -276,7 +280 @@
- /* _H v2.0.2 adds Object.Prototype.Get() breaking
- GET verb's dynamic call, this is a workaround. */
- GET(Parameters*) {
- return this.Request("GET", Parameters*)
- }
-
- __Call(Method, Parameters) {
+ __Call(Method, Parameters*) {
@@ -292,3 +290,3 @@
- method := HasMethod(JSON, "parse") ? "parse" : "Load"
- oJson := ObjBindMethod(JSON, method, this.Text).Call()
- this.DefineProp("Json", { Value: oJson })
+ method := Json.HasKey("parse") ? "parse" : "Load"
+ oJson := ObjBindMethod(Json, method, this.Text).Call()
+ ObjRawSet(this, "Json", oJson)
@kk0033
Copy link

kk0033 commented Jan 27, 2025

Thanks for your awesome work. I love it!.
I am getting an AHK error that says:
"[0X80072F99 There were no credentials available in the client certificate"
Any idea how to solvel it?.
Thanks again!

Capturar-1 copia
My code:
Capturar-2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment