Excel VBA MSXML2.XMLHTTP60 PUT request fail on "send" action - excel

I'm creating an integration with Jira on Excel using VBA.
I'm able to login securely (using POST) and retrieve Jira issues (using GET) using Jira's API.
Now I'm trying to update issues, and the HTTP verb on Jira's API is GET. This shouldn't be a problem, but the fact is I can't even make the request.
Here's my current code - it's based on the POST code, but I'm not sure if I'm missing some other params.
I'm omitting some variable declarations - this is not the issue!
Public JiraService As New MSXML2.XMLHTTP60
JiraDataUrl = "https://atlassian.XXXXXXXX.com/jira/rest/api/2/issue/" & JiraId
body = "{""fields"" : {""customfield_13800"":""2011-10-03""}}"
Call JiraLogin(user, pass) 'This calls another Sub that log into Jira
JiraService.Open "PUT", JiraDataUrl, False
JiraService.setRequestHeader "Content-Type", "application/json"
JiraService.setRequestHeader "Accept", "application/json"
JiraService.setRequestHeader "X-Atlassian-Token:", "nocheck"
JiraService.send body
jsonText = JiraService.responseText
sStatus = JiraService.Status
When I run the script, it's interrupted by excel with the following messages:
I click on Debug and the JiraService.send body part is marked on the code
If I click on play, I get the final error (This method cannot be called after the send method has been called), that doesn't make any sense to me:
If I replace PUT for POST it runs normally, but Jira API returns with 405 HTTP error - as the method I'm trying to use requires a PUT.
Any idea on what am I doing wrong in this code?

I am doing the same thing right now, and I've figured out, that updating an issue requers async connection:
JiraService.Open "PUT", URL, True
In that case
JiraService.send data
will be succesful, but JiraService.status returns 1223! However, an issue field will be updated...
There is a discussion with the same "problem" with MSXML2.XMLHTTP60 and it seems, 1223 code is a kind of "success code":
https://social.msdn.microsoft.com/Forums/en-US/c4911cd8-caba-4c25-b71c-fe2e1a7ef8be/update-sharepoint-list-metadata-using-rest-from-vba-using-msxml2xmlhttp60

Related

Node- soap request - Setting preemptive authorization

I'm new at soap requests, and after setting username and pwd, I also need to set preemptive option. To true or setting the type. I reealy want o know how to set this option since that resolved my request problem in soapUi tool.
code on Angular:
client.setEndpoint(this.apiUrlSoap);
client.addHttpHeader('Authorization', 'Basic ' + btoa('user:pwd'));
I search a lot for this and couldn't find any answer.
Thank you
I tried this:
client.addHttpHeader('Authentication Type', 'Preemptive') ??? Not this for sure...
Meanwhile I've tried another aproach but still didn't work...
client.addHttpHeader("httpclient.authentication.preemptive", "true");
client.addHttpHeader("Authentication-Type", "Preemptive");
Result in Request Headers:
Authentication-Type: Preemptive
Authorization: Bearer
httpclient.authentication.preemptive: true
The status code is 200 ok, but in preview I only see the user and password inputs. I just want to pass that...

VBA: XMLHTTP request fails until I toggle POST/GET

