google-api-ruby-client: Request serialization results in empty requests - ruby

replacement_requests = [
Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: "{{name}}", replace_text: "Joe"),
Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: "{{age}}", replace_text: "34"),
Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: "{{address}}", replace_text: "Westwood"),
]
batch_request = Google::Apis::DocsV1::BatchUpdateDocumentRequest.new(requests: replacement_requests)
Given the above code, when I pass this BatcUpdateDocumentRequest instance into my service.batch_update_document function, I receive a 400 bad request. This seems to be related to the way the batch request is being serialized.
To illustrate, if we call batch_request.to_json we receive the following:
"{\"requests\":[{},{},{}]}"
This tells me that something is going wrong during serialization, however my code seems rather canonical.
Any thoughts on why my requests are failing to be serialized?

You want to use the replaceAllText request using google-api-client with ruby.
You have already been able to put and get values for Google Document using Google Docs API.
If my understanding is correct, how about this modification? In your script, the created request body is {"requests":[{},{},{}]}. By this, the error occurs. Please modify the script as follows.
Modification points:
Use Google::Apis::DocsV1::SubstringMatchCriteria for contains_text of Google::Apis::DocsV1::ReplaceAllTextRequest
Use Google::Apis::DocsV1::Request for Google::Apis::DocsV1::ReplaceAllTextRequest.
By above modification, the request body is created.
Modified script:
text1 = Google::Apis::DocsV1::SubstringMatchCriteria.new(text: "{{name}}")
text2 = Google::Apis::DocsV1::SubstringMatchCriteria.new(text: "{{age}}")
text3 = Google::Apis::DocsV1::SubstringMatchCriteria.new(text: "{{address}}")
req1 = Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: text1 , replace_text: "Joe")
req2 = Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: text2, replace_text: "34")
req3 = Google::Apis::DocsV1::ReplaceAllTextRequest.new(contains_text: text3, replace_text: "Westwood")
replacement_requests = [
Google::Apis::DocsV1::Request.new(replace_all_text: req1),
Google::Apis::DocsV1::Request.new(replace_all_text: req2),
Google::Apis::DocsV1::Request.new(replace_all_text: req3)
]
batch_request = Google::Apis::DocsV1::BatchUpdateDocumentRequest.new(requests: replacement_requests)
# result = service.batch_update_document(document_id, batch_request) # When you request with "batch_request", you can use this.
Request body:
When above script is run, the following request body is created.
{"requests":[
{"replaceAllText":{"containsText":{"text":"{{name}}"},"replaceText":"Joe"}},
{"replaceAllText":{"containsText":{"text":"{{age}}"},"replaceText":"34"}},
{"replaceAllText":{"containsText":{"text":"{{address}}"},"replaceText":"Westwood"}}
]}
Note:
When the error related to the authorization occurs, please confirm the scopes and whether Docs API has been enabled.
References:
Method: documents.batchUpdate
ReplaceAllTextRequest
If this didn't work, I apologize.

Related

how save value in string variable by Javascript executor in jmeter web sampler

Hi I want to store the value return by below code in JMeter webDriver Sampler . but i am getting error.
String access_token = WDS.browser.executeScript("return window.localStorage.getItem(localStorage.key(2))");
WDS.log.info("access_token : " + access_token);
OR
var access_token = WDS.browser.executeScript("return window.localStorage.getItem(localStorage.key(2))");
WDS.log.info("access_token : " + access_token);
Both above ways are not working?
In order to be able to help we need to know the details of the error "you are getting". Also it's unclear what localStorage.key(2) object stands for.
Here is an example of getting se:fkey value from https://stackoverflow.com website:
I used default language for WebDriver Sampler: javascript and the following piece of code:
WDS.sampleResult.sampleStart()
WDS.browser.get('https://stackoverflow.com')
var access_token = WDS.browser.executeScript('return window.localStorage.getItem("se:fkey")')
WDS.log.info('Got the following value from local storage: ' + access_token)
WDS.sampleResult.sampleEnd()
And it works just fine:
If you additionally need to store the value into a JMeter Variable add the following line:
WDS.vars.put('access_token', access_token)
and you will be able to access the extracted value as ${access_token} where required.
More information: The WebDriver Sampler: Your Top 10 Questions Answered

Ruby Post returns 404 URL Not found while curl works fine

I'm trying to write some Ruby code to update GitLab CI/CD variables using the REST endpoint update variable. When I perform a curl with the same path, the same private token, and the same --form data it updates the variable as expected. When I use the Ruby code that I put together based on reading stackoverflow and the net::http docs, it fails with a 404 URL not found.
I can use a similar piece of code to create a new CI/CD variable successfully. I can also delete an existing variable, and re-create it, but it I would like to know the mistake I am making in the update call.
Can someone point out what I did wrong?
#!/usr/bin/env ruby
require 'net/http'
require 'uri'
token = File.read(__dir__ + '/.gitlab-token').chomp
host = 'https://gitlab.com/'
variables_path = 'api/v4/projects/123456/variables'
env_var = 'MY_VAR'
update_uri = URI(host + variables_path + '/' + env_var)
# I've written the above this way because my actual code
# has a delete and create in order to "update" the variable
response = Net::HTTP.start(update_uri.host, update_uri.port, use_ssl: true) do |http|
update_request = Net::HTTP::Post.new(update_uri)
update_request['PRIVATE-TOKEN'] = token
form_data = [
['value', 'a new value']
]
update_request.set_form(form_data, 'multipart/form-data')
response = http.request(update_request)
response.body
end

how to make an api call to server which requires special characters using NSURL session?

I am building an iOS app with Swift2.0, XCode 7.2
I am trying to make an api call to:
htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={"locality":{"$eq":"miami"}}
let endPoint:String = "htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={%22locality%22:{%22$eq%22:%22miami%22}}"
When I try to create an URL using this string(endPoint):
let url = NSURL(string: endPoint), a nil is returned.
So I tried encoding the string before trying to create URL:
let encodedString = endPoint.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
Now the encodedString:
"htttp://xyz.com/t/restaurants-us?KEY=someKey&filters=%7B%2522locality%2522:%7B%2522$eq%2522:%2522miami%2522%7D%7D"
But now when i create a NSURL session and send the request, I get an unexpected response from the server:
Reply from server:
{
"error_type" = InvalidJsonArgument;
message = "Parameter 'filters' contains an error in its JSON syntax. For documentation, please see: http://developer.factual.com.";
status = error;
version = 3;
}
So if I don't encode the string, I will not be able to create NSURL.
But if I encode and send the request, the server is not able to handle the request.
Can anyone please suggest a workaround.
When you declare endpoint, you have already percent-encoded some characters (the quotes). When you ask iOS to percent-encode it, it percent-encodes the percent-encodes. Decoding the encodedString results in:
htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={%22locality%22:{%22$eq%22:%22miami%22}}
Instead, you should start with actual quotes in endpoint:
let endPoint:String = "htttp://xyz.com/t/restaurants-us?KEY=someKey&filters={\"locality\":{\"$eq\":\"miami\"}}"

Ruby's Net::HTTP doesn't get the right answer from google OAuth server

I'm writing a small cli tool, that should check my calendar and do some stuff according to my appointments.
I'm struggling a little bit with the OAuth2 authentication. I've checked the scope and the client_id with the curl tool like this:
curl -d "client_id=12345...&scope=scope=https://www.googleapis.com/auth/calendar.readonly" https://accounts.google.com/o/oauth2/device/code
This way, I get the right response.
{
"device_code" : "somestuff",
"user_code" : "otherstuff",
"verification_url" : "http://www.google.com/device",
"expires_in" : 1800,
"interval" : 5
}
But, when I try to use Net::HTTP in Ruby I just get HTTP state 200. I've done it this way:
res = Net::HTTP.post_form(uri, {'client_id' =>'1234....apps.googleusercontent.com', 'scope' => 'https://www.googleapis.com/auth/calendar.readonly' })
If I check the res variable afterwards I get the state 302, but I guess this is correct.
Can someone tell me what I'm, doing wrong so I don't get the JSON response? Should I try something different than Net::HTTP?
res is a variable containing all the response data, not just the text of the response. If you puts res.body after your post_form() call, you should find your JSON (which you can parse with the JSON module).

Sending An HTTP Request using Intersystems Cache

I have the following Business Process defined within a Production on an Intersystems Cache Installation
/// Makes a call to Merlin based on the message sent to it from the pre-processor
Class sgh.Process.MerlinProcessor Extends Ens.BusinessProcess [ ClassType = persistent, ProcedureBlock ]
{
Property WorkingDirectory As %String;
Property WebServer As %String;
Property CacheServer As %String;
Property Port As %String;
Property Location As %String;
Parameter SETTINGS = "WorkingDirectory,WebServer,Location,Port,CacheServer";
Method OnRequest(pRequest As sgh.Message.MerlinTransmissionRequest, Output pResponse As Ens.Response) As %Status
{
Set tSC=$$$OK
Do ##class(sgh.Utils.Debug).LogDebugMsg("Packaging an HTTP request for Saved form "_pRequest.DateTimeSaved)
Set dateTimeSaved = pRequest.DateTimeSaved
Set patientId = pRequest.PatientId
Set latestDateTimeSaved = pRequest.LatestDateTimeSaved
Set formName = pRequest.FormName
Set formId = pRequest.FormId
Set episodeNumber = pRequest.EpisodeNumber
Set sentElectronically = pRequest.SentElectronically
Set styleSheet = pRequest.PrintName
Do ##class(sgh.Utils.Debug).LogDebugMsg("Creating HTTP Request Class")
set HTTPReq = ##class(%Net.HttpRequest).%New()
Set HTTPReq.Server = ..WebServer
Set HTTPReq.Port = ..Port
do HTTPReq.InsertParam("DateTimeSaved",dateTimeSaved)
do HTTPReq.InsertParam("HospitalNumber",patientId)
do HTTPReq.InsertParam("Episode",episodeNumber)
do HTTPReq.InsertParam("Stylesheet",styleSheet)
do HTTPReq.InsertParam("Server",..CacheServer)
Set Status = HTTPReq.Post(..Location,0) Quit:$$$ISERR(tSC)
Do ##class(sgh.Utils.Debug).LogDebugMsg("Sent the following request: "_Status)
Quit tSC
}
}
The thing is when I check the debug value (which is defined as a global) all I get is the number '1' - I have no idea therefore if the request has succeeded or even what is wrong (if it has not)
What do I need to do to find out
A) What is the actual web call being made?
B) What the response is?
There is a really slick way to get the answer the two questions you've asked, regardless of where you're using the code. Check the documentation out on the %Net.HttpRequest object here: http://docs.intersystems.com/ens20102/csp/docbook/DocBook.UI.Page.cls?KEY=GNET_http and the class reference here: http://docs.intersystems.com/ens20102/csp/documatic/%25CSP.Documatic.cls?APP=1&LIBRARY=ENSLIB&CLASSNAME=%25Net.HttpRequest
The class reference for the Post method has a parameter called test, that will do what you're looking for. Here's the excerpt:
method Post(location As %String = "", test As %Integer = 0, reset As %Boolean = 1) as %Status
Issue the Http 'post' request, this is used to send data to the web server such as the results of a form, or upload a file. If this completes correctly the response to this request will be in the HttpResponse. The location is the url to request, e.g. '/test.html'. This can contain parameters which are assumed to be already URL escaped, e.g. '/test.html?PARAM=%25VALUE' sets PARAM to %VALUE. If test is 1 then instead of connecting to a remote machine it will just output what it would have send to the web server to the current device, if test is 2 then it will output the response to the current device after the Post. This can be used to check that it will send what you are expecting. This calls Reset automatically after reading the response, except in test=1 mode or if reset=0.
I recommend moving this code to a test routine to view the output properly in terminal. It would look something like this:
// To view the REQUEST you are sending
Set sc = request.Post("/someserver/servlet/webmethod",1)
// To view the RESPONSE you are receiving
Set sc = request.Post("/someserver/servlet/webmethod",2)
// You could also do something like this to parse your RESPONSE stream
Write request.HttpResponse.Data.Read()
I believe the answer you want to A) is in the Server and Location properties of your %Net.HttpRequest object (e.g., HTTPReq.Server and HTTPReq.Location).
For B), the response information should be in the %Net.HttpResponse object stored in the HttpResponse property (e.g. HTTPReq.HttpResponse) after your call is completed.
I hope this helps!
-Derek
(edited for formatting)
From that code sample it looks like you're using Ensemble, not straight-up Cache.
In that case you should be doing this HTTP call in a Business Operation that uses the HTTP Outbound Adapter, not in your Business Process.
See this link for more info on HTTP Adapters:
http://docs.intersystems.com/ens20102/csp/docbook/DocBook.UI.Page.cls?KEY=EHTP
You should also look into how to use the Ensemble Message Browser. That should help with your logging needs.

Resources