Sei sulla pagina 1di 18

Delphi XE5: REST Client Library

09/24/2013 Vlad 33 Comments Delphi in Web , Delphi Components

As I mentioned earlier , among other innovations in Delphi


XE5 adds support for authentication protocols OAuth 1.0, OAuth 2.0, and with this
opportunity, and a new library called REST Client Library. Since most of my work on and
have to deal with the writing of components and modules to work with various API - from
Google and Facebook to Live Connect and Dropbox API, then, of course, this new library
could not be left without my attention.

And check the usability of the new library, I decided on services, with whom I worked most
recently, namely one of the API Google - Drive API. Running a little ahead, I will say that
the components of the library can also be used in the development of mobile applications,
but first things first.

Components REST Client Library


So all the work of the library is based on the use of three main components:

1. Client (TRESTClient)
2. Request (TRESTRequest)
3. Answer (TRESTResponse)

Since most Web services require prior authorization of the user before the API to provide
their resources in use, the REST Client Library also has four components for authentication
and user authentication:

1. TSimpleAuthenticator
2. THTTBasicAuthenticator
3. TOAuth1Authenticator
4. TOAuth2Authenticator

Finally, as an additional component can be identified


component TRESTResponseDataSetAdapter, which in some cases can be used to convert
data in JSON-dataset TDataSet.

Immediately it should be noted that the basic data format for REST Client Library is JSON.

Consider the work of some components of the library with Google Drive API.

Log in Google Drive API. Testing connection.


To get started with Drive API, we need to create a new project in the Console Google and
get the values Client ID andClient Secret. To learn how to do it, I say, for example, in the
article " Testing requests to API Google means Delphi.Component for Delphi XE
OAuthClient - XE3 ". We assume that this time the work was carried out successfully and
you have the necessary information to get started with the service, and along with the
components of REST Client Library.

Now create a new project Delphi XE5 and threw it on the main form
components TRESTClient, TRESTRequest, TRESTResponse and TOAuth2Authenticator.

Now we define the necessary parameters, and simultaneously test the connection to Google
Drive API.

Keys API access to the Design-Time

Choosing to form component OAuth2Authenticator1 and Object Inspector'e click on the


link «Configure ...«:

In the window that opens, select the following values for the following fields:

 Authorization-Endpoint: https://accounts.google.com/o/oauth2/auth
 Token-Endpoint: https://accounts.google.com/o/oauth2/token
 Redirctioon-Endpoint: urn: ietf: wg: oauth: 2.0: oob
 Client-ID: Client ID value of your project
 Client-Secret: Client Secret value of your project
 Access-Scope: https://www.googleapis.com/auth/drive

As a result, the settings window component takes the following form:

Now you can test the connection. Click the button Authorize and if all the data are correct, it
will open Google confirmation of access to resources API:

and after the access to the Settings window will be filled with fields group «Codes &
Tokens«:
Now you can press «Apply» then all the set values will be transferred to the component
properties (including the values obtained from the Codes & Tokens).

Basically, now we can go to work with the resources API, because necessary access keys
we already have. However, when working with the library, we will most likely need to
obtain access keys in run-time, and therefore, in this part of the article should consider
getting access keys without using the assistant discussed above.

Keys Access Run-Time

For access keys in run-time, we need:

1. Cause the window in which the user confirms the right of access to resources
2. Get the value of code
3. Exchange code on Acess Token

In principle, these steps I saw a bunch of times in the blog. Now reproduce them using
features REST Client Library.

Plug-in uses the main module of our application


module REST.Authenticator.OAuth.WebForm.Win. This module contains a
form Tfrm_OAuthWebForm, which can be used to authenticate the
user. Tfrm_OAuthWebForm contains TWebBrowser and the Close button in the designer
and looks as follows:
In form, the following new developments:

property OnAfterRedirect: TOAuth2WebFormRedirectEvent read FOnAfterRedirect write FOnAfterRedirect;

property OnBeforeRedirect: TOAuth2WebFormRedirectEvent read FOnBeforeRedirect write FOnBeforeRedirect;

property OnTitleChanged: TOAuth2WebFormTitleChangedEvent read FOnBrowserTitleChanged write FOnBrowserTitleChanged;

type

TOAuth2WebFormRedirectEvent = procedure (const AURL: string; var DoCloseWebView: boolean) of object;

