I am building an API using FastAPI that must be accessible from Excel VBA. FastAPI's OAuth2 authentication mechanism requires me to send a "form-data" POST request, but I don't know how to do this using WinHTTPRequest in VBA.
I already have a function which get plain JSON from the API, but this is a GET function and I'm not sure where to specify the "form-data" part in the body, nor where to put the username and password key-value pairs.
Here is a simple VBA GET that handles some errors. How would I modify this to do a form-data POST with username and password fields?
Public Function getreq(url As String)
Dim req As WinHttpRequest
Dim JsonString As String
Dim jp As Object
Dim resp As String
Dim errorstring As String
Set req = New WinHttpRequest
' req.SetRequestHeaderxxx ?
' this is where auth will go via POST form-data username and password?
req.Open "GET", url
On Error GoTo errhand:
req.Send
resp = req.ResponseText
If resp = "Internal Server Error" Then
resp = "{'error': 'Internal server error'}"
End If
getreq = resp
Exit Function
errhand:
Select Case Err.Number
Case -2147012894 'Code for Timeout
getreq = "{'error': 'Request timeout'}"
Case -2147012891 'Code for Invalid URL
getreq = "{'error': 'Bad url'}"
Case -2147012867 'Code for Invalid URL
getreq = "{'error': 'Cannot establish connection'}"
Case Else 'Add more Errorcodes here if wanted
errorstring = "Errornumber: " & Err.Number & vbNewLine & "Errordescription: " & Error(Err.Number)
getreq = "{'error': '" & errorstring & "'}"
End Select
End Function
Instead of opening a GET request req.Open "GET", url
you need to open a POST
req.Open "POST", url, False
Then you can use setRequestHeader
to set which content type you are going to send and what you accept in return.
req.setRequestHeader "Content-Type", "multipart/form-data"
req.setRequestHeader "Accept", "application/xml"
For authorization you would also need to create a request header. This depends on what your API uses.
req.setRequestHeader "Authorization:", "Bearer " & EncodeBase64("Your-access-token")
Finally you send your request
req.send (YourData)
Have a look into this answer which shows how the data structure for multipart/form-data
is generated.
If a WinHTTPRequest does not work I recommend to try the following
Set objHttp = CreateObject("MSXML2.ServerXMLHTTP.6.0")
URL = "https:///commercial/payments-processing/v1/test/token"
objHttp.Open "POST", URL, False
objHttp.setRequestHeader "Content-Type", "multipart/form-data"
objHttp.setRequestHeader "Accept", "application/xml"
objHttp.setRequestHeader "Authorization:", "Bearer [Access Token]"
objHttp.send (strPaylodValue)
strResponseStatus = objHttp.Status
strResponseText = objHttp.ResponseText
strResponseText = CStr(strResponseText)