WinHttp post request

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

WinHttp post request

05 Feb 2020, 07:10

I have found this script bellow to send get Winhttp request, would like to ask for help in how i could use it to send a post request, like:

/api/item/write
So in the body:
{ "species": "value", "name": "item name", "quantity": 300 }

Code: Select all

getWebPage("https granblue.herokuapp.com /api/item/write/collection/550")  Broken Link for safety

;=========== get the content of a webpage into a variable
getWebPage(url, postdata :="")
{
    Static whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")    ; Static will make it use the same object in memory
    whr.Open((postdata?"Post":"Get"), url, true)                ; Post or Get depending if postdata is submitted
    whr.SetTimeouts("30000", "30000", "30000", "30000")         ; timeout 30 seconds

    if (StrLen(postdata)>0)
    {
        whr.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded")
        whr.Send(postdata)
    }
    else
    {
        whr.Send()
    }
    whr.WaitForResponse()
    Return whr.ResponseText
}
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: WinHttp post request

05 Feb 2020, 10:31

You need to create and send the form data (param 2). You can use this to build your data: https://gist.github.com/tmplinshi/8428a280bba58d25ef0b
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: WinHttp post request

05 Feb 2020, 17:16

hi @Masonjar13

Code: Select all

; CreateFormData() by tmplinshi, AHK Topic: https://autohotkey.com/boards/viewtopic.php?t=7647
; Thanks to Coco: https://autohotkey.com/boards/viewtopic.php?p=41731#p41731
; Modified version by SKAN, 09/May/2016

whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("POST", "https  site  /api/item/write/",  Broken Link for safety true)

objParam := { "species": "bird"
            , "name": "cana"
            , "quantity": 5 }

CreateFormData(PostData, hdr_ContentType, objParam)

whr.SetRequestHeader("Content-Type", hdr_ContentType)
whr.SetRequestHeader("Referer", "https    site      /api/item/write/")  Broken Link for safety
whr.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0")
whr.Option(6) := False ; No auto redirect
whr.Send(PostData)
whr.WaitForResponse()
;Run, % "https black-desert-notifier.herokuapp.com /api/item/write/"  Broken Link for safety . whr.GetResponseHeader("Location")


CreateFormData(ByRef retData, ByRef retHeader, objParam) {
	New CreateFormData(retData, retHeader, objParam)
}

