Using VBScript to POST API call - post

I am not sure what I am missing. I am trying to make a call to get a token returned via API. I need this token to do further calls - like create users, etc. Anyway, if I a similar call using GET to find the status, it works. Also, if I use the same information in this code in FIDDLER, it works and returns a token. Here is the Code:
Set oWinHttp = CreateObject("WinHttp.WinHttpRequest.5.1")
msgbox("body build")
sReqBody = "<Token>" &_
"<Password>password</Password>" &_
"<SiteCode>ABC1</SiteCode>" &_
"<Username>Username1</Username>" &_
"<Token>"
msgbox("Building the POST")
sWebServiceURL ="http://testapi.releasecandidate-community360.net/api/token" 'Web Service URL
sWebhost = "testapi.community360.net"
msgbox (sWebServiceURL)
msgbox (sWebHost)
'POST the URL
oWinHttp.open "POST", "http://testapi.releasecandidate-community360.net/api/token", False
msgbox ("Set header")
'Set Header
oWinHttp.setRequestHeader "Content-Type", "application/xml"
oWinHttp.setRequestHeader "Accept", "application/xml"
oWinHttp.setRequestHeader "Host", sWebHost
oWinHttp.setRequestHeader "Content-Length", ""
msgbox("sending")
oWinHttp.send sReqBody
msgbox(sReqBody)
oWinHttp.WaitForResponse(120)
sResponse = oWinHttp.ResponseText
wscript.echo sResponse
The error is 404 - File or directiry not found.
This makes no sense since I can find that directory and FIDDLER tool works fine. I am guessing I need to talk to my Dev guys about the error messages we are returning.
But, any ideas what I am doing wrong with this? Thanks.

Related

A Python code used to get the parent message of a slack thread not working

I wanted to make an API call to get the parent message of a thread using the thread ID on zapier
This is the code I got by chatgpt to do that, I am getting a no output error and I am not sure why it happens
import requests
def main(input_data):
# Set the API endpoint, headers, and Slack API token for the request
api_endpoint = "https://slack.com/api/conversations.replies"
headers = {
"Authorization": "Bearer xoxb-3482548707638-4570295651095-8J4mDrROrcYV0U3L5FZhJtTf",
"Content-Type": "application/json; charset=utf-8"
}
slack_api_token = "xoxb-3482548707638-4570295651095-8J4mDrROrcYV0U3L5FZhJtTf"
# Set the request parameters
params = {
"channel": input_data["thread_id"],
"ts": input_data["thread_id"],
"inclusive": "true",
"limit": 1
}
# Make a GET request to the API endpoint
response = requests.get(api_endpoint, headers=headers, params=params)
# Get the first message in the result
message = response.json()["messages"][0]
# Print the message text to the console
print(message["text"])
This my first time working with API's or code, so I am pretty sure I mus have done something stupid. Could anyone point out what I did wrong
PS: After this, what should I learn to operate such codes, I find this interesting

restsharp and Postman

I am attempting to get an OAuth2 access token from ZOHO using RestSharp code. The Postman simulation works correctly so I know there is something I'm missing in my code.
I always get an "invalid client id" result status. However in Postman, it works and returns a code when I click the "Get new access token". I have the same items as in the Postman authorization tab (client_id, client_secret, etc). In Postman, "Body" is set to "none", and there are no parameters or headers. The only difference between my code and postman, is that Postman requires the Callback URL. My code is trying to get the code using "self-client", which bypasses the callback URL.
I have tried several different alternatives to the request call including ParameterType.Body, and ParameterType.GetOrPost. Is GetOrPost the same as a form?
client = New RestClient(ZOHO_API_URL)
request = New RestRequest(TokenUrl, Method.POST)
request.AddHeader("content-type", "application/x-www-form-urlencoded") ' also tried: "application/json")
request.AddParameter("grant_type", "authorization_code",
ParameterType.GetOrPost)
request.AddParameter("client_id", Client_ID, ParameterType.GetOrPost)
request.AddParameter("client_secret", Client_Secret,
ParameterType.GetOrPost)
request.AddParameter("code", Grant_Token, ParameterType.GetOrPost)
response = client.Execute(request)
This is the translated Postman code for RestSharp:
var client = new RestClient("http://");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx");
request.AddHeader("cache-control", "no-cache");
IRestResponse response = client.Execute(request);
Any ideas on what I am doing wrong. I have tried to view the raw data coming across with Fiddler, but when I do that, Postman indicates a failure.
What code do I need to use to duplicate what Postman is doing?
How do I implement a callback URL if that is also required?
I quickly checked ZoHo REST API docs and it seems like you should use the Limited Input Device authentication flow.
From what I can understand from their help page, you indeed need to do a POST request, but parameters must be specified as query parameters:
https://accounts.zoho.com/oauth/v3/device/code?
client_id=1000.GMB0YULZHJK411248S8I5GZ4CHUEX0&
scope=AaaServer.profile.READ&
grant_type=device_request
You will also get better off with JSON set as a default for serialisation and content type just by using client.UseJson().
It maybe that Postman is following a redirect from your API endpoint as the functionality is different Postman verses RestSharp (possibly missing a trailing slash or similar).
Try adding
client.FollowRedirects = false;
to your RestSharp code and analyse the result.

Shopify API HTTP POST redirecting instead of POSTing

I have code (Classic ASP) which was recently working POSTing orders to Shopify but has now stopped POSTing and either creates an error "A Redirection problem has occurred" or redirects to the admin area of the Shopify site, depending on which XMLHTTP component I employ. The code below still works on older OS but not on Server 2016 where I am working.
I can't find much on Google but there was an indication in the Shopify Forum that the problem was a result of cookies (I have set none) and that this is overcome by sending a header containing X-Shopify-Access-Token:. I tried this using the "Authorize" setRequestHeader but it made no difference, or I got the syntax wrong or something. I used
xmlhttp.setRequestHeader "Authorization","X-Shopify-Access-Token=<token>"
Below is the code that worked a few weeks back. Variable jsondata contains valid JSON to send to create an order.
Set xmlhttp = Server.CreateObject("MSXML2.ServerXMLHTTP.3.0")
xmlhttp.Open "POST", "https://<api key>:<passowrd>#<sitename>.myshopify.com/admin/orders.json", false, "<api key>", "<password>"
xmlhttp.setRequestHeader "Content-Type", "application/json; charset=utf-8"
xmlhttp.setRequestHeader "Content-Length", Len(jsondata)
xmlhttp.Send jsondata
Set xmlhttp = nothing
I expect a POST and a JSON order response but this is not happening - just a redirection to https://<sitename>.myshopify.com/admin. Any ideas anyone?

XMLHTTP Request (POST) to retrieve data from web site using VBScript

dear collegues! I need your help.
Fisrt of all, this is NOT ad. I try to make a POST request on website of railway tickets http://booking.uz.gov.ua/en/ to know if there is tickets on current date. BUT... have a problem. I'm using a VBScript to make a request. To know what HTTP Header and POST request to send on website I used Chrome in-build development tools.
Here's my script:
Dim URL
Dim URL2
Dim URL3
Dim sRequest
Dim sCookies
'This is web page where I need to enter information.
URL = "http://booking.uz.gov.ua/en/"
'This is path that Chrome shows to send POST request.
URL2 = "http://booking.uz.gov.ua/en/purchase/search/"
'Optional URL, Chrome shows this link near of URL2. I think this is .js that works on info I enter on web site (URL).
'URL3 = "http://booking.uz.gov.ua/i/js/common.138.js"
'POST request that Chrome shows to send.
sRequest ="station_id_from=2200001&station_id_till=2208001&station_from=Kyiv&station_till=Odesa&date_ dep=09.19.2013&time_dep=00%3A00&search="
'Here I'm using GET request to retrieve Set-Cookie Header (SessionID first of all) to reuse in my second POST request.
sCookies = GetSetHeader(URL)
'Here I'm calling function to make POST request.
Result = HTTPPost(URL2, sRequest)
Function GetSetHeader(URL)
Set objhttp = CreateObject("Microsoft.XmlHttp")
objhttp.open "GET", URL, FALSE
objhttp.Send
'I'm getting only SessionID + other cookies that Chrome shows.
GetSetHeader = Left (objhttp.getResponseHeader("Set-Cookie"), 38) & " " & "HTTPSERVERID=server1; _gv_lang=en; __utma=31515437.675496133.1376934004.1376934004.1376934004.1; __utmb=31515437.2.10.1376934004; __utmc=31515437; __utmz=31515437.1376934004.1.1.utmcsr= (direct)|utmccn=(direct)|utmcmd=(none)"
End Function
Function HTTPPost(URL2, sRequest)
'Header I just took from Chrome.
Set objhttp = CreateObject("Microsoft.XmlHttp")
objHTTP.open "POST", URL2, false
objHTTP.setRequestHeader "Connection", "keep-alive"
objHTTP.setRequestHeader "Host", "booking.uz.gov.ua"
objHTTP.setRequestHeader "Connection", "keep-alive"
objHTTP.setRequestHeader "Content-Length", "Len(Request)"
objHTTP.setRequestHeader "GV-Token", "64214392f178b9f91e3b61a069915cd1"
objHTTP.setRequestHeader "Origin", "http://booking.uz.gov.ua"
objHTTP.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
objHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
objHTTP.setRequestHeader "GV-Unique-Host", "1"
objHTTP.setRequestHeader "GV-Ajax", "1"
objHTTP.setRequestHeader "GV-Screen", "1366x768"
objHTTP.setRequestHeader "GV-Referer", "http://booking.uz.gov.ua/en/"
objHTTP.setRequestHeader "Accept", "*/*"
objHTTP.setRequestHeader "Referer", "http://booking.uz.gov.ua/en/"
objHTTP.setRequestHeader "Accept-Encoding", "gzip,deflate,sdch"
objHTTP.setRequestHeader "Accept-Language", "ru-RU,ru;q=0.8,en- US;q=0.6,en;q=0.4"
'Here I use cookies retrieved with first GET request.
objHTTP.setRequestHeader "Cookie", "sCookies"
objHTTP.send sRequest
'I use this msg to check that right cookies send with POST request.
WScript.Echo sCookies
HTTPPost = objHttp.responseText
'Write answer to TXT file.
Set FSO = CreateObject("Scripting.FileSystemObject")
Set oFile = FSO.OpenTextFile("D:\Results.txt", 2, True)
oFile.Write(objHttp.responseText)
oFile.Close
Set oFile = Nothing
Set FSO = Nothing
end Function
I can't make me script work. I get empty TXT file if I use URL2 to send a request. If I use URL3 - path to script that Chrome show me - to send a request, I just receive a contents of common.138.js in my TXT file. But I expect to receive info in JSON type like shown in Chrome response.
What I noticed,
First, if refresh the website, and try to resend old request, I give me an error:
NetworkError: 400 Bad Request - http://booking.uz.gov.ua/en/purchase/search/"
Maybe because SessionID changed.
Second, I can't to simply write name of station, I need to chose it from drop-down list (When work with this site in UI mode). OR I get an error - Select a departure point from a drop down list.
Third, if try to send request by simply clicking the button on site to search, I get error Status Code:400 Bad Request. I think time of SessionID expired.
There is a working script using InternetExplorer.Application system object, but it is no decision. I want to make it work by sending requests. In future want to try do it on php (as a peart of learning process).
Maybe it's some kind of defence from people like me??? There is a way to make my script work???? Maybe SessionID changes between GET and POST requests?? Or maybe VBScript can't resolve it and I need PHP, for example???
I don't know how to solve this problem. Help me please. Can't sleep. Can't eat. Thanks very very much.
You are getting "400" because you are sending wrong GV-Token header to UZ site.
Eventually GV-token is an md5 of some session-dependent variable (session is identified via _gv_sessid cookie).
This token is obfuscated in JavaScript and resides in page body like,
...
$$_.$_=($$_.$_=$$_+"")[$$_.$_$]+($$_._$=$$_.$_[$$_.__$])+($$_.$$=($$_.$+"")[$$_.__$])+((!$$_)+"")[$$_._$$]+($$_.__=$$_.$_[$$_.$$_])
...
Which evaluates to something like
localStorage.setItem('gv-token',4619709a341b4ffdacce3dafd2f85af3)
and then conducted to all UZ Ajax requests.
So I wish you happy deobfuscating :)) (not for the weak)
PS Also make sure to turn on .NET useUnsafeHeaderParsing via app configuration or reflection.
UPD: As i see, this topic is still alive, so i made up deobfuscation code - it seems like basic regular expressions & string search-and-replace are enough.
Suppose you have UZ start page HTML in pageHTML, then to make things work you need something like (sans validitiy checking), in C#:
Obfuscated code contains some tokens, each evaluates to a hex number from 0 to F, they can be directly replaced. Here is a correspondence dictionary:
var subsitutes = new Dictionary<string, string>
{
{"$$_.$$$", "7"},
{"$$_.$$$$", "f"},
{"$$_.$$$_", "e"},
{"$$_.$$_", "6"},
{"$$_.$$_$", "d"},
{"$$_.$$__", "c"},
{"$$_.$_$", "5"},
{"$$_.$_$$", "b"},
{"$$_.$_$_", "a"},
{"$$_.$__", "4"},
{"$$_.$__$", "9"},
{"$$_.$___", "8"},
{"$$_._$$", "3"},
{"$$_._$_", "2"},
{"$$_.__$" ,"1"},
{"$$_.___", "0"},
};
Then by using regex we get part of obfuscated the code we're interesed in
var scramble = Regex.Match(pageHTML, #"\$\$_\.\$\(\$\$_\.\$\((.*)\)\(\)\)\(\);");
And replace the mentioned above tokens with their real meaning
var keysSorted = subsitutes.Keys.OrderByDescending(key => key.Length);
var halfBakedDeobfuscated = keysSorted.Aggregate(scramble.Groups[1].Value, (current, key) => current.Replace(key, subsitutes[key]));
Almost done, cut out some garbage
var start = Regex.Escape(new string(new[] { '"', '\\', '\\', '\\', '"', ',', '\\', '\\', '"', '+' }) + "4+0+" + new string(new[] { '\"', '\\', '\\', '\\', '\"', '\"', '+' }));
var end = Regex.Escape(new string(new[] { '+', '"', '\\', '\\', '\\', '"', ')' }));
var core = Regex.Match(halfBakedDeobfuscated, start + "(.*)" + end).Groups[1].Value;
Now core contains almost clean version of gvToken, something like 7+0+f+a+7+7+9+8+5+7+e+b+3+3+a+8+3+c+7+8+3+b+d+d+e+f+4+8+7+7+f+7
so last step is to remove these + symbols
var gvToken = string.Join(string.Empty, core.Split('+'));
At last, gvToken contains what you need to give to UZ site - a string like 70fa779857eb33a83c783bddef4877f7.
No JS library and of course no InternetExplorer needed.
You made mistake here:
objHTTP.setRequestHeader "Content-Length", "Len(Request)"
Should be:
objHTTP.setRequestHeader "Content-Length", Len(Request)
Interesting, need to use InternetExplorer.Application, for example list powershell code:
$erroractionpreference = "Continue"
$ie = New-Object -ComObject "InternetExplorer.Application"
$ie.navigate("http://booking.uz.gov.ua/en/")
$ie.visible = $true
sleep 5
while($ie.ReadyState -ne 4) {start-sleep -m 100}
$ie.document.getElementByID("station_id_from").Value = "2200001"
$ie.document.getElementByID("station_id_till").Value = "2208001"
$ie.document.getElementsByName("station_from").Item(1).Value = "Kyiv"
$ie.document.getElementsByName("station_till").Item(1).Value = "Odesa"
$ie.document.getElementByID("date_dep").Value = "12.26.2014"
$ie.document.getElementByID("time_dep").Value = "00:00"
$ie.document.getElementByID("search").Click()
Cookies, including GV-Token, in such case need no to be transferred. I think, there is a way to write without InternetExplorer.Application but emulate browser with your code. Need to explore it.

YouTube API: Delete video HTTP request from Ruby not working

I am trying to delete a video on YouTube from a Ruby on Rails application. I am following these instructions, from the YouTube API docs:
DELETE /feeds/api/users/default/uploads/VIDEO_ID HTTP/1.1
Host: gdata.youtube.com
Content-Type: application/atom+xml
Authorization: Bearer ACCESS_TOKEN
GData-Version: 2
X-GData-Key: key=DEVELOPER_KEY
I am not very familiar with Ruby's Net::HTTP class, but it seems that no matter what I try I cannot get the request to work properly. I have looked carefully at the many other StackOverflow questions regarding deleting videos from YouTube, but none that I could find address this particular problem. My code is below, where I've replaced the user name, video ID, access token, and developer key.
url = URI.parse("https://gdata.youtube.com/feeds/api/users/[USER_NAME]/uploads/[VIDEO_ID]")
post_args = { 'Host' => 'gdata.youtube.com', 'GData-Version' => '2', 'Content-Type' => 'application/atom+xml', 'Authorization' => "Bearer [ACCESS_TOKEN]", 'X-GData-Key' => 'key=[DEVELOPER_KEY]' }
req = Net::HTTP::Delete.new(url.path)
req.set_form_data(post_args)
httpreq = Net::HTTP.new(url.host, url.port)
httpreq.use_ssl = true
resp = httpreq.start {|http| http.request(req) }
Checking the response, I get an Error 400 (Bad Request) from YouTube. The response simply says "Your client has issued a malformed or illegal request. That's all we know".
Is there something wrong with the request I'm making? I've checked it against the template time and time again and I can't see anything wrong with it. I know that my access token and developer key are working because I can make other requests like video uploads just fine.
I printed the debug output from the HTTP request, and as far as I can tell it looks fine:
<- "DELETE /feeds/api/users/[USER_NAME]/uploads/[VIDEO_ID] HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nContent-Type: application/x-www-form-urlencoded\r\nHost: gdata.youtube.com\r\nContent-Length: 275\r\n\r\n"
<- "Host=gdata.youtube.com&GData-Version=2&Content-Type=application%2Fatom%2Bxml&Authorization=Bearer+[ACCESS_TOKEN]&X-GData-Key=key%3D[DEVELOPER_KEY]"
The only thing I could see as a possible problem was that in the first line of the request, the "Content-Type" is set to "application/x-www-form-urlencoded". Again, not being an expert on HTTP requests I'm not sure what the difference is between the Content-Type set in the first line and the Content-Type that I explicitly set as "application/atom+xml" which appears on the second line of the request. After some digging, though, I found out that the set_form_data method automatically sets the content type as "application/x-www-form-urlencoded", so I tried adding the following line to my code:
req.content_type = 'application/atom+xml'
right after the line
req.set_form_data(post_args)
When I do this, I do see a corresponding change in the request:
<- "DELETE /feeds/api/users/[USER_ID]/uploads/[VIDEO_ID] HTTP/1.1\r\nAccept: */*\r\nUser-Agent: Ruby\r\nContent-Type: application/atom+xml\r\nHost: gdata.youtube.com\r\nContent-Length: 275\r\n\r\n"
<- "Host=gdata.youtube.com&GData-Version=2&Content-Type=application%2Fatom%2Bxml&Authorization=Bearer+[ACCESS_TOKEN]&X-GData-Key=key%3D[DEVELOPER_KEY]"
However, I still get the exact same response from YouTube. Error 400, bad request. What the heck is going on here??
Of course, 10 minutes after asking my question, I find out the answer. I did not understand the distinction between the HTTP header fields and form arguments, which I don't feel so bad about since it's not explained anywhere either in the Ruby documentation on Net::HTTP or in the YouTube API. The reason I was confused was because for uploading a video, you can provide all the values like Authorization and Content-Type as form data, so the above approach from my question works fine. For deleting a video, you have to provide those values as part of the header, not form data. At least, that is now my understanding.
Anyway, in case anyone ever runs into this problem, this solved it for me:
req = Net::HTTP::Delete.new(url.path)
req['GData-Version'] = '2' # this syntax sets header fields & values
req['Authorization'] = "..."
req['X-GData-Key'] = "..."
req.content_type = 'application/atom+xml'
httpreq = Net::HTTP.new(url.host, url.port)
httpreq.use_ssl = true
resp = httpreq.start {|http| http.request(req) }
Another case where one explanatory sentence from the authors of the documentation would have saved two hours of wasted time. If I had a nickel...

Resources