使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client

转自:http://www.cnblogs.com/dennieschang/p/6966403.html

在 Delphi XE 推出以前的年代,Delphi的展方向是笔直朝向库连结Windows 用程式个目不断前的,从Delphi 1开始,到Delphi 7,Delphi奠定了VB Killer的外号,主要依靠的就是与接功能超越其他开工具,而且超越的距离不只一个世代。 

在 .NET开始展,Delphi 8, Delphi .NET 不断延候,与库连接功能的方便性,仍然让许多ERP厂商、硬体厂商持续爱用 Delphi.

直到 Web 开与 App 开超越了 Windows 用程式的需求,VC, VB, Delphi 也开始随着波潮流,渐渐不再像 1990年代那么广受戴了。

在1990到 2010年之,Delphi的网路连线功能,主要是借由第三方元件来提供的,其中知名度最高,全球使用人数也最多的,应该就是 Indy 套元件了。

套元件在 2000 年前,叫做 WinShose,从第八版之后才改名Indy,全球投入套元件开的开,前后超40人,从最基的 TCP/IP 功能到各种定的Client与Server 端元件,笔者从中得益非常多,也开了当中的DNS Server元件,讯协定的深入了解,Indy团队是我不可或缺的师长

随着Delphi 工具走入了多平台开域,Indy的局限性也在两三年凸了出来,主要是在各个作上面于SSL与加密功能的支援无法合到作内建的功能所致。

由于个局限性,Delphi XE6开始,REST Client系列元件渐渐开始成 Delphi 团队的重点开发项目之一,所以我从 Delphi XE6, Delphi XE7 之后的版本,可以发现到,使用 TRESTClient, TRESTRequest, TRESTResponse 系列合的用程式越来越多了,原厂也不断鼓励大家使用套元件来提供 REST API 的连线功能。

REST API 的基是 HTTP 定,大多以 HTTP 的 POST 方法把 JSON 编码形式的参数传递到 Server,而 Server 再以 JSON 形式的参数回

作法也会稍有化,例如以 POST 方法把 Web-Form 编码形式的参数传递给 Server,Server 再以 JSON 形式把料回

形式不一而足,但相同的是 HTTP 定,最常用的也是以 POST 方法把参数传给 Server 端。

今天要跟大家分享的主是如何『使用 TRESTClient 与 TRESTRequest 作 HTTP Client』。

 

前面已提到,在没有 TRESTClient 整元件以前,我通常用的是 Indy 系列的元件来提供网路传输的功能,而在有了 TRESTClient 整元件,我在行平台上面就可以不需要另外配置函式,也能直接使用 https 与 server 连线了,在勒索病毒泛的今天,使用 https 会使用者比安心。

POST业说

在 HTTP 的 POST 作当中,参数跟 GET 作,Client端需要以 name=value&name2=value2 种形式行字串接,再送到 Server 端去。Get 跟 POST的差异,在于 Get 方法是把所有参数当做 URL 的一部分,送 HTTP GET 指令的候,参数同 URL  一起送。

而 POST 作业则送完 POST 指令后,把所有的参数与料随之送。依照 HTTP 型定的范,GET 作的 URL 是无法加密的,而且度也有限制。因此,当需要传递料比多,或者有机敏性,透 HTTPS 送,就是最直接,也最方便,更是目前最通用的料保方法。 

 POST 传递的参数,除了字串以外,常常包含了档案传递。我很常看到在网上面以按提供使用者选择要上的档案,也常看提供以拖拉的方式把档案上端系,尤其网页邮件系最常种作法。 

去以 TIdHTTP 元件的 POST 方法送参数,呼叫方式如下:

 1 var
 2     httpClient : TIdHTTP;
 3     url, params, httpResultStr : string;
 4 begin
 5     url := ‘http://mytestURL.com/test.php‘;
 6     params := ‘name=我的名字&test=测试‘;
 7
 8     httpClient := TIdHTTP.Create(self);
 9     try
10          httpResultStr := httpClient.Post(url, params);
11          showMessage(httpResultStr);
12     finally
13         httpClient.Free;
14     end;
15 end;

