Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

WinHTTP.WinHTTPRequest error

Status
Not open for further replies.

AlastairP

Technical User
Feb 8, 2011
286
AU
I am using WinHTTP.WinHTTPRequest to send a request to a server.
I am having trouble with an error "OLE IDispatch exception code 0 from WinHTTP.WinHTTPRequest: a connection to the server could not be established.

I have ensured that my headers are all correct. To check this I added the same headers with an add-on in Chrome browser and sent the request. This worked.
The error occurs at the .send() method.
Is there any flags or setting I need to make before the send method?


Code:
SELECT cTable 
lcURL = ALLTRIM(companyURL) && the URL that forms part of every request for data
lcAccessToken= 'Bearer ' + ALLTRIM(Access_token)
lcUserPass = STRCONV(ALLTRIM(Username) + ':' + ALLTRIM(Password),13)
lcApi=ALLTRIM(apikey)

LOCAL ServerRequest AS WinHttp.WinHttpRequest
oServerRequest = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")

oServerRequest.Open("GET",lcURL, .f.)
oServerRequest.SetRequestHeader('Authorization',lcAccessToken)
oServerRequest.SetRequestHeader('x-myobapi-cftoken',lcUserPass)
oServerRequest.SetRequestHeader('x-myobapi-key',lcApi)
oServerRequest.SetRequestHeader('x-myobapi-version','v2') 
oServerRequest.SetRequestHeader('Content-Type','application/json') 
oServerRequest.SetRequestHeader('Accept-Encoding','gzip,deflate') 

oServerRequest.Send()
lcResponseText  = "" + oServerRequest.ResponseText
 
AlaistarP,

Most probably the problem comes from the value of [tt]lcURL[/tt]. The Open method only checks the URL syntax and protocol, it's the Send method that will complain if there is a problem with the actual connection.
 
Try this to just check if there is something wrong with the WinHttp.WinHttpRequest.5.1 class on your system.

Code:
LOCAL ServerRequest AS WinHttp.WinHttpRequest
oServerRequest = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")

oServerRequest.Open("GET","[URL unfurl="true"]https://google.com",[/URL] .f.)
oServerRequest.SetRequestHeader('Authorization',"blahblah")
oServerRequest.SetRequestHeader('x-myobapi-cftoken',"user:pass")
oServerRequest.SetRequestHeader('x-myobapi-key',"apikey")
oServerRequest.SetRequestHeader('x-myobapi-version','v2') 
oServerRequest.SetRequestHeader('Content-Type','application/json') 
oServerRequest.SetRequestHeader('Accept-Encoding','gzip,deflate') 

oServerRequest.Send()
lcResponseText  = "" + oServerRequest.ResponseText 
? Left(lcResponseText,200)

A simple test, because every website will simply ignore any headers it doesn't know. This works for me. If you get the same OLE error, then something is wrong in your system. So first just text that 1:1.

One thing is obviously wrong with your request. With the Content-Type header you announce sending JSON (this is not specifying what you expect as result, but the content of this request), but you send nothing. Maybe you mixed instructions for sending authentication info via header and via JSON body or there is something missing.

Anyway, that code in itself has no problem, but the server you want to use needs to be addressed differently. I know this can be frustrating, but this often is very pedantic about formats and structure, sometimes even just a CR is necessary.

The OLE error really just points out what it points out, the server rejects your request you don't establish a connection. That indeed differs from something like the response status 4040 (not found) or such errors, you don't even get through to establishing the connection as it rejects your credentials. Something needs to be sent over differently than you do. That's details of whatever API you're using. Nobody can tell you what to change.

Bye, Olaf.

Olaf Doschke Software Engineering
 
AlastairP said:
I have tested the URL and it is ok.

You're assuming that you're reproducing the same circumstances. That will require at least a confirmation. For instance, WinHTTP is affected by NETSH connexion settings, while Google Chrome isn't.
 
You also might look into this: thread184-1715949
Or look into thread184-1728463

and what is said there about using which versions of WinHTTP.WinHTTPRequest.

Googling 'x-myobapi-cftoken' I think you use the myob.com api. That asks you to send user:passwird base 64 encoded. You should really simply look more closely what your request headers needs to contain.

Bye, Olaf.



Olaf Doschke Software Engineering
 
Good Morning,
I believe that my headers are all correct: Let me provide some more background.
I validated the URL by first opening the web connection in Chrome with no headers.
This was the Response:

Code:
{
    "Errors": [
      {
        "Name": "DeveloperInactive",
        "Message": "API key is missing or inactive",
        "AdditionalDetails": "Header: x-myobapi-key",
        "ErrorCode": null,
        "Severity": "Error",
        "LearnMore": "[URL unfurl="true"]http://developer.myob.com/api/accountright/api-overview/error-messages/?label=developer_inactive&context=403"[/URL]
      }
    ],
    "Information": "Warning, error messages have not been finalised in this release and may change"
}

Next I entered the headers into Chrome and it worked. The result was the response I was expecting being a list of company files.
I used the exact same headers as my code by setting up a controls on the form, then copying the header values into the headers I created in Chrome, using an addon.
To check the exactness I tried changing 1 character at random and I would get various responses such as:

"OAuthTokenIsInvalid"
"The supplied OAuth token (Bearer) is not valid Header"

The user:password is base 64 encoded and worked properly as I get the correct response as above in Chrome.
Code:
lcUserPass = STRCONV(ALLTRIM(Username) + ':' + ALLTRIM(Password),13)

To get to this stage, I have already used WinHTTP.WinHTTPRequest a number of times and ways to get access tokens, refresh tokens etc.