TOAuth2WebFormTitleChangedEvent = procedure (const ATitle: string; var DoCloseWebView: boolean) of object;

OnBeforeRedirect and OnAfterRedirect triggered before and after we redirect to another


URL in the browser.OnTitleChanged triggered when the browser changes the properties
of Title.

According to the documentation on the Google OAuth 2.0. , after the user gives permission
to access your data, Google will return us the value AuthCode, which we have to be
exchanged for an access key. Meaning AuthCode also issued in Title as a string
type «Success code = ... ..«.

Thus obtaining access to key API Google Drive in run-time can be as follows:

var wf: Tfrm_OAuthWebForm;

begin

// Create the window with the browser to redirect the user to the Google homepage

wf: = Tfrm_OAuthWebForm.Create (self);

try

// Define event handler change Title

wf.OnTitleChanged: = TitleChanged;

// Show the window opens in the browser URL to access a form of confirmation

wf.ShowModalWithURL (OAuth2Authenticator1.AuthorizationRequestURI);

finally

wf.Release;

end;

// Replace AuthCode on AccessToken

OAuth2Authenticator1.ChangeAuthCodeToAccesToken;

// Display the key values in the Memo


Memo1.Lines.Add (OAuth2Authenticator1.AccessToken);

Memo1.Lines.Add (OAuth2Authenticator1.RefreshToken);

Memo1.Lines.Add (DateTimeToStr (OAuth2Authenticator1.AccessTokenExpiry));

end;

The event handler OnTitleChanged the window will look like this:

procedure TForm21.TitleChanged (const ATitle: string;

var DoCloseWebView: boolean);

begin

if (StartsText ('Success code', ATitle)) then

begin

OAuth2Authenticator1.AuthCode: = Copy (ATitle, 14, Length (ATitle));

if (OAuth2Authenticator1.AuthCode & lt; & gt; '') then

DoCloseWebView: = TRUE;

end;

end;

Thus we get from Google needs the key values we can start working directly with the API
Google Drive.

Working with TRESTRequest and TRESTResponse.Receive data


from Google Drive.
Now you are ready to obtain the necessary data from Google Drive. First of all, check the
settings of components REST Client Library, which we placed on our application form. So
The,

TRESTClient the component properties must have the following values:

 Autenticator = OAuth2Authenticator1
 BaseURL = 'https://www.googleapis.com/drive/v2'

BaseURL value is usually specified in the documentation for a particular API, and is the part of the
URL for the request to the server, which never changes. In this case, any request to Google Drive
will begin with the substring https://www.googleapis.com/drive/v2
TRESTRequest the component properties must have the following values:

 Client = RESTClient1
 Response = RESTResponse1
the component TRESTResponse reserve all properties with default values.

Now let's try to get a list of all files in Google Drive. To that I added to the main form of the
application components TListBoxfor output file names and TMemo - to display information
about a specific file. Became the main application form as follows:

To get a list of files from Google Drive, we need to send a GET request to the
URLhttps://www.googleapis.com/drive/v2/files.

To do this, use the component TRESTRequest. Write OnClick handler button "Get a list of
files":

procedure TForm21.Button2Click (Sender: TObject);

begin

RESTRequest1.Method: = rmGET; // define the HTTP-method - GET

RESTRequest1.Resource: = '/ files'; // path to the resource API

RESTRequest1.Execute; // Execute the query

end;

It is worth noting that


properties TRestClient.BaseURL with TRESTRequest.Resource define the URL to which you want
to query.
Once the query is executed, the component will work TRESTRequest event:

property OnAfterExecute: TCustomRESTRequestNotifyEvent read FOnAfterExecute write FOnAfterExecute;

type

TCustomRESTRequestNotifyEvent = procedure (Sender: TCustomRESTRequest) of object;

In this case, the answer (TRESTResponse) will contain data received from the server. We
write the handler of this event:
procedure TForm21.RESTRequest1AfterExecute (Sender: TCustomRESTRequest);

const

// Type of server response

cResponseKind: array [0..3] of string = ('drive # fileList', 'drive # file', 'drive # about', 'drive # revision');

var JSONObject: TJSONObject;

Kind: string;

begin

if Assigned (Sender.Response.JSONValue) then

begin

JSONObject: = Sender.Response.JSONValue as TJSONObject;

// Find the type of server response

Sender.Response.GetSimpleValue ('kind', Kind);

case AnsiIndexStr (Kind, cResponseKind) of

