Usage and information: https://redd.it/mcjj4s
-
-
Save anonymous1184/e6062286ac7f4c35b612d3a53535cc2a to your computer and use it in GitHub Desktop.
#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) |
Thank you for making this!
Thanks for your awesome work! :)
I had some trouble decoding UTF8 responses in my script, so I had to change the _Text()
function to parse from the response body instead of the response text (cf. this solution posted in r/AutoHotKey).
@htadashi Great it worked for you. I've been trying to get my hands in something that will return an error for the ._Text()
method, so it throws an exception. The answer you linked and the code after the try
do the same.
Can you share where you get issues, so I can fine-tune the class?
Hi @anonymous1184, sorry for my late reply.
When I used WinHttpRequest without modifying the .Text()
method (the diff can be seen in htadashi/GPT3-AHK@896feb8), the script didn't throw an exception. However, some accented characters (such as "É") in the response rendered as garbled text, though the original response had the correct accented characters.
Here is an error report detailing the issue of the accented characters: https://www.reddit.com/r/AutoHotkey/comments/zrzjc2/comment/j28hxi0/
I'm aware of the issue, and I tried to prevent it, but seems like it needs another approach. However, I haven't come across a URL that returns the issue.
What I require is a URL that returns an error with my current implementation, so I can fix it. Even tho, in fact is quite simple: I just need to remove the try
block and use the byte array from the response.
arr := this.whr.ResponseBody
pData := NumGet(ComObjValue(arr) + 8 + A_PtrSize)
response := StrGet(pData, arr.MaxIndex() + 1, "UTF-8")
But that's the point, I rather test than blindly do it. What's the URL that returns the data that required you to change the ._Text()
method?
Ah, I understood your point now. To return the faulty data, I made a POST to https://api.openai.com/v1/completions
with the headers
Content-Type: application/json
Authorization: Bearer API_TOKEN
and the body
{
"prompt":"Write the polish alphabet: ",
"model":"text-davinci-003",
"max_tokens":200
}
API_TOKEN
should be your OpenAI API token, but in case you do not want to create one for this, I made a server with Google Apps Script that should return the same response to this query. You just need to do a POST to https://script.google.com/macros/s/AKfycbyKYNdD2h1F5T9vdq5qEA3Po3tawn77fprCnLJUhwzT-lGQKPYewcMtxS6DX1aR8OM/exec
.
@htadashi Thanks for setting up the Google Apps Script, that lead me to figure out that the issue is OpenAI and not the script. Google sends the response properly encoded, while OpenAI sends it as ASCII.
So there is no need for me to update the script, the problem lies within the server. If you wanted to address the issue, you only needed to pass the encoding (UTF-8
is all that's needed for basically everything).
Got it now! Thanks for the detailed explanation @anonymous1184 :)
Amazing! Thank you!