这样就可以把 params 字串的众参数到 server 去了。理上是这样,但事情并没有简单,在 HTTP 定当中要参数 Server,如果些字串包含了特殊字元,要先经过编码,而编码,是我一生都需要与之抗的繁复程序。

在 HTTP GET 方法当中,所有的参数除了要以 name=value 每一个参数做描述,以及需要用 & 来接各参数,所有的 value 都需要以 url encode 来脱 URL 保留字元的纠缠。name 是否需要编码呢?笔者建,name 就乖乖的用英文吧,可以省下很多问题,以及些可避免的问题所需要的时间

那么同的功能,以 TRESTClient 跟 TRESTRequest 要怎么达成呢? 也很容易,作法如下:

1. 在 form 里面放上 TRESTClient 跟 TRESTRequest 元件各一。

2. 把要传递的参数加到 TRESTRequest 体的 params 属性里面去,个属性的型是 TArray,所以可以存放多参数。

3. 定 TRESTClient 要送参数的URL,注意,URL 是定在TRESTClient 哦!

4. 定 TRESTRequest 要使用的传输方法,要POST(因正在介的是POST方法,按照您的需求整)

5. 呼叫 TRESTRequest 体的 execute 方法,就可以把料送去 server 了。

 

写成 Delphi 的程式,会像以下这样:

self.RESTClient1.BaseURL :=
          ‘http://我的网址/acceptNewCard.php‘;
self.RESTRequest1.Params.Clear;
self.RESTRequest1.Method := rmPOST;

self.RESTRequest1.AddParameter(‘test‘, self.EditCardNo.Text);
self.RESTRequest1.AddParameter(‘name‘, self.EditName.Text);

是不是很容易呢?的确很容易,里问题等下再深入探,先来看 server 端要怎么接收些个参数,我用 PHP 当范例,需要用 C#,JSP的者朋友们请自行转译喔??

 

PHP Server 端接收 POST 参数的方法

从 1994 年开始,笔者就陆续撰文明 HTTP POST 方法如何接参数,包含了CGI 用C,perl等作,也包含 ISAPI 以 Delphi 作,近几年比流行的是 PHP,JSP,C#,但 PHP 程式码读起来比较简洁易懂,所以我就选择 PHP 来做范例了。 

在 PHP 里面,透GET 跟 POST 方法传递的参数,会被分存放在 $_GET 跟 $_POST 两个数里面,如果要偷懒,不想区分 GET 或 POST 方法,也可以从 $_REQUEST 取,当中有些安全性考量,最好勤一点,把它区分开来。

 

刚刚的例子来看,我们传了一个名 name,以及一个名 test 的字串,用的是 POST 方法,所以我得用以下两个数来存取两个字串:

•  $_POST[‘name‘]  数可以取得 Client 端送出来的 name 

•  $_POST[‘test‘]  数可以取得 Client 端送出来的 test

所以在 server 端,我可以这样写,来抓到两个料:

$name = $_POST["name"];

$test = $_POST["test"];

 

这样写会不会出问题呢? 答案是不会!如果使用者不入中文的

 

中文料的编码处

Delphi的开员绝大多数都是英美系的人,我推因此系的文字示与传输没有法完整的测试,但于我以中文的人来,从电脑诞生的那个年代,中文的示在每个操作、每种通讯协定的设计都比英文来的困

以上面的例子来看,如果我直接拿个例子来测试,笔者写的范例程式,传输资,Server 所抓到的文字并不是正确的中文字,如下所示:              

  

可以看得出来,到 server 的候,server 是不到资讯的。是怎么回事呢?笔者属于不认输的好奇宝宝,使出了身解数,于解决了问题

 

 Web 程式的一定可以立刻推出来,这绝对是文字编码问题了,然而,是什么地方出问题?可能出问题的点我列出来跟大家分享:

•  HTTP Client 的 charset 

•  HTTP Request 里面的文字编码问题

检查的方向也是从两个关点出,第一点的检测很容易,从Object Inspector检查一下 RESTRequest1的定:

AcceptCharset 确定是 UTF-8,没,所以定不是问题

