文章
· 五月 20, 2021 阅读大约需 9 分钟

第一章 发送HTTP请求

第一章 发送HTTP请求

本主题介绍如何发送HTTP请求(如POSTGET)和处理响应。

HTTP请求简介

可以创建%Net.HttpRequest的实例来发送各种HTTP请求并接收响应。此对象相当于Web浏览器,可以使用它发出多个请求。它会自动发送正确的cookie,并根据需要设置Referer标头。

要创建HTTP请求,请使用以下常规流程:

  1. 创建%Net.HttpRequest的实例。
  2. 设置此实例的属性以指示要与之通信的Web服务器。基本属性如下:
  • 服务器指定Web服务器的IP地址或计算机名称。默认值为localhost

注意:不要将http://https://作为服务器值的一部分。这将导致错误#6059:无法打开到服务器http:/的TCP/IP套接字

  1. 可以选择设置HTTP请求的其他属性和调用方法,如指定其他HTTP请求属性中所述。
  2. 然后,通过调用%Net.HttpRequest实例的get()方法或其他方法来发送HTTP请求,如“发送HTTP请求”中所述。

可以从实例发出多个请求,它将自动处理cookie和Referer标头。

注意:如果创建此HTTP请求是为了与生产出站适配器(EnsLib.HTTP.Outbound Adapter)一起使用,那么请改用该适配器的方法来发送请求。

  1. 如果需要,使用%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支持和配置的第一个方案。默认情况下,它按以下顺序考虑这些身份验证方案:

  1. 协商(SPNEGO和Kerberos,根据RFC 4559和RFC 4178)
  2. NTLM(NT LAN Manager身份验证协议)
  3. 基本认证(RFC 2617中描述的基本接入认证)

重要:如果有可能使用基本身份验证,请确保也使用SSL(参见“使用SSL进行连接”)。
在基本身份验证中,凭据以base-64编码的形式发送,因此很容易读取。

在Windows上,如果没有指定Username属性,IRIS可以使用当前登录上下文。
具体来说,如果服务器使用401状态码和用于SPNEGOKerberosNTLMWWW-Authenticate头响应,那么IRIS将使用当前操作系统用户名和密码创建Authorization头。

具体情况与HTTP 1.0不同,如下所示:

  1. 如果认证成功,IRIS更新%NetCurrentAuthenticationScheme属性。
    HttpRequest实例来指示它在最近的身份验证中使用的身份验证方案。
  2. 如果尝试获取方案的身份验证句柄或令牌失败,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/jsonapplication/pdfapplication/postscriptimage/jpegimage/pngmultipart/form-datatext/htmltext/plantext/xml等等

  • ContentCharset属性控制请求的任何内容(例如,text/htmltext/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命令建立隧道。代理服务器的地址取自ProxyServerProxyPort属性。如果ProxyHttps为true,则隧道建立后,系统间IRIS将协商SSL连接。在这种情况下,由于隧道与目标系统建立直接连接,因此将忽略https属性。

使用SSL进行连接

%Net.HttpRequest类支持SSL连接。要通过SSL发送请求,请执行以下操作:

  1. SSLConfiguration属性设置为要使用的已激活SSL/TLS配置的名称。

  2. 还要执行以下操作之一,具体取决于是否使用代理服务器:

  • 如果未使用代理服务器,请将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。

HTTPVersionTimeoutWriteTimeoutFollowRedirect属性

%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")

讨论 (1)2
登录或注册以继续