Class CreateFormData {

	__New(ByRef retData, ByRef retHeader, objParam) {

		Local CRLF := "`r`n", i, k, v, str, pvData
		; Create a random Boundary
		Local Boundary := this.RandomBoundary()
		Local BoundaryLine := "------------------------------" . Boundary

    this.Len := 0 ; GMEM_ZEROINIT|GMEM_FIXED = 0x40
    this.Ptr := DllCall( "GlobalAlloc", "UInt",0x40, "UInt",1, "Ptr"  )          ; allocate global memory

		; Loop input paramters
		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
          this.StrPutUTF8( str )
          this.LoadFromFile( Filename )
          this.StrPutUTF8( CRLF )
				}
			} Else {
				str := BoundaryLine . CRLF
				     . "Content-Disposition: form-data; name=""" . k """" . CRLF . CRLF
				     . v . CRLF
        this.StrPutUTF8( str )
			}
		}

		this.StrPutUTF8( BoundaryLine . "--" . CRLF )

    ; Create a bytearray and copy data in to it.
    retData := ComObjArray( 0x11, this.Len ) ; Create SAFEARRAY = VT_ARRAY|VT_UI1
    pvData  := NumGet( ComObjValue( retData ) + 8 + A_PtrSize )
    DllCall( "RtlMoveMemory", "Ptr",pvData, "Ptr",this.Ptr, "Ptr",this.Len )

    this.Ptr := DllCall( "GlobalFree", "Ptr",this.Ptr, "Ptr" )                   ; free global memory 

    retHeader := "multipart/form-data; boundary=----------------------------" . Boundary
	}

  StrPutUTF8( str ) {
    Local ReqSz := StrPut( str, "utf-8" ) - 1
    this.Len += ReqSz                                  ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42
    this.Ptr := DllCall( "GlobalReAlloc", "Ptr",this.Ptr, "UInt",this.len + 1, "UInt", 0x42 )   
    StrPut( str, this.Ptr + this.len - ReqSz, ReqSz, "utf-8" )
  }
  
  LoadFromFile( Filename ) {
    Local objFile := FileOpen( FileName, "r" )
    this.Len += objFile.Length                     ; GMEM_ZEROINIT|GMEM_MOVEABLE = 0x42 
    this.Ptr := DllCall( "GlobalReAlloc", "Ptr",this.Ptr, "UInt",this.len, "UInt", 0x42 )
    objFile.RawRead( this.Ptr + this.Len - objFile.length, objFile.length )
    objFile.Close()       
  }

	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"
	}

}

I followed the example on the link you post, but I'm not receiving anything on my site
User avatar
Masonjar13
Posts: 1555
Joined: 20 Jul 2014, 10:16
Location: Не Россия
Contact:

Re: WinHttp post request

05 Feb 2020, 17:25

Looks correct. Have you checked your server logs? Did you see a connection, possibly failed? You may need to authenticate first, or open your endpoint to the public. Potentially, you could also be timing out (though this should throw an error on AHK). You can use whr.setTimeouts() to alter those, if needed.
OS: Windows 10 Pro | Editor: Notepad++
My Personal Function Library | Old Build - New Build
tmplinshi
Posts: 1604
Joined: 01 Oct 2013, 14:57

Re: WinHttp post request

06 Feb 2020, 23:23

There are mainly 3 types of POST data.
  1. application/x-www-form-urlencoded
    example body: name=admin&shoesize=12
  2. application/json
    example body: {"name":"admin", "shoesize":12}
  3. multipart/form-data
    It's normally used for uploading binary file. CreateFormData is only used for this type.
The body is a json string, so it should be application/json.

Code: Select all

whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("POST", "https://granblue.herokuapp.com/api/item/write")
whr.SetRequestHeader("Content-Type", "application/json")
body = {"species": "value", "name": "item name", "quantity": 300}
whr.Send(body)
MsgBox % whr.ResponseText
blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: WinHttp post request

26 Feb 2021, 15:16

Hi @tmplinshi ,

I have tried this for upload file to Sharepoint, and my image creates, but can not be open, maybe some data are not transfering corectly?

Code: Select all

objParam := { "filename": ["Capture.jpg"] }

CreateFormData(postData, ContentType, objParam)

FileGetSize, filesize, %filename%
whr := ""
whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
whr.Open("POST", "https://xxx.sharepoint.com/sites/xxx/_api/web/GetFolderByServerRelativeUrl('" url "')/Files/add(url='" filename "')", true)
whr.SetRequestHeader("Content-Type", ContentType)
whr.SetRequestHeader("Authorization", "Bearer " access_token "")
whr.SetRequestHeader("Accept", "application/json;odata=nometadata")
whr.SetRequestHeader("X-RequestDigest", FormDigestValue)
whr.SetRequestHeader("Content-length", filesize)
whr.Option(6) := False ; No auto redirect
whr.Send(postData)
whr.WaitForResponse()
variable := ""
variable := whr.ResponseText
MsgBox,,, %variable%, 0
blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: WinHttp post request

27 Feb 2021, 05:58

Acctually I did it with .pdf file, but .jpg have some problems and cant be read when is uploaded.

blue
Gate
Posts: 27
Joined: 31 Jan 2021, 20:00

Re: WinHttp post request

17 Dec 2021, 21:54

Hi there,

I've modified the GetWebPage function to handle JSON well. Posting here for anyone to use.

Code: Select all


JsonData := {"contact": {"email": "[email protected]","firstName": "John","lastName": "Doe","phone": "7223224241","fieldValues":[{"field":"1","value":"The Value for First Field"},{"field":"6","value":"2008-01-20"}]}}
msgbox % GetWebPage(URL,JsonData,{ "API-TOKEN" : APIkey })
; get BuildJson() https://www.autohotkey.com/board/topic/95262-obj-json-obj/

getWebPage(url, postData := 0, headers := 0, method := 0)
{   	
	if (postData && IsObject(postData))
		postData := BuildJson(postData)
	
	whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")    ; Static will make it use the same object in memory	
    whr.Open((method?method:(postData?"POST":"GET")), url, true)                ; Post or Get depending if postdata is submitted
    whr.SetTimeouts("30000", "30000", "30000", "30000")         ; timeout 30 seconds
	
    postData ? whr.SetRequestHeader("Content-Type", "application/json")	
	
	if (IsObject(headers))
		for k, v in headers
			whr.SetRequestHeader(k, v)
	
	(postData?whr.Send(postData):whr.Send())
    whr.WaitForResponse()
    Return whr.ResponseText
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 282 guests