在 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 程