接着,就要从 Client 端出去的料下手了。有者或『你怎么不怀疑Server端程式写了?』问题很好,之所以排除了问题,是因同一个 Server 端的 PHP 程式,我用了 Postman 做对测试,回果是正确的,因此判定是 Client 端程式的问题

接着笔者从 TRESTRequest.AddParameter 的各种多形式来尝试,AddParameter 个方法有以下几种多的形式:

procedure AddParameter(const AName, AValue: string); overload;
procedure AddParameter(const AName: string; AJsonObject: TJSONObject; AFreeJson: boolean = true); overload;
procedure AddParameter(const AName, AValue: string; const AKind: TRESTRequestParameterKind); overload;

三种形式我都测试过,从 AddParameter 的行中 trace 去看各个可能性,由于 TRESTRequest 的参数中,Get 跟 Post 的加入方法是混用的,在程式里面编码又会有点不同。

在 REST.Client.pas 里面,我曾经怀过编码错误,所以也在各个数都察,最后,找到了原因与解法,至于程,就不多了,花了我两天咧。

原因:编码错误

用HTTP传递中文的候,必用UTF-8编码,但一定要得,中文字在作中,都是UCS32编码象在Windows里面如此,在Android里面如此,在iOS跟Mac我不确定,但理方法是一的。 

直接以 AddParameter(‘name‘, ‘中文测试‘); 把参数加 TRESTRequest 候,REST.Client.pas 的程式是把 ‘中文测试‘ 个字串直接抓 Ord 的料来做编码的,然而,个作法,是的!!!!!!!! 

在 HTTP 传递 UTF-8 料的候,我传递的是 UTF-8 文字的二料,但直接把 ‘中文测试‘ 个字串直接拿来成二位? 当时编码并不是 UTF-8 啊,当然怎么编码送到 server 都是的!!!!

解法:AddParameter之前先做 UTF-8 转换

个解法,笔者第一天就已想到,只是很想像以前改 Indy 程式一,直接改好 REST.Client.pas 之后,回馈给原厂使用,所以花了不少时间找方法,最后发现这个方法不用到 REST.Client.pas,又能正确理,就直接么跟大家分享了,写成 Delphi 程式如下:

var
     nameStr : String;
begin
   ...
   nameStr := TIdURI.ParamsEncode(nameStr, IndyTextEncoding_UTF8);
   self.RESTRequest1.AddParameter(‘name‘, nameStr,
             TRESTRequestParameterKind.pkGETorPOST,
             [TRESTRequestParameterOption.poDoNotEncode]);
   ...
end;

在把字串透 AddParameter 加入参数列之前,我先把字串做个 UTF-8 转换,在里用的是 TIdURI 的类别方法 ParamsEncode,个方法只有两个参数,第一个参数是字串内容,第二个参数是要文字编码的种,在里我选择了 UTF8,写法就是上面范例程式的第一行。

接着,在呼叫 AddParameter 的候,我使用了多形式当中的第三种,要求 AddParameter 料的候不要再我的编码,因我已经处理好了。

这么修改过之后,在各个作业系统当中,执行结果都是正确的,上面两个图以 Windows 作业系统为例,现在我们拿 Android 截图来做为例子:

 

者可以看到右的截里面,server 回料已是正确的中文字了。

最后,我把 PHP 程式也附上来大家参考:

 1 <?php
 2 date_default_timezone_set("Asia/Taipei");
 3 header(‘Content-Type: charset=utf-8‘);
 4
 5 include("public/DBClassPDO.php");
 6 $objDBPDO = new DBClassPDO();
 7
 8 $cardNum = $_POST["cardNum"];
 9 $floorIdx = $_POST["floorIdx"];
10 $name = $_POST["name"];
11 $houseNum = $_POST["houseNum"];
12
13 $params = array();
14 $params[‘name‘] = $name;
15 $params[‘cardno‘] = $cardNum;
16 $params[‘houseNum‘] = $houseNum;
17 $params[‘floorIdx‘] = $floorIdx;
18 $params[‘picFilename‘] = $fileSaveName;
19 $params[‘created‘] = 0;
20
21 $result["resultCode"] = "0";
22 $result["result"] = "成功";
23 $result["sqlcmd"] = $name;
24
25 $jsonStr = json_encode($result);
26 echo $jsonStr;
27 ?>