Okay, I need the internet's collective wisdom on this one.
I'm calling an API from Excel (code abbreviated, most of this code I got online. Need to use late binding, but not sure if MSXML2.XMLHTTP.6.0 is the best to use - Excel 365):
Dim body as String
Dim request as Object
Dim isAsync as Boolean
Set request = CreateObject("MSXML2.XMLHTTP.6.0")
isAsync = False
body = "...just some query params"
With request
.Open "POST", authUrl, isAsync
.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
.setRequestHeader "User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"
.send body
'spin wheels whilst waiting for response
While request.ReadyState <> 4
DoEvents
Wend
Debug.print(.responseText)
End With
The issue I'm having is that the first time this code runs, it fails on the .send body line with the following error:
However, if I change "POST" to "GET" it will fail again, albeit because the server doesn't accept that method apparently. But then if I change it back to POST and run it again, it runs fine!
Then, if I save the file, close Excel, open the file again and try to run, again it's the same error as above!
So why am I having to "shake" it like this, toggling the method back and forth? It doesn't make any sense to me why that works. Obviously, I can't tell my end users to mess with the code like this, so I'd like to know what's happening. What can I test and try?
Update (May 5):
If I put a breakpoint at .send body then try to step over that (it errors), and debug, I see that request.status has a value of 12019, which is apparently some kind of bogus IE error code (?). I am running this on a machine that has IE 11, Edge, and Chrome installed. Would changing the User Agent string do anything? I tried the Chrome string as given on MDN, as well as just "MyApp" but it didn't change anything.
At this point, I'm wondering if I have to just do On Error Resume Next, try it as-is, then send the request again with GET and then again with POST and see if that works, although that's a hateful, hacky workaround.

How do i export as global variable

I have a karate feature file
Scenario: Feature
Given url 'https://testlocal/v1/test/authorize'
And request 'type=code&uri=http://www.testlocal/app'
And header Accept = 'application/x-www-form-urlencoded'
And header Content-Type = 'application/x-www-form-urlencoded'
When method POST
Then status 302
* def code = responseHeaders['Location'][0].substring(59,95)
* print code
when i run the above feature file i can see the code being printed seperately, however I would like to use that code in the following of the same feature file
Scenario: Login
Given url 'https://testlocal/v1/test/authorize/login'
And request 'username=test1#gmail.com&password=123!&requestId=**"I am not sure how to call the above code here"**
And header Accept = 'application/x-www-form-urlencoded'
And header Content-Type = 'application/x-www-form-urlencoded'
When method POST
Then status 302
Thanks
Sounds like you just need a Background: section, refer to this as a good example of re-use: headers.feature.
If you really need re-use across multiple feature files, refer to the documentation on how to re-use feature files via the call keyword.
I'd like to suggest an improvement to your test, you can do the following instead of manually forming the request, using the form field syntax:
EDIT: full solution
Background:
Given url 'https://testlocal/v1/test/authorize'
And form field type = 'code'
And form field uri = 'http://www.testlocal/app'
When method post
Then status 302
And def code = responseHeaders['Location'][0].substring(59,95)
Scenario: login
Given path 'login'
And form field username = 'test1#gmail.com'
And form field password = '123!'
And form field requestId = code
When method post
Then status 302

Azure Logic App: how to make a x-www-form-encoded?

I'm trying to make a request with Content-Type x-www-form-urlencoded that works perfectly in postman but does not work in Azure Logic App I receive a Bad Request response for missing parameters, like I'd not send enything.
I'm using the Http action.
The body value is param1=value1&param2=value2, but I tried other formats.
HTTP Method: POST
URI : https://xxx/oauth2/token
In Headers section, add the below content-type:
Content-Type: application/x-www-form-urlencoded
And in the Body, add:
grant_type=xxx&client_id=xxx&resource=xxx&client_secret=xxx
Try out the below solution . Its working for me .
concat(
'grant_type=',encodeUriComponent('authorization_code'),
'&client_id=',encodeUriComponent('xxx'),
'&client_secret=',encodeUriComponent('xxx'),
'&redirect_uri=',encodeUriComponent('xxx'),
'&scope=',encodeUriComponent('xxx'),
'&code=',encodeUriComponent(triggerOutputs()['relativePathParameters']['code'])).
Here code is dynamic parameter coming from the previous flow's query parameter.
NOTE : **Do not forget to specify in header as Content-Type ->>>> application/x-www-form-urlencoded**
Answering this one, as I needed to make a call like this myself, today.
As Assaf mentions above, the request indeed has to be urlEncoded and a lot of times you want to compose the actual message payload.
Also, make sure to add the Content-Type header in the HTTP action with value application/x-www-form-urlencoded
therefore, you can use the following code to combine variables that get urlEncoded:
concat('token=', **encodeUriComponent**(body('ApplicationToken')?['value']),'&user=', **encodeUriComponent**(body('UserToken')?['value']),'&title=Stock+Order+Status+Changed&message=to+do')
When using the concat function (in composing), the curly braces are not needed.
First of all the body needs to be:
{ param1=value1&param2=value2 }
(i.e. surround with {})
That said, value1 and value2 should be url encoded. If they are a simple string (e..g a_b) then this would be find as is but if it is for exmaple https://a.b it should be converted to https%3A%2F%2Fa.b
The easiest way I found to do this is to use https://www.urlencoder.org/ to convert it. convert each param separately and put the converted value instead of the original one.
Here is the screenshot from the solution that works for me, I hope it will be helpful. This is example with Microsoft Graph API but will work with any other scenario:

Excel Internet Explorer Automation Causes IE Environment to Crash

I've successfully automated a VBA Excel macro to iterate through a loop and hit a series of URL's to trigger a server-side script - this is simply done with:
myIE.Navigate ("http://someURL.php?VARIABLE=" & var_string)
where var_string is assigned within the loop as it iterates through. Before this, I've cleared cache, cookies and history with:
Shell "RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess #
I've tried many #'s including 8,2, 16 etc to see if any of these had an effect (and combination of #'s).
The issue I am having, is that although the entire script SOMETIMES works, if I were to run it a second time the line where I navigate to the URL fails to call the URL even though the domain/URL is fully live and functional. Any other URL I manually type into the IE window works just fine - just not the one I am calling inside the loop. IE is locking me out of that domain temporarily. If I come back to the script a few hours from last running it, it generally works.
Again the domain is functional and script is fine - I verify it all the time with another machine.
It's as if I am setting something environmentally and breaking Internet Explorer within VBA even though the script is absurdly simple.
I've tried CreateObject(), GetObject as well as InternetExplorerMedium for myIE object.
If all you need is to "touch" that URL for its side effects, you can as well use a XMLHTTP object. In VBA, go to menu Tools, then References and choose Microsoft XML, v6.0. Then:
Dim Request As New XMLHTTP
Request.open "GET", Url & "?VARIABLE=" & var_string, False
Request.send
' Check Request.status, probably for 200
Some notes:
You may want to use POST instead of GET, if you're having problems with caching
You should pass the data in the POST body, if the server can handle it
The value of var_string should be escaped, in this case, URL encoded
If you don't want to block waiting for responses, you can make requests asynchronously (True third argument to open)
Following these notes, here's a more elaborate example:
Dim Request As New XMLHTTP
Request.open "POST", Url, True
Dim Handler As New CXMLHTTPHandler
Handler.Initialize Request
Set Request.onreadystatechange = Handler
Request.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
Request.send UrlEncode("VARIABLE") & "=" & UrlEncode(var_string)
' This returns immediately, the check must now be done in the Handler
For the missing pieces, here's the code for CXMLHTTPHandler, which I actually found through stackoverflow, and a definition of UrlEncode at stackoverflow.
You should specialize CXMLHTTPHandler for your needs, probably even make it accept an AddressOf a procedure and call it in the actual default procedure. The default procedure should set the m_xmlHttp to Nothing when m_xmlHttp.readyState is 4.
EDIT 1: If your request code is in a loop, you need to break the Dim ... New statements in two, to ensure you're using fresh objects:
Dim Request As XMLHTTP
Set Request = New XMLHTTP
Request.open "POST", Url, True
Dim Handler As CXMLHTTPHandler
Set Handler = New CXMLHTTPHandler
Handler.Initialize Request
Set Request.onreadystatechange = Handler
Request.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
Request.send UrlEncode("VARIABLE") & "=" & UrlEncode(var_string)
' This returns immediately, the check must now be done in the Handler

Resources