For example here is my code for getting access token using a "POST" request:

Code:
********************************************************************************************
*** This method gets the access token by sending the access code                         ***
********************************************************************************************


oServerRequest=this.create_winhttprequest()

*!*	'client_id' // your API Key
*!*	'client_secret' // your API Secret
*!*	'scope' // this should say CompanyFile
*!*	'code' // the Access Code you just got
*!*	'redirect_uri' // your redirect URL
*!*	'grant_type' // this should say authorization_code

lcCode = this.codereturned

SELECT MYOB_System

lcURL = ALLTRIM(post_url)
lcRedirectURI = ALLTRIM(Redirect_URI)
lcRedirectURL = ALLTRIM(Redirect_URL)
lcApi=ALLTRIM(apikey)
lcScope = 'CompanyFile'
lcSecret = ALLTRIM(secretkey)
lcGrant_type='authorization_code'
lcHeader = "application/x-[URL unfurl="true"]www-form-urlencoded"[/URL] 

lcData = 'code=' + lcCode + '&redirect_uri=' + lcRedirectURI + '&client_id=' + lcApi + '&scope=' + lcScope + '&client_secret=' + lcSecret + '&grant_type=' + lcGrant_type


&& Get Response
lcFail=.f.
TRY 
	oServerRequest.Open("POST",lcURL, .f.)
	oServerRequest.SetRequestHeader('Content-Type',lcHeader) 
	oServerRequest.Send(lcData)
	lcResponseText  = "" + oServerRequest.ResponseText
CATCH 
	lcFail=.t.
ENDTRY 

IF lcFail=.t.
	MESSAGEBOX("There was some kind of error sending the request to the server. Please check the connection or settings")
	RETURN 
ENDIF
 
I have run this in Postman, and it also worked.
Here is the request:

Code:
GET /accountright HTTP/1.1
Host: api.myob.com
x-myobapi-key: (Changed for security)
x-myobapi-version: v2
Accept-Encoding: gzip,deflate
Authorization: Bearer AAEAAJ (Truncated)
x-myobapi-cftoken: QWRtaW5pc3RyYXRvcjo=
User-Agent: PostmanRuntime/7.15.0
Accept: */*
Cache-Control: no-cache
Postman-Token: f83c7233-08f2-4847-9481-65d48d7c8059,747fc432-aace-478c-8dd6-57e97b4ee780
Host: api.myob.com
Connection: keep-alive
cache-control: no-cache

And the response headers:
Code:
Cache-Control ?must-revalidate, private
Content-Encoding ?gzip
Content-Type ?application/json; charset=utf-8
Date ?Fri, 19 Jul 2019 21:36:13 GMT
Expires ?-1
Server ?Microsoft-IIS/10.0
Vary ?Accept-Encoding
X-AspNet-Version ?4.0.30319
X-Mashery-Message-ID ?69196c44-5741-41d3-8ffb-9d8713d38069
X-Mashery-Responder ?prod-j-worker-ap-southeast-2a-34.mashery.com
x-myobapi-elapsed ?18
x-myobapi-requestid ?b37e9118-128d-4329-8275-1d391aa71e2a
X-Powered-By ?ASP.NET
Content-Length ?543
Connection ?keep-alive


 
AlastairP,

Testing from my side:

Code:
LOCAL HTTPRequest AS WinHttp.WinHttpRequest

m.HTTPRequest = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")

m.HTTPRequest.Open("Get", "[URL unfurl="true"]https://api.myob.com/accountright",[/URL] .f.)
m.HTTPRequest.SetRequestHeader('Authorization',"blahblah")
m.HTTPRequest.SetRequestHeader('x-myobapi-cftoken',"user:pass")
m.HTTPRequest.SetRequestHeader('x-myobapi-key',"apikey")
m.HTTPRequest.SetRequestHeader('x-myobapi-version','v2') 
m.HTTPRequest.SetRequestHeader('Content-Type','application/json') 
m.HTTPRequest.SetRequestHeader('Accept-Encoding','gzip,deflate') 

m.HTTPRequest.Send()

? m.HTTPRequest.Status
?
? m.HTTPRequest.GetAllResponseHeaders()
?
? m.HTTPRequest.Responsetext

results in

[tt]403

Connection: keep-alive
Date: Fri, 19 Jul 2019 22:06:11 GMT
Content-Length: 474
Content-Type: application/json
Server: Mashery Proxy
X-Error-Detail-Header: Account Inactive
X-Mashery-Error-Code: ERR_403_DEVELOPER_INACTIVE
X-Mashery-Message-ID: e07d8064-6408-4047-a42c-e4c101d6646e
X-Mashery-Responder: prod-j-worker-ap-southeast-2b-37.mashery.com

{
"Errors": [
{
"Name": "DeveloperInactive",
"Message": "API key is missing or inactive",
"AdditionalDetails": "Header: x-myobapi-key",
"ErrorCode": null,
"Severity": "Error",
"LearnMore": " }
],
"Information": "Warning, error messages have not been finalised in this release and may change"
}
[/tt]

but no error from the Send() method, that works as expected and returns an HTTP status, headers, and response.
 
I feel a little silly, but I have discovered something.
I installed Microsoft TLS hotfix which was recommended on the MYOB support website
I rebooted my computer.
Tested and now worked.
But I am not sure if it was the hotfix or the reboot that fixed it

However, WinHttpRequest was working for other calls prior to reboot as I needed to update the access token every 20 minutes.

I am wondering if I may need a way to reload/restart WinHttp.WinHttpRequest.5.1 on the fly without restarting the server the application resides on.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top