第一章 发送HTTP请求
本主题介绍如何发送HTTP
请求(如POST
或GET
)和处理响应。
HTTP请求简介
可以创建%Net.HttpRequest
的实例来发送各种HTTP
请求并接收响应。此对象相当于Web浏览器,可以使用它发出多个请求。它会自动发送正确的cookie
,并根据需要设置Referer
标头。
要创建HTTP请求,请使用以下常规流程:
- 创建
%Net.HttpRequest
的实例。 - 设置此实例的属性以指示要与之通信的Web服务器。基本属性如下:
- 服务器指定Web服务器的IP地址或计算机名称。默认值为
localhost
。
注意:不要将http://
或https://
作为服务器值的一部分。这将导致错误#6059:无法打开到服务器http:/的TCP/IP套接字
。
- 可以选择设置HTTP请求的其他属性和调用方法,如指定其他HTTP请求属性中所述。
- 然后,通过调用
%Net.HttpRequest
实例的get()
方法或其他方法来发送HTTP请求,如“发送HTTP请求”中所述。
可以从实例发出多个请求,它将自动处理cookie和Referer标头。
注意:如果创建此HTTP请求是为了与生产出站适配器(EnsLib.HTTP.Outbound Adapter
)一起使用,那么请改用该适配器的方法来发送请求。
- 如果需要,使用
%Net.HttpRequest
的同一实例发送其他HTTP请求。默认情况下,InterSystems IRIS使TCP/IP套接字保持打开状态,以便可以重复使用套接字,而无需关闭和重新打开它。
以下是一个简单的示例:
/// w ##class(PHA.TEST.HTTP).Get()
ClassMethod Get()
{
set request=##class(%Net.HttpRequest).%New()
set request.Server="tools.ietf.org"
set request.Https=1
set request.SSLConfiguration="yx"
set status=request.Get("/html/rfc7158")
d $System.Status.DisplayError(status)
s response = request.HttpResponse
s stream = response.Data
q stream.Read()
}
提供身份验证
如果目标服务器需要登录凭据,则HTTP请求可以包括提供凭据的HTTP Authorization
标头。
如果使用的是代理服务器,还可以指定代理服务器的登录凭据;为此,请设置ProxyAuthorization
属性
使用HTTP 1.0时对请求进行身份验证
对于HTTP 1.0,要验证HTTP请求,请设置%Net.HttpRequest
实例的用户名和密码属性。然后,该实例使用基本访问身份验证基于该用户名和密码创建HTTP Authorization
标头(RFC 2617)。此%Net.HttpRequest
发送的任何后续请求都将包括此头。
重要提示:请确保还使用SSL。在基本身份验证中,凭据以base-64编码形式发送,因此易于读取。
在使用HTTP 1.1时对请求进行身份验证
对于HTTP 1.1,要验证HTTP请求,在大多数情况下,只需设置%Net.HttpRequest
实例的用户名和密码属性。当%Net.HttpRequest
的实例收到401 HTTP
状态代码和WWW-Authenticate
标头时,它会尝试使用包含支持的身份验证方案的Authorization
标头进行响应。使用为IRIS支持和配置的第一个方案。默认情况下,它按以下顺序考虑这些身份验证方案:
- 协商(SPNEGO和Kerberos,根据RFC 4559和RFC 4178)
- NTLM(NT LAN Manager身份验证协议)
- 基本认证(RFC 2617中描述的基本接入认证)
重要:如果有可能使用基本身份验证,请确保也使用SSL(参见“使用SSL进行连接”)。
在基本身份验证中,凭据以base-64编码的形式发送,因此很容易读取。
在Windows上,如果没有指定Username
属性,IRIS可以使用当前登录上下文。
具体来说,如果服务器使用401状态码和用于SPNEGO
、Kerberos
或NTLM
的WWW-Authenticate
头响应,那么IRIS将使用当前操作系统用户名和密码创建Authorization
头。
具体情况与HTTP 1.0不同,如下所示:
- 如果认证成功,IRIS更新
%Net
的CurrentAuthenticationScheme
属性。
HttpRequest
实例来指示它在最近的身份验证中使用的身份验证方案。 - 如果尝试获取方案的身份验证句柄或令牌失败,IRIS会将基础错误保存到
%Net.HttpRequest
实例的AuthenticationErrors
属性中。此属性的值为$List
,其中每一项都具有格式scheme ERROR: message
仅HTTP 1.1支持协商和NTLM
,因为这些方案需要多次往返,而HTTP 1.0要求在每个请求/响应对之后关闭连接。
Variations
如果知道服务器允许的一个或多个身份验证方案,则可以通过包括Authorization
标头来绕过服务器的初始往返行程,该标头包含所选方案的服务器的初始令牌。为此,请设置%Net.HttpRequest
实例的InitiateAuthentication
属性。对于此属性的值,请指定服务器允许的单个授权方案的名称。使用下列值之一(区分大小写):
- Negotiate
- NTLM
- Basic
如果要自定义要使用的身份验证方案(或更改其考虑顺序),请设置%Net.HttpRequest
实例的AuthenticationSchemes
。对于此属性的值,请指定以逗号分隔的身份验证方案名称列表(使用上一个列表中给出的准确值)。
直接指定授权标头
对于HTTP 1.0或HTTP 1.1(如果适用于场景),可以直接指定HTTP Authorization
标头。具体地说,可以将Authorization
属性设置为等于正在请求的资源的用户代理所需的身份验证信息。
如果指定Authorization
属性,则忽略用户名和密码属性。
启用HTTP身份验证的日志记录
要启用HTTP身份验证的日志记录,请在终端中输入以下内容:
set $namespace="%SYS"
kill ^ISCLOG
set ^%ISCLOG=2
set ^%ISCLOG("Category","HttpRequest")=5
日志条目将写入^ISCLOG global
中.。要将日志写入文件(以提高可读性),请输入以下内容(仍在%SYS
命名空间内):
do ##class(%OAuth2.Utils).DisplayLog("filename")
其中,filename
是要创建的文件的名称。该目录必须已存在。如果该文件已经存在,它将被覆盖。
要停止日志记录,请输入以下内容(仍在%SYS
命名空间内):
set ^%ISCLOG=0
set ^%ISCLOG("Category","HttpRequest")=0
指定其他HTTP请求属性
在发送HTTP请求之前(请参阅发送HTTP请求),可以指定其属性,如以下各节所述:
可以为%Net.HttpRequest
的所有属性指定默认值,如最后列出的部分中所指定。
Location属性
Location
属性指定从Web服务器请求的资源。如果设置此属性,则在调用Get()
, Head()
, Post()
, 或 Put()
方法时,可以省略location参数。
例如,假设正在向url http://machine_name/test/index.html
发送一个HTTP请求
在这种情况下,将使用下列值:
%Net.HttpRequest
的示例属性
Properties | Value |
---|---|
Server | machine_name |
Location | test/index.html |
指定Internet媒体类型(Media Type)和字符编码(Character Encoding)
可以使用以下属性指定%Net.HttpRequest
实例及其响应中的Internet媒体类型(也称为MIME类型)和字符编码:
- Content-Type指定
Content-Type
标头,该标头指定请求正文的Internet媒体类型。默认类型为None。
可能的值包括application/json
、application/pdf
、application/postscript
、image/jpeg
、image/png
、multipart/form-data
、text/html
、text/plan
、text/xml
等等
- ContentCharset属性控制请求的任何内容(例如,
text/html
或text/xml
)类型时所需的字符集。如果不指定此属性,InterSystems IRIS将使用InterSystems IRIS服务器的默认编码。
注意:如果设置此属性,则必须首先设置ContentType
属性。
-
NoDefaultContentCharset
属性控制在未设置ContentCharset
属性的情况下是否包括文本类型内容的显式字符集。默认情况下,此属性为False。
如果此属性为true,则如果有文本类型的内容,并且没有设置ContentCharset
属性,则内容类型中不包括任何字符集;这意味着字符集iso-8859-1用于消息输出。
- WriteRawMode属性影响实体正文(如果包含)。它控制请求正文的写入方式。默认情况下,此属性为False,并且InterSystems IRIS以请求标头中指定的编码写入正文。如果此属性为true,则InterSystems IRIS以原始模式写入正文(不执行字符集转换)。
-
ReadRawMode
属性控制如何读取响应正文。默认情况下,此属性为False,并且InterSystems IRIS假定正文在响应标头中指定的字符集中。如果此属性为true,InterSystems IRIS将以原始模式读取正文(不执行字符集转换)。
使用代理服务器
可以通过代理服务器发送HTTP请求。要设置此设置,请指定HTTP请求的以下属性:
-
ProxyServer
指定要使用的代理服务器的主机名。如果此属性不为空,则将HTTP请求定向到此计算机。 -
ProxyPort
指定代理服务器上要连接到的端口。 -
ProxyAuthorization
指定Proxy-Authorization
标头,如果用户代理必须使用代理验证其自身,则必须设置该标头。对于该值,请使用正在请求的资源的用户代理所需的身份验证信息。 -
ProxyHTTPS
控制HTTP请求是针对HTTPS页面还是针对普通HTTP页面。如果未指定代理服务器,则忽略此属性。此属性将目标系统上的默认端口更改为代理端口443。 -
ProxyTunes
指定是否通过代理建立到目标HTTP服务器的隧道。如果为true,则请求使用HTTP CONNECT命令建立隧道。代理服务器的地址取自ProxyServer
和ProxyPort
属性。如果ProxyHttps
为true,则隧道建立后,系统间IRIS将协商SSL连接。在这种情况下,由于隧道与目标系统建立直接连接,因此将忽略https属性。
使用SSL进行连接
%Net.HttpRequest
类支持SSL连接。要通过SSL发送请求,请执行以下操作:
将
SSLConfiguration
属性设置为要使用的已激活SSL/TLS配置的名称。还要执行以下操作之一,具体取决于是否使用代理服务器:
- 如果未使用代理服务器,请将
https
属性设置为true。 - 如果使用的是代理服务器,请将
ProxyHTTPS
属性设置为true。
在这种情况下,要使用到代理服务器本身的SSL
连接,请将https属性设置为true。
请注意,当使用到给定服务器的SSL
连接时,该服务器上的默认端口假定为443(HTTPS端口)。例如,如果没有使用代理服务器,并且https为true,则会将Default Port属性更改为443。
服务器身份检查
默认情况下,当%Net.HttpRequest
实例连接到SSL/TLS安全的Web服务器时,它会检查证书服务器名称是否与用于连接到服务器的DNS
名称匹配。如果这些名称不匹配,则不允许连接。此默认行为可防止“中间人”攻击,在RFC 2818的3.1节中进行了描述;另请参阅RFC 2595的2.4节。
若要禁用此检查,请将SSLCheckServerIdentity
属性设置为0。
HTTPVersion
、Timeout
、WriteTimeout
和FollowRedirect
属性
%Net.HttpRequest
还提供以下属性:
HTTPVersion
指定请求页面时使用的HTTP版本。默认值是"HTTP/1.1"
。你也可以使用“HTTP/1.0”
。
Timeout
指定等待web服务器响应的时间,以秒为单位。
缺省值是30秒。
WriteTimeout
指定等待Web服务器完成写入的时间(以秒为单位)。默认情况下,它将无限期等待。可接受的最小值为2秒。
FollowRedirect
指定是否自动跟踪来自Web服务器的重定向请求(由300-399范围内的HTTP状态代码发出信号)。如果使用的是GET或HEAD,则默认值为TRUE;否则为FALSE。
指定HTTP请求的默认值
可以为%Net.HttpRequest
的所有属性指定默认值。
- 要指定适用于所有名称空间的默认值,请设置全局节
^%SYS("HttpRequest","propname")
,其中“PropName”
是属性的名称。 - 要为一个名称空间指定默认值,请转到该名称空间并设置节点
^SYS("HttpRequest","propname")
(^%SYS
全局设置会影响整个安装,^SYS
全局设置会影响当前命名空间。)
例如,要为所有名称空间指定默认代理服务器,请设置全局节^%SYS("HttpRequest","ProxyServer")