0: ParseFileList (JSONObject);

1: ParseFile (JSONObject);

end;

end;

end;

The methods and ParseFileList ParseFile used to parse JSON and are as follows:

procedure TForm21.ParseFile (AJSONObject: TJSONObject);

begin

Memo1.Lines.Clear;

Memo1.Lines.Add ('Title:' + AJSONObject.Get ('title'). JsonValue.Value);

Memo1.Lines.Add ('Mime-Type:' + AJSONObject.Get ('mimeType'). JsonValue.Value);

Memo1.Lines.Add ('Created Date:' + AJSONObject.Get ('createdDate'). JsonValue.Value);

end;

procedure TForm21.ParseFileList (AJSONObject: TJSONObject);

var FileObject: TJSONObject;

Pair: TJSONPair;
NextToken: string;

ListItems: TJSONArray;

I: Integer;

begin

// Get the URL parameter for the next part of the file list

Pair: = AJSONObject.Get ('nextPageToken');

if Assigned (Pair) then

NextToken: = Pair.JsonValue.Value;

// Get list of files

ListItems: = AJSONObject.Get ('items'). JsonValue as TJSONArray;

// Parse the array elements

for I: = 0 to ListItems.Size-1 do

begin

FileObject: = ListItems.Get (i) as TJSONObject;

// Get the file name

ListBox1.Items.Add(FileObject.Get('title').JsonValue.Value+'//'+FileObject.Get('id').JsonValue.Value);

// ....

end;

// If not obtained all the files, then repeat the request, including in the URL parameter pageToken

if Length (NextToken) & gt; 0 then

begin

RESTRequest1.Params.Clear;

RESTRequest1.Params.AddItem ('pageToken', NextToken, pkGETorPOST);

RESTRequest1.Execute;

end;

end;

Pay attention to the last part of the method ParseFileList:

if Length (NextToken) & gt; 0 then

begin

RESTRequest1.Params.Clear;

RESTRequest1.Params.AddItem ('pageToken', NextToken, pkGETorPOST);


RESTRequest1.Execute;

end;

Here, our query component also receives an additional parameter pageToken. This option
when you run the query is inserted in the URL, or if we would perform POST-request - a
request body. That is, in this case, URL query was as follows:

https://www.googleapis.com/drive/v2/files?pageToken=Dfkdf5g67

Collection Params in TRESTRequest may contain the following types of parameters:

 pkCOOKIE - parameter is passed as Cookies


 pkGETorPOST - parameter is passed as a parameter in the URL for GET-, POST- and PUT-
query
 pkURLSEGMENT - parameter is inserted in the URL as part of the URL
 pkHTTPHEADER - parameter is passed as a request header
 pkREQUESTBODY - setting request transmitted in the body and, if it is determined that the type
of multiple parameters, the request will be multi-part.

Let's see how you can use different types of parameters in the query. For example, I did not
specifically handler OnAfterExecute parse the whole answer and pull out all response
properties of the object, of which there are in abundance, and limited only title and
identifier. All information about the file we will get a separate request and need to look in
the documentation for Google Drive , as follows:

https://www.googleapis.com/drive/v2/files/ {fileId}

where fileId - is the ID of the object that we can get along with the title of the previous
request. That is, we have had the opportunity to use the values from the collection of
elements as Params URL. Let's see how this can be done in practice.Will display the
information on file in Memo after a click on its name in the ListBox. Write a OnClick
handler ListBox:

procedure TForm21.ListBox1Click (Sender: TObject);

var Id: string;

begin

Id: = Copy (ListBox1.Items [ListBox1.ItemIndex],

pos ('//', ListBox1.Items [ListBox1.ItemIndex]) + 2,

Length (ListBox1.Items [ListBox1.ItemIndex]));

RESTRequest1.Resource: = '/ files / {fileId}';

RESTRequest1.Method: = rmGET;
RESTRequest1.Params.AddItem ('fileId', Id, TRESTRequestParameterKind.pkURLSEGMENT);