是最基本的传递字串,下次再大家示范怎么档案,透 TRESTRequest来做也是很简单的,TRESTRequest 跟 TRESTClient 的确是取代 TIdHTTP 的好工具。

时间: 2024-10-24 00:13:10

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)的相关文章

delphi 各新版本特性收集

delphi 各新版本特性收集 Delphi XE6新增了一些特性并增强了原有的功能,主要有以下几个方面: IDE(整合开发环境) Internet XML(扩展标记语言) Compiler(编译器) COM/Active X Database support(数据库支持) CORBA Actions(动作) Custom Variants(可定义的可变类型) VCL 单元和特性 RTL单元和特性 Cross-platform development(跨平台开发) Translation too

我的第一个REST客户端程序!

Delphi:XE8 看了好几天的资料了,也没有弄出来一个REST程序,尝试了XE8中带的例子,也都没有搞懂.我在网上不断搜索,看是否能够找到适合自己的文章,希望能够做出来一个REST的小例子,万幸,终于弄出来一个了! 这个小程序是把IP地址发送到淘宝的REST API,得到淘宝IP库返回的解析结果,先看看运行效果吧! 这是一个REST客户端程序,既然自己暂时编不出来REST服务器,那么最简单就是找一个可以尝试的REST服务器,所以我用这种方法先编一个RESET客户端程序,对REST程序了解一下

adb server version (31) doesn’t match this client (36); killing… 的解决方法

今天折腾了一下Android studio,好不容易搞完了,结果在运行adb命令的时候出错了 不要着急,我们先看下这个错误是怎么出现的. 1.搞完Android studio之后也升级使用了新的sdk,并配置了环境变量 2.启动了第三方模拟器 3.之后用adb devices命令就出现了上图的错误 从报错的原因来看应该是版本不一致导致的,大概的意思是说你现在的adb版本是31,但是你client端的却是36(这里的client端我猜就是第三方的模拟器)不匹配啊. 尝试解决下,既然版本不一致,那就

swoole webSocket server or client example

server: $ws = new swoole_websocket_server('0.0.0.0', 9502); $ws->on('open', function ($ws, $request) {    var_dump($request->fd, $request->get, $request->server);    $ws->push($request->fd, "hello world\n");}); $ws->on('mess

elasticsearch java 客户端之Client简介

elasticsearch通过构造一个client体现对外提供了一套丰富的java调用接口.总体来说client分为两类cluster信息方面的client及数据(index)方面的client.这两个大类由可以分为普通操作和admin操作两类.以下是client的继承关系(1.5版本,其它版本可能不一样): 通过这个继承关系图可以很清楚的了解client的实现,及功能.总共有三类即client, indicesAdminClient和ClusterAdminClient.它都有自己的实现类,但

QDjango,tufao,C++ websocket client/server

QDjango, a Qt-based C++ web frameworkhttps://github.com/jlaine/qdjango/ An asynchronous web framework for C++ built on top of Qt http://vinipsmaker.github.io/tufao/https://github.com/vinipsmaker/tufao C++ websocket client/server library http://www.za

打开vsphere client提示Unable connect to MKS

问题描述:客户有3台服务器,突然发现用户的vsphere client打开虚拟机控制台的时候,提示Unable connect to MKS:Failed to connect to server IP地址:902 解决方法:通过测试发现,有一台是没问题的,另外两台无法均报错,通过对比发现,出现问题的两台服务器网关地址填写错误导致的,把网关地址修改为正确的,发现问题得到解决.

简单的Client / Server 使用 linux 伯克利 socket实现 编辑

server /* *run command: * g++ server.cpp -o server && ./server */ #ifndef SERVER #define SERVER #include<arpa/inet.h> #include<assert.h> #include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<errno.h>

Install Softether vpn client on CentOS 6.5, using Radius authentication

to disable ipv6method 1:vi /etc/grub.confadd ipv6.disable=1 to kernel line, and reboot method 2:echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.confsysctl -p 1. disable selinux and iptables service iptables stop chkconfig iptables