How do I make the call to URL above with AHK?
username .: Username to the provider password .: Password to the provider type .: Message type, e.g. text destination .: Receiver, in format 0046700123123 (in Sweden) originator type .: Transmitter type, e.g. numeric originator .: transmitter, e.g. 0046700123123 for numeric transmitter (in Sweden) charset. .: Character set of parameter values are specified in either UTF-8 or ISO-8859-1 (default) text.: The SMS message ...
An example on a SMS-message from AHK .: (a space is in https to display the entire URL-string) http s://se-1.cellsynt.net/sms.php?username=demo&password=test123&destination=0046700123123&originatortype=numeric&originator=46700456456&charset=UTF-8&text=Test+123
endpoint:="se-1.cellsynt.net/sms.php" ; url pointing to the API endpoint
data:={"username":"demo","password":"test123"} ; key-val data to be posted
try{ ; only way to properly protect from an error here
createFormData(rData,rHeader,data) ; formats the data, stores in rData, header info in rHeader
hObject:=comObjectCreate("WinHttp.WinHttpRequest.5.1") ; create WinHttp object
hObject.setRequestHeader("Content-Type",rHeader) ; set content header
hObject.open("POST",endpoint) ; open a post event to the specified endpoint
hObject.send(rData) ; send request with data
; you can get the response data either in raw or text format
; raw: hObject.responseBody
; text: hObject.responseText
}catch e{
return e.message
}
Re: an HTTP GET or POST call to URL
Posted: 06 Feb 2020, 05:28
by Albireo
Thanks! (trying to understand what's going on in the code)
When I tried to use the code above, an error occurred.
Error: Return's parameter should be blank except inside a function.
ErrorLevel doesn't actually do anything, it just allows you to get the error if a command sets one. A try block will not throw any visual/breaking errors, rather, if an error is encountered, it jumps to the respective catch block with an error object, which you can then do whatever you want. Or, you could exclude the catch block and just suppress any errors, but that isn't the best idea.
If you want to try it, run the code when you're offline, with and without the try block.
Re: an HTTP GET or POST call to URL
Posted: 06 Feb 2020, 14:12
by Albireo
I see- Try is much better than ErrorLevel in this case.
But now I got this error message .: 0x800401E3 - Åtgärden är inte tillgänglig (perhaps from Windows)
Maybe translated to Operation unavailable or The action is not available on the catch e-instruction below.
; 1. CreateFormData (Build the PostData )
;
; 2. WinHttpRequest object (to send the data)
; https://docs.microsoft.com/en-us/windows/win32/winhttp/winhttprequest
;
endpoint := "se-1.cellsynt.net/sms.php" ; url pointing to the API endpoint
UserName := "user"
Pass := "password"
FromType := "numeric"
From := "46701234567"
CharSet := "UTF-8"
ToNumber := "0046701234567"
Message := "Test+123"
data := {"username":UserName,"password":Pass,"destination":ToNumber,"originatortype":FromType,"originator":From,"charset":CharSet,"text":Message} ; Data to be posted
; MsgBox ,, %A_ScriptName% - Row %A_LineNumber%, % "endpoint .: " endpoint "`ndata.username .: " data.username "`ndata.password .: " data.password "`ndata.destination .: " data.destination
try{ ; only way to properly protect from an error here
createFormData(rData, rHeader, data) ; formats the data, stores in rData, header info in rHeader
hObject := comObjectCreate("WinHttp.WinHttpRequest.5.1") ; create WinHttp object
hObject.setRequestHeader("Content-Type", rHeader) ; set content header
hObject.open("POST", endpoint) ; open a post event to the specified endpoint
hObject.send(rData) ; send request with data
; you can get the response data either in raw or text format
; raw: hObject.responseBody
; text: hObject.responseText
} catch e {
MsgBox 64, %A_ScriptName% - Row %A_LineNumber%, % e.message
; return e.message
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; - - - - - - - - - - - - CreateFormData.ahk - - - - - - - - - - - - - - - - - - - - -
/*
Version 6 feb 2020
From .: https://gist.github.com/tmplinshi/8428a280bba58d25ef0b
By .: tmplinshi
CreateFormData - Creates "multipart/form-data" for http post
https://www.autohotkey.com/boards/viewtopic.php?t=7647
Usage: CreateFormData(ByRef retData, ByRef retHeader, objParam)
retData - (out) Data used for HTTP POST.
retHeader - (out) Content-Type header used for HTTP POST.
objParam - (in) An object defines the form parameters.
To specify files, use array as the value. Example:
objParam := { "key1": "value1"
, "upload[]": ["1.png", "2.png"] }
Requirements: BinArr.ahk -- https://gist.github.com/tmplinshi/a97d9a99b9aa5a65fd20
Version : 1.30 / 2019-01-13 - The file parameters are now placed at the end of the retData
1.20 / 2016-06-17 - Added CreateFormData_WinInet(), which can be used for VxE's HTTPRequest().
1.10 / 2015-06-23 - Fixed a bug
1.00 / 2015-05-14
*/
; Used for WinHttp.WinHttpRequest.5.1, Msxml2.XMLHTTP ...
CreateFormData(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(retData, retHeader, objParam)
}
; Used for WinInet
CreateFormData_WinInet(ByRef retData, ByRef retHeader, objParam) {
New CreateFormData(safeArr, retHeader, objParam)
size := safeArr.MaxIndex() + 1
VarSetCapacity(retData, size, 1)
DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(safeArr), "ptr*", pdata)
DllCall("RtlMoveMemory", "ptr", &retData, "ptr", pdata, "ptr", size)
DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(safeArr))
}
Class CreateFormData {
__New(ByRef retData, ByRef retHeader, objParam) {
CRLF := "`r`n"
Boundary := this.RandomBoundary()
BoundaryLine := "------------------------------" . Boundary
; Loop input paramters
binArrs := []
fileArrs := []
For k, v in objParam
{ If IsObject(v) {
For i, FileName in v
{
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=""" . k . """; filename=""" . FileName . """" . CRLF
. "Content-Type: " . this.MimeType(FileName) . CRLF . CRLF
fileArrs.Push( BinArr_FromString(str) )
fileArrs.Push( BinArr_FromFile(FileName) )
fileArrs.Push( BinArr_FromString(CRLF) )
}
} Else {
str := BoundaryLine . CRLF
. "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF
. v . CRLF
binArrs.Push( BinArr_FromString(str) )
}
}
binArrs.push( fileArrs* )
str := BoundaryLine . "--" . CRLF
binArrs.Push( BinArr_FromString(str) )
retData := BinArr_Join(binArrs*)
retHeader := "multipart/form-data; boundary=----------------------------" . Boundary
}
RandomBoundary() {
str := "0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"
Sort, str, D| Random
str := StrReplace(str, "|")
Return SubStr(str, 1, 12)
}
MimeType(FileName) {
n := FileOpen(FileName, "r").ReadUInt()
Return (n = 0x474E5089) ? "image/png"
: (n = 0x38464947) ? "image/gif"
: (n&0xFFFF = 0x4D42 ) ? "image/bmp"
: (n&0xFFFF = 0xD8FF ) ? "image/jpeg"
: (n&0xFFFF = 0x4949 ) ? "image/tiff"
: (n&0xFFFF = 0x4D4D ) ? "image/tiff"
: "application/octet-stream"
}
}
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; - - - - - - - - - - - - BinArr.ahk - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Update: 2015-6-4 - Added BinArr_ToFile()
; https://gist.github.com/tmplinshi/a97d9a99b9aa5a65fd20
; By tmplinshi
BinArr_FromString(str) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 2 ; adTypeText
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
oADO.Charset := "UTF-8"
oADO.WriteText(str)
oADO.Position := 0
oADO.Type := 1 ; adTypeBinary
oADO.Position := 3 ; Skip UTF-8 BOM
return oADO.Read, oADO.Close
}
BinArr_FromFile(FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.LoadFromFile(FileName)
return oADO.Read, oADO.Close
}
BinArr_Join(Arrays*) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
For i, arr in Arrays
oADO.Write(arr)
oADO.Position := 0
return oADO.Read, oADO.Close
}
BinArr_ToString(BinArr, Encoding := "UTF-8") {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Mode := 3 ; adModeReadWrite
oADO.Open
oADO.Write(BinArr)
oADO.Position := 0
oADO.Type := 2 ; adTypeText
oADO.Charset := Encoding
return oADO.ReadText, oADO.Close
}
BinArr_ToFile(BinArr, FileName) {
oADO := ComObjCreate("ADODB.Stream")
oADO.Type := 1 ; adTypeBinary
oADO.Open
oADO.Write(BinArr)
oADO.SaveToFile(FileName, 2)
oADO.Close
}
Is it easy / possible to see what will be sent to the URL endpoint?
(e.g. hObject / rHeader / rData)
Re: an HTTP GET or POST call to URL
Posted: 06 Feb 2020, 19:30
by Albireo
I think there must be another solution for me?
If I copy the string below, with the correct username / password / phone number and so on, to a browser (in my case FireFox),
a SMS with the text Test+123 is sent to me. (no space in https://...)
On the browser I got the message .: OK: 6414a917729df3f1acbd7bdf4e340bbc (OK: + trackingid on the SMS)
With the trackingid I can get the status of the delivery of the SMS.
But first I need to be able to send a HTTPS- message (without first opening a browser and then copying the text into the browser)
Is it possible with AHK?
Previously, I showed a program, written in PHP, as on a few lines solve this.
Re: an HTTP GET or POST call to URL
Posted: 06 Feb 2020, 23:11
by tmplinshi
You can make an HTTP GET or HTTP POST request, according to its API.
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("GET", "https://se-1.cellsynt.net/sms.php?username=demo&password=test123&destination=0046700123123&originatortype=numeric&originator=46700456456&charset=UTF-8&text=Test+123", true)
whr.Send()
; Using 'true' above and the call below allows the script to remain responsive.
whr.WaitForResponse()
MsgBox % whr.ResponseText
CreateFormData.ahk is used for the content-type "multipart/form-data", which is normally used when the form contains a file to upload.
Re: an HTTP GET or POST call to URL (Solved!)
Posted: 07 Feb 2020, 07:29
by Albireo
Great! thanks!
It was this solution I was looking for - both methods seem to work perfectly
Re: an HTTP GET or POST call to URL
Posted: 07 Feb 2020, 07:44
by Albireo
Is it better to use Try / Catch in this case (as in this example below?)
What problems will be catched? (error from WinHttp.WinHttpRequest.5.1? or ...)
You can make an HTTP GET or HTTP POST request, according to its API.
@tmplinshi Once I saw your post I got the idea that it could be used to accomplish the final request ("Using the refresh token to get an access token") for Google-Drive as it is described here: https://martinfowler.com/articles/command-line-google.html#OutlineFlowForAuthorization
I've downloaded your http.ahk from GitHub but have no idea how to use it in this case? Probably you can shed some light on this. Thx
Without further ado: Sir, you made my day! [AHK-Certicicate of Debt : BoBo, owing @tmplinshi a pint of his favorite beer] Thx !
Re: an HTTP GET or POST call to URL
Posted: 08 Jun 2021, 18:54
by Drugwash
One year later...
Could someone, anyone, please help me with reaching youtube from AHK? All I need is get some details from the video page in order to format a link.
My script used to work fine until they decided to throw in a cookie consent page for us poor europeans. Ever since I can only get that consent page "Before accessing YouTube" which contains two "buttons", one of which being a form submittal of type POST. The form contains about a dozen hidden input fields with name and value.
I tried sniffing headers in the browser, making repeated GET and POST calls using various request headers, to no avail. Tried usingWinHttp and XmlHttp - the latter is the only one that actually sets one cookie - the very first one in a set of about four or five - and then nothing. Besides all the cookies there are also at least three redirects that complicate things: from original URL www youtube com it goes to consent google com, then to consent google ro and then back to www youtube com (unless I missed some other redirect). With WinHttp one can select whether to follow redirects or not and get/set the cookies manually, while XmlHttp errored out at req.Option(WinHttpRequestOption_EnableRedirects) := true/false . I'm at my wits' end and to top it all not feeling well at all today.
So please, if anyone from the EU is around and can perform some tests I'd very much appreciate it, and any tips/advices as well.
Simply adding request header Cookie with CONSENT=YES+EN didn't work with XMLHTTP but it did work with WinHttp. Strange. However, the former seems to be preferred lately for some reason so it'd be great to find a common solution that would work in both versions.
Nevertheless, thank you for providing a working solution for one version of the request.