{Or so

RESTRequest1.Params.AddUrlSegment ('fileId', Id);

RESTRequest1.Execute;

end;

Notice how I define the properties of Resource - part of which is to insert our setting framed
by curly braces, and inside the parentheses is written the name of the parameter.

That's probably ready primerchik little interaction with Google Drive using the new
library Delphi XE5 REST Client Library.Now, in the performance of each request will be
triggered OnAfterExecute handler that we choose appropriate method for parsing JSON:
ParseFileList, ParseFile etc. depending on what is required to obtain from the server. It only
remains to add that in the folder with the source REST Client
Library ({Path_To_Delphi_XE5} \ source \ data \ rest \ restdebugger \) for you to collect
small proektiki on FireMonkey called RESTDebugger. With this simple program you can
debug their work with a variety of online services, and in general, take a look how to use
the new components when working with FireMonkey.

Above I have given you a fairly simple example of working with new components without
getting deep into each component and without considering the details of each property and
event. But I think that the example above would be sufficient to assess the possibility of a
new library.

In general I would say that working with REST Client Library seemed to me quite simple
and convenient. There are, of course, that add to the already existing components, but it is
already quite a library especially in the usability of VCL-projects.
Like this? By Then:

Important! Plus! Say Thanks "!

E-Mail Send Off


Send PDF to

Related publications:

1. Google API. ClientLogin interface for Delphi. Today, finally managed to download code.google.com, which can not but rejoice. ...
2. Google API in Delphi. Update module for OAuth. In one of the posts in the blog I talked about a new ...
3. Component Delphi 2010 TGooleLogin. Today, decided to bring a little order among the modules relating to work with ...
4. Google API in Delphi. OAuth for Delphi-applications. Long time I did not write anything about the Google API in Delphi, ...
5. Testing the queries to API Google means Delphi. OAuthClient component for Delphi XE -
XE3 The article presents a Delphi component and the program uses it to ...

Tags: Delphi , Delphi xe5 , REST , REST Client Library , Delphi components , component
overview |

33 Comments · Leave Comment

1. Alex

09/25/13

The figures I have one do not appear?

To Reply

o Vlad

09/25/13

No, just the server was rolled back, and the last two posts were lost, had to recover from the cache of Google. While only perezalil image files - click on
the picture and you will see it in full size
To Reply

2. Roman Jankowski

09/26/13

The word «Autenticator» occurs many times. Obvious misprint.

To Reply

o Vlad

09/26/13

yes, a typo. Thank you, Roman :)


To Reply

3. Dmitry

01/16/14

Vlad, thank you so much for the article!


To Reply

o Vlad

01/16/14

always glad to help :)


To Reply

4. Dan

01/16/14

Under iOS 7.0.4 (I have this, I will not say for others) does not work

To Reply

5. Dim

01/18/14

Thanks, Vlad for an educational program.


Started juzat components - it works like normal.
But there he problem with the encoding.
When transmitting in API (my own) for example (Builder):
......
RESTRequest1-> Params-> ParameterByName («log») -> Value = «Hello !!! Hello world !!! ";
......
API that accepts a string: «Hello !!! A7C4D0C0C2D1D2C2D3C9 CCC8D0 !!! »
although the reverse reception from the API Cyrillic goes well ...
I do not understand what's Trouble ???

To Reply

o Vlad

01/18/14

hm..mozhet before sending the string encoding should be changed to the one that is installed on the server? For example, in UTF8? Try it, if you will -
plz accomplish your goal. Although judging from the API Text adopted clearly something "left" :)
To Reply

6. Dim

01/18/14
Tried this:
RESTRequest1-> Params-> ParameterByName («log») -> Value = AnsiToUtf8 («Hello !!! Hello World !!!");
nepomoglo.

To Reply

o Vlad

01/19/14

Line A7C4D0C0C2D1D2C2D3C9 CCC8D0 looks as if taken text performed URLEncoded (), and then all povyrezali%. I think the question here is more
to API, than to the components. Using the API to other components handled? Or simply distribute a small script in php and check tighter line.
To Reply

7. Dim

01/20/14

Similar to the encoding kepshenov in .dfm-ah


I will dig ...

To Reply

8. Pingback: Twitter OAuth and Russian characters. Decided. | Delphi on the Internet

9. Dim

05/01/14

Use functions Encode64 () and Decode64 () on the side of builder and coding
-dekodirovaniem in the API host.

To Reply

10. Pingback: REST Client Library: VKontakte API usage. | Delphi on the Internet

11. Bega

05/25/14

swears on RESTRequest1.Method: = rmGET - I do not understand what's wrong

To Reply

o Vlad

05/25/14

Maybe you have not connected to the module REST.Types uses? Or try to write so: RESTRequest1.Method := TRESTRequestMethod.rmGET
To Reply

 Bega

05/25/14

thank you! Really uses has not been spelled out REST.Types. But now swears «Could not load SSL library.»
To Reply

 Vlad

05/26/14

What's the cloud? If it `s not a secret. Probably next to EXE-file must put the library to work with SSL ?The link is listed these libraries (libeay32.dll
and ssleay32.dll), try - can help to solve your problem
To Reply

 Bega

05/26/14

Helped. Thank a lot. But again came mistake :( Project Project1.exe raised exception class EidHTTPProtocolException with message 'http / 1.1 401
unauthorized delphi'

 Vlad

05/26/14

This is the exception to the library, not a bug in the code, or somewhere else. Probably something you're not tuned or not the parameter is passed or
not pass them as required by the API. Here I already hardly help.

12. Rafael Aparecido Rossi

05/29/14

u can help me to insert a event in google calendar?


After loging, i'm trying use this:
procedure TfrmPrincipal.Button4Click (Sender: TObject);
var Parametros: TJsonObject;
begin
try
Parametros: = TJsonObject.Create;
Parametros.AddPair ('summary', TJSONString.Create ('Sumário'));
Parametros.AddPair ('location', TJSONString.Create ('Local'));
Parametros.AddPair ('start', TJSONObject.Create (TJSONPair.Create ('dateTime', '2014-05-28T17: 00: 00.000-03: 00')));
Parametros.AddPair ('end', TJSONObject.Create (TJSONPair.Create ('dateTime', '2014-05-28T17: 30: 00.000-03: 00')));
Parametros.AddPair ('attendees', TJsonArray.Create (TJSONObject.Create (TJSONPair.Create ('email', 'russo.bradock@gmail.com'))));
RESTRequest1.Method: = rmPOST;
RESTRequest1.Resource: = '/calendars/russo.bradock@gmail.com/events';
RESTRequest1.AddBody (Parametros.ToString, ctAPPLICATION_JSON);
Memo1.Lines.Clear;
RESTRequest1.Execute;
finally
Parametros.Free;
end;
end;
Well, thanks for all.
(Sorry for my english, i'm from Brazil)

To Reply

13. Pingback: Google ClientLogin. When it makes sense to use the HOSTED? | Delphi on the Internet

14. Yuri

11/13/14

try to get a list of files, but returns for some reason only
{
«Kind»: «drive # fileList»,
«Etag»: «....»,
«SelfLink»: «https://www.googleapis.com/drive/v2/files»,
«Items»: []
}
the ones. items empty, although there are files just try to do the same thing on the pagehttps://developers.google.com/drive/v2/reference/files/list -
everything works correctly
do not tell me what could be the problem? Delphi - XE6

To Reply

o Vlad

11/13/14

To what URL request is sent (the exact address unabridged). Most likely something with the ID of the folder where the files or ask in the parameters
something namudrili
To Reply

 Yuri

11/13/14

RestClient - BaseURL -
https://www.googleapis.com/drive/v2
RestRequest - Resource -
files
To Reply

 Yuri

11/13/14

in PArams - nothing
I try to see the list of files in the root of the Google Drive
To Reply
 Vlad

11/13/14

I have now is XE7 in Tools -> REST Debugger everything works as it should. If you can - lay somewhere source (no Client ID and Client
Secret). The fact that this is not a bug or API Delphi - precisely becausewe have implemented this API and REST Client Library and without. Not a
single bug report was not
To Reply

 Yuri

11/14/14

https://drive.google.com/open?id=0B6kR8ImhM6jFOFhLdFNwUk1fY0k&authuser=0
and immediately, if not difficult, may suggest how to create folders, I watched the documentation Google, tried it, but meets all the time Bad request
I understand I have to do a POST request, and Params to specify the folder title, parent id, and the desired mime-type ...

 Vlad

11/14/14

// I understand I have to do a POST request, and Params to specify the folder title, parent id, and the desired mime-type ...
not exactly. You are sent to the server JSON-object must specify title, rather than in the URL parameters
all look today. Just one more question on this topic have

 Vlad

11/14/14

Open access to the file to me :)

 Yuri

11/14/14

in RESTDEbugger I also checked - it works ...

 Yuri

11/14/14

Sori https://drive.google.com/file/d/0B6kR8ImhM6jFOFhLdFNwUk1fY0k/view?usp=sharing

Leave a Reply

Potrebbero piacerti anche