No authentication is required to call this REST service that was created with Delphi.
The client Classes API documented (ClientClassesUnit1.pas).
function TGeneralClient.UpdateCIM2(PostData : TJSONOjbect; const ARequestFilter:string):string
begin
if FUpdateCIM2Command = nil then
begin
FUpdateCIM2Command := FConnection.CreateCommand;
FUpdateCIM2Command.RequestType := 'POST';
FUpdateCIM2Command.Text := 'TGeneral."UpdateCIM2"';
FUpdateCIM2Command.Prepare(TGeneral_UpdteCIM2);
end;
FUpdateCIM2Command.Parameters[0].Value.SetJSONValue(PostData,FInstanceOwner);
FUpdateCIM2Command.Execute(ARequestFilter);
Result := FUpdateCIM2Command.Parmeters[1].Value.GetWideString;
end;
But I would like to create a test using the Delphi REST Debugger and I cannot determine what the settings in the utility should be ... or even if the REST Debugger is capable of doing it. Postman tool doesn't seem to work either.
I tried to post a picture but can't because of company policy restrictions.
Method: POST
URL: https://wxdf0-servername.com/snap4.dll/datasnap/rest/TGeneral/UpdatCIM2
Content type: application/json
Custom body (edited)
{
"data" :{
"Stage" :"7",
"Step" :"1"
}
}
All I get in return on the debugger is "500 :Internal Server error"
What is the proper setup (if possible) to make a call to a Delphi REST call that uses TJSONObject as a parameter?
An object in JSON is surround by { } which you have omitted. As well, properties are separated by a comma.
{
"data": {
"Stage": "7",
"Step": "1"
}
}
Related
I am trying to insert an event into my Google Calendar via the Delphi REST controls, but I am uncertain where to add the access token to my request. My Code looks like this:
var
evt : String;
begin
ResetRESTComponentsToDefaults;
RESTClient.BaseURL := 'https://www.googleapis.com/calendar/v3';
RESTClient.Authenticator := OAuth2_GoogleCalendar;
RESTRequest.Resource := 'calendars/primary/events';
evt:='{"summary":"test","description":"test","id":"06824945162f4204bfdc041ae1bbae85","start":{"date":"2018-04-10"},"end":{"date":"2018-04-10"},"guestsCanInviteOthers":false,"visibility":"private"}'
RESTRequest.AddParameter('access_token',OAuth2_GoogleTasks.AccessToken,pkHTTPHEADER);
RESTRequest.Method := TRESTRequestMethod.rmPOST;
RESTRequest.Body.Add(evt,ctAPPLICATION_JSON);
RESTRequest.Execute;
end;
The scope is https://www.googleapis.com/auth/calendar
If I send it in like this I this error:
{
"error":
{
"errors":
[
{
"domain":"global",
"reason":"required",
"message":"Login Required",
"locationType":"header",
"location":"Authorization"
}
]
,
"code":401,
"message":"Login Required"
}
}
Appending ?access_token={accessToken} to the end of the url i get
error 400, parseError.
Where should I add the access token to the request?
I cant help much with Delphi its been years since i have used it, but you have a two options with regard to adding your access token.
First is to just add it as a parameter on the base url
?access_token=TokenHere
The second option is to send it as an authorization header on your request its a bearer token.
Authorization : Bearer cn389ncoiwuencr
After a bit of googling i found this
FIdHTTP.Request.CustomHeaders.FoldLines := False;
FIdHTTP.Request.CustomHeaders.Add('Authorization:Bearer ' + txtToken.Text);
I am trying to insert an event into my google calendar using the delphi REST controls.
This is the code so far:
procedure TForm1.TestGoogleRestParams;
var
i: Integer;
jsonObjEventResource,jsonObjStart,jsonObjEnd: TJSONObject;
begin
try
jsonObjEventResource:=TJSONObject.Create();
jsonObjStart:=TJSONObject.Create();
jsonObjEnd:=TJSONObject.Create();
jsonObjEventResource.AddPair(TJSONPair.Create('summary','test'));
jsonObjEventResource.AddPair(TJSONPair.Create('description','Testing'));
jsonObjEventResource.AddPair(TJSONPair.Create('id',LowerCase('06824945162F4204BFDC041AE1BBAE85')));
jsonObjStart.AddPair(TJSONPair.Create('date',FormatDateTime('yyyy-mm-dd',Now)));
jsonObjEventResource.AddPair(TJSONPair.Create('start',jsonObjStart));
jsonObjEnd.AddPair(TJSONPair.Create('date',FormatDateTime('yyyy-mm-dd',Now)));
jsonObjEventResource.AddPair(TJSONPair.Create('end',jsonObjEnd));
jsonObjEventResource.AddPair(TJSONPair.Create('guestsCanInviteOthers',TJSONBool. Create(false)));
jsonObjEventResource.AddPair(TJSONPair.Create('visibility','private'));
mem_Test.Lines.Add(TJson.Format(jsonObjEventResource));
//mem_Test.Lines.Add(jsonObjEventResource.ToJSON);
RESTRequest.Method := TRESTRequestMethod.rmPOST;
RESTRequest.Body.ClearBody;
RESTRequest.AddBody(jsonObjEventResource);
RESTRequest.Execute;
finally
//jsonObjEventResource.Free;
//jsonObjStart.Free;
//jsonObjEnd.Free;
end;
end;
The Scope I am using is: https://www.googleapis.com/auth/calendar.
BaseURL : https://www.googleapis.com/calendar/v3
ResourceURI : calendars/primary/events
I do get an access token and a refresh token but I cannot Post the Request. This is the error i recieve:
{
"error":
{
"errors":
[
{
"domain":"global",
"reason":"required",
"message":"Login Required",
"locationType":"header",
"location":"Authorization"
}
]
,
"code":401,
"message":"Login Required"
}
}
With the following uri: https://www.googleapis.com/calendar/v3/calendars/primary/events
How can i fix this?
If I don't call this method and just call RESTRequest.Execute; I get a list of all my existing events.
":"Invalid Credentials"
Means that the client id and client secret that you are using are incorrect. You should download a new file from Google Developer console and try again.
Option 2:
Try authenticating the user it could be that the access token has expired and needs to be refreshed
I am having some trouble with PUT requests to the google sheets api.
I have this code
spreadsheet_inputer := WebClient(`$google_sheet_URI_cells/R3C6?access_token=$accesstoken`)
xml_test := XDoc{
XElem("entry")
{
addAttr("xmlns","http://www.w3.org/2005/Atom")
addAttr("xmlns:gs","http://schemas.google.com/spreadsheets/2006")
XElem("id") { XText("https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"), },
XElem("link") { addAttr("rel","edit");addAttr("type","application/atom+xml");addAttr("href","https://spreadsheets.google.com/feeds/cells/$spreadsheet_id/1/private/full/R3C6?access_token=$accesstoken"); },
XElem("gs:cell") { addAttr("row","3");addAttr("col","6");addAttr("inputValue","testing 123"); },
},
}
spreadsheet_inputer.reqHeaders["If-match"] = "*"
spreadsheet_inputer.reqHeaders["Content-Type"] = "application/atom+xml"
spreadsheet_inputer.reqMethod = "PUT"
spreadsheet_inputer.writeReq
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
echo(spreadsheet_inputer.resStr)
Right now it returns
sys::IOErr: No input stream for response 0
at the echo statement.
I have all the necessary data (at least i'm pretty sure) and it works here https://developers.google.com/oauthplayground/
Just to note, it does not accurately update the calendars.
EDIT: I had it return the response code and it was a 0, any pointers on what this means from the google sheets api? Or the fantom webclient?
WebClient.resCode is a non-nullable Int so it is 0 by default hence the problem would be either the request not being sent or the response not being read.
As you are obviously writing the request, the problem should the latter. Try calling WebClient.readRes() before resStr.
This readRes()
Read the response status line and response headers. This method may be called after the request has been written via writeReq and reqOut. Once this method completes the response status and headers are available. If there is a response body, it is available for reading via resIn. Throw IOErr if there is a network or protocol error. Return this.
Try this:
echo(spreadsheet_inputer.readRes.resStr)
I suspect the following line will also cause you problems:
spreadsheet_inputer.reqOut.writeXml(xml_test.writeToStr).close
becasue writeXml() escapes the string to be XML safe, whereas you'll want to just print the string. Try this:
spreadsheet_inputer.reqOut.writeChars(xml_test.writeToStr).close
I am interested in dynamically taking arguments from the user as input through a browser or a CLI to pass in those parameters to the REST API call and hence construct the URL dynamically using Go which is going to ultimately fetch me some JSON data.
I want to know some techniques in Go which could help me do that. One ideal way I thought was to use a map and populate it with arguments keys and corresponding values and iterate over it and append it to the URL string. But when it comes to dynamically taking the arguments and populating the map, I am not very sure how to do that in Go. Can someone help me out with some code snippet in Go?
Request example:
http://<IP>:port?api=fetchJsonData&arg1=val1&arg2=val2&arg3=val3.....&argn=valn
There's already url.URL that handles that kind of things for you.
For http handlers (incoming requests) it's a part of http.Request (access it with req.URL.Query()).
A very good example from the official docs:
u, err := url.Parse("http://bing.com/search?q=dotnet")
if err != nil {
log.Fatal(err)
}
u.Scheme = "https"
u.Host = "google.com"
q := u.Query()
q.Set("q", "golang")
u.RawQuery = q.Encode()
fmt.Println(u)
https://github.com/golang/go/issues/17340#issuecomment-251537687
https://play.golang.org/p/XUctl_odTSb
package main
import (
"fmt"
"net/url"
)
func someURL() string {
url := url.URL{
Scheme: "https",
Host: "example.com",
}
return url.String()
}
func main() {
fmt.Println(someURL())
}
returns:
https://example.com
url.Values{} provides an interface for building query params. You can construct inline and/or use .Add for dynamic properties:
queryParams := url.Values{
"checkin": {request.CheckIn},
"checkout": {request.CheckOut},
}
if request.ReservationId {
queryParams.Add("reservationId", request.ReservationId)
}
url := "https://api.example?" + queryParams.Encode() // checkin=...&checkout=...
My code sample was
package require rest
set yweather(forecast) {
url http://weather.yahooapis.com/forecastrss
req_args { p: }
opt_args { u: }
}
rest::create_interface yweather
Output
% set res [yweather::forecast -p 94089]
channel {title {content {Yahoo! Weather - Sunnyvale, CA}} .........
But i am trying to view Response header, like Status codes, set-cookie information. I don't know how to view, some one please help to resolve this issue.
Thanks
Typically with handling REST, I'd just use the standard http package directly (or wrapped into a little class). That would let you use http::meta to get at the gory response details, and also let you control much more precisely what message gets sent in the first place (usually rather important!)
However, that's me (as I'm pretty au fait with REST and the http package). Let's dig into the rest package more carefully and get it to do what we want.
By close reading of the documentation, I see that the interface descriptor dictionary allows the keys pre_transform and post_transform, and that the http token is available in the calling context. Let's try with the post_transform…
package require rest
set yweather(forecast) {
url http://weather.yahooapis.com/forecastrss
req_args { p: }
opt_args { u: }
post_transform extract_metadata
}
rest::create_interface yweather
proc extract_metadata {response} {
upvar 1 token token
lappend response [http::meta $token]
return $response
}
Now, if you do:
set res [yweather::forecast -p 94089]
You should get the extra information you want (and far more probably!) in the meta field at the end.