第一章 發(fā)送HTTP請(qǐng)求
本主題介紹如何發(fā)送HTTP
請(qǐng)求(如POST
或GET
)和處理響應(yīng)。
HTTP請(qǐng)求簡(jiǎn)介
可以創(chuàng)建%Net.HttpRequest
的實(shí)例來(lái)發(fā)送各種HTTP
請(qǐng)求并接收響應(yīng)避除。此對(duì)象相當(dāng)于Web瀏覽器呵燕,可以使用它發(fā)出多個(gè)請(qǐng)求凌盯。它會(huì)自動(dòng)發(fā)送正確的cookie
,并根據(jù)需要設(shè)置Referer
標(biāo)頭。
要?jiǎng)?chuàng)建HTTP請(qǐng)求少欺,請(qǐng)使用以下常規(guī)流程:
- 創(chuàng)建
%Net.HttpRequest
的實(shí)例白翻。 - 設(shè)置此實(shí)例的屬性以指示要與之通信的Web服務(wù)器乍炉。基本屬性如下:
- 服務(wù)器指定Web服務(wù)器的IP地址或計(jì)算機(jī)名稱滤馍。默認(rèn)值為
localhost
岛琼。
注意:不要將http://
或https://
作為服務(wù)器值的一部分。這將導(dǎo)致錯(cuò)誤#6059:無(wú)法打開到服務(wù)器http:/的TCP/IP套接字
巢株。
- 可以選擇設(shè)置HTTP請(qǐng)求的其他屬性和調(diào)用方法槐瑞,如指定其他HTTP請(qǐng)求屬性中所述。
- 然后阁苞,通過(guò)調(diào)用
%Net.HttpRequest
實(shí)例的get()
方法或其他方法來(lái)發(fā)送HTTP請(qǐng)求困檩,如“發(fā)送HTTP請(qǐng)求”中所述。
可以從實(shí)例發(fā)出多個(gè)請(qǐng)求那槽,它將自動(dòng)處理cookie和Referer標(biāo)頭悼沿。
注意:如果創(chuàng)建此HTTP請(qǐng)求是為了與生產(chǎn)出站適配器(EnsLib.HTTP.Outbound Adapter
)一起使用,那么請(qǐng)改用該適配器的方法來(lái)發(fā)送請(qǐng)求骚灸。
- 如果需要糟趾,使用
%Net.HttpRequest
的同一實(shí)例發(fā)送其他HTTP請(qǐng)求。默認(rèn)情況下甚牲,InterSystems IRIS使TCP/IP套接字保持打開狀態(tài)义郑,以便可以重復(fù)使用套接字,而無(wú)需關(guān)閉和重新打開它丈钙。
以下是一個(gè)簡(jiǎn)單的示例:
/// 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()
}
提供身份驗(yàn)證
如果目標(biāo)服務(wù)器需要登錄憑據(jù)非驮,則HTTP請(qǐng)求可以包括提供憑據(jù)的HTTP Authorization
標(biāo)頭。
如果使用的是代理服務(wù)器著恩,還可以指定代理服務(wù)器的登錄憑據(jù)院尔;為此蜻展,請(qǐng)?jiān)O(shè)置ProxyAuthorization
屬性
使用HTTP 1.0時(shí)對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證
對(duì)于HTTP 1.0,要驗(yàn)證HTTP請(qǐng)求邀摆,請(qǐng)?jiān)O(shè)置%Net.HttpRequest
實(shí)例的用戶名和密碼屬性纵顾。然后,該實(shí)例使用基本訪問(wèn)身份驗(yàn)證基于該用戶名和密碼創(chuàng)建HTTP Authorization
標(biāo)頭(RFC 2617)栋盹。此%Net.HttpRequest
發(fā)送的任何后續(xù)請(qǐng)求都將包括此頭施逾。
重要提示:請(qǐng)確保還使用SSL。在基本身份驗(yàn)證中例获,憑據(jù)以base-64編碼形式發(fā)送汉额,因此易于讀取。
在使用HTTP 1.1時(shí)對(duì)請(qǐng)求進(jìn)行身份驗(yàn)證
對(duì)于HTTP 1.1榨汤,要驗(yàn)證HTTP請(qǐng)求蠕搜,在大多數(shù)情況下,只需設(shè)置%Net.HttpRequest
實(shí)例的用戶名和密碼屬性收壕。當(dāng)%Net.HttpRequest
的實(shí)例收到401 HTTP
狀態(tài)代碼和WWW-Authenticate
標(biāo)頭時(shí)妓灌,它會(huì)嘗試使用包含支持的身份驗(yàn)證方案的Authorization
標(biāo)頭進(jìn)行響應(yīng)。使用為IRIS支持和配置的第一個(gè)方案蜜宪。默認(rèn)情況下虫埂,它按以下順序考慮這些身份驗(yàn)證方案:
- 協(xié)商(SPNEGO和Kerberos,根據(jù)RFC 4559和RFC 4178)
- NTLM(NT LAN Manager身份驗(yàn)證協(xié)議)
- 基本認(rèn)證(RFC 2617中描述的基本接入認(rèn)證)
重要:如果有可能使用基本身份驗(yàn)證圃验,請(qǐng)確保也使用SSL(參見“使用SSL進(jìn)行連接”)掉伏。
在基本身份驗(yàn)證中,憑據(jù)以base-64編碼的形式發(fā)送澳窑,因此很容易讀取斧散。
在Windows上,如果沒有指定Username
屬性照捡,IRIS可以使用當(dāng)前登錄上下文颅湘。
具體來(lái)說(shuō),如果服務(wù)器使用401狀態(tài)碼和用于SPNEGO
栗精、Kerberos
或NTLM
的WWW-Authenticate
頭響應(yīng)闯参,那么IRIS將使用當(dāng)前操作系統(tǒng)用戶名和密碼創(chuàng)建Authorization
頭。
具體情況與HTTP 1.0不同悲立,如下所示:
- 如果認(rèn)證成功鹿寨,IRIS更新
%Net
的CurrentAuthenticationScheme
屬性。
HttpRequest
實(shí)例來(lái)指示它在最近的身份驗(yàn)證中使用的身份驗(yàn)證方案薪夕。 - 如果嘗試獲取方案的身份驗(yàn)證句柄或令牌失敗脚草,IRIS會(huì)將基礎(chǔ)錯(cuò)誤保存到
%Net.HttpRequest
實(shí)例的AuthenticationErrors
屬性中。此屬性的值為$List
原献,其中每一項(xiàng)都具有格式scheme ERROR: message
僅HTTP 1.1支持協(xié)商和NTLM
馏慨,因?yàn)檫@些方案需要多次往返埂淮,而HTTP 1.0要求在每個(gè)請(qǐng)求/響應(yīng)對(duì)之后關(guān)閉連接。
Variations
如果知道服務(wù)器允許的一個(gè)或多個(gè)身份驗(yàn)證方案写隶,則可以通過(guò)包括Authorization
標(biāo)頭來(lái)繞過(guò)服務(wù)器的初始往返行程倔撞,該標(biāo)頭包含所選方案的服務(wù)器的初始令牌。為此慕趴,請(qǐng)?jiān)O(shè)置%Net.HttpRequest
實(shí)例的InitiateAuthentication
屬性痪蝇。對(duì)于此屬性的值,請(qǐng)指定服務(wù)器允許的單個(gè)授權(quán)方案的名稱冕房。使用下列值之一(區(qū)分大小寫):
- Negotiate
- NTLM
- Basic
如果要自定義要使用的身份驗(yàn)證方案(或更改其考慮順序)躏啰,請(qǐng)?jiān)O(shè)置%Net.HttpRequest
實(shí)例的AuthenticationSchemes
。對(duì)于此屬性的值耙册,請(qǐng)指定以逗號(hào)分隔的身份驗(yàn)證方案名稱列表(使用上一個(gè)列表中給出的準(zhǔn)確值)给僵。
直接指定授權(quán)標(biāo)頭
對(duì)于HTTP 1.0或HTTP 1.1(如果適用于場(chǎng)景),可以直接指定HTTP Authorization
標(biāo)頭觅玻。具體地說(shuō)想际,可以將Authorization
屬性設(shè)置為等于正在請(qǐng)求的資源的用戶代理所需的身份驗(yàn)證信息培漏。
如果指定Authorization
屬性溪厘,則忽略用戶名和密碼屬性。
啟用HTTP身份驗(yàn)證的日志記錄
要啟用HTTP身份驗(yàn)證的日志記錄牌柄,請(qǐng)?jiān)诮K端中輸入以下內(nèi)容:
set $namespace="%SYS"
kill ^ISCLOG
set ^%ISCLOG=2
set ^%ISCLOG("Category","HttpRequest")=5
日志條目將寫入^ISCLOG global
中.畸悬。要將日志寫入文件(以提高可讀性),請(qǐng)輸入以下內(nèi)容(仍在%SYS
命名空間內(nèi)):
do ##class(%OAuth2.Utils).DisplayLog("filename")
其中珊佣,filename
是要?jiǎng)?chuàng)建的文件的名稱蹋宦。該目錄必須已存在。如果該文件已經(jīng)存在咒锻,它將被覆蓋冷冗。
要停止日志記錄,請(qǐng)輸入以下內(nèi)容(仍在%SYS
命名空間內(nèi)):
set ^%ISCLOG=0
set ^%ISCLOG("Category","HttpRequest")=0
指定其他HTTP請(qǐng)求屬性
在發(fā)送HTTP請(qǐng)求之前(請(qǐng)參閱發(fā)送HTTP請(qǐng)求)惑艇,可以指定其屬性蒿辙,如以下各節(jié)所述:
可以為%Net.HttpRequest
的所有屬性指定默認(rèn)值,如最后列出的部分中所指定滨巴。
Location屬性
Location
屬性指定從Web服務(wù)器請(qǐng)求的資源思灌。如果設(shè)置此屬性,則在調(diào)用Get()
, Head()
, Post()
, 或 Put()
方法時(shí)恭取,可以省略location參數(shù)泰偿。
例如,假設(shè)正在向url http://machine_name/test/index.html
發(fā)送一個(gè)HTTP請(qǐng)求
在這種情況下蜈垮,將使用下列值:
%Net.HttpRequest
的示例屬性
Properties | Value |
---|---|
Server | machine_name |
Location | test/index.html |
指定Internet媒體類型(Media Type)和字符編碼(Character Encoding)
可以使用以下屬性指定%Net.HttpRequest
實(shí)例及其響應(yīng)中的Internet媒體類型(也稱為MIME類型)和字符編碼:
- Content-Type指定
Content-Type
標(biāo)頭耗跛,該標(biāo)頭指定請(qǐng)求正文的Internet媒體類型裕照。默認(rèn)類型為None。
可能的值包括application/json
调塌、application/pdf
牍氛、application/postscript
、image/jpeg
烟阐、image/png
搬俊、multipart/form-data
、text/html
蜒茄、text/plan
唉擂、text/xml
等等
- ContentCharset屬性控制請(qǐng)求的任何內(nèi)容(例如,
text/html
或text/xml
)類型時(shí)所需的字符集檀葛。如果不指定此屬性玩祟,InterSystems IRIS將使用InterSystems IRIS服務(wù)器的默認(rèn)編碼。
注意:如果設(shè)置此屬性屿聋,則必須首先設(shè)置ContentType
屬性空扎。
-
NoDefaultContentCharset
屬性控制在未設(shè)置ContentCharset
屬性的情況下是否包括文本類型內(nèi)容的顯式字符集。默認(rèn)情況下润讥,此屬性為False转锈。
如果此屬性為true,則如果有文本類型的內(nèi)容楚殿,并且沒有設(shè)置ContentCharset
屬性撮慨,則內(nèi)容類型中不包括任何字符集;這意味著字符集iso-8859-1用于消息輸出脆粥。
- WriteRawMode屬性影響實(shí)體正文(如果包含)砌溺。它控制請(qǐng)求正文的寫入方式。默認(rèn)情況下变隔,此屬性為False规伐,并且InterSystems IRIS以請(qǐng)求標(biāo)頭中指定的編碼寫入正文。如果此屬性為true匣缘,則InterSystems IRIS以原始模式寫入正文(不執(zhí)行字符集轉(zhuǎn)換)猖闪。
-
ReadRawMode
屬性控制如何讀取響應(yīng)正文。默認(rèn)情況下孵户,此屬性為False萧朝,并且InterSystems IRIS假定正文在響應(yīng)標(biāo)頭中指定的字符集中。如果此屬性為true夏哭,InterSystems IRIS將以原始模式讀取正文(不執(zhí)行字符集轉(zhuǎn)換)检柬。
使用代理服務(wù)器
可以通過(guò)代理服務(wù)器發(fā)送HTTP請(qǐng)求。要設(shè)置此設(shè)置,請(qǐng)指定HTTP請(qǐng)求的以下屬性:
-
ProxyServer
指定要使用的代理服務(wù)器的主機(jī)名何址。如果此屬性不為空里逆,則將HTTP請(qǐng)求定向到此計(jì)算機(jī)。 -
ProxyPort
指定代理服務(wù)器上要連接到的端口用爪。 -
ProxyAuthorization
指定Proxy-Authorization
標(biāo)頭原押,如果用戶代理必須使用代理驗(yàn)證其自身,則必須設(shè)置該標(biāo)頭偎血。對(duì)于該值诸衔,請(qǐng)使用正在請(qǐng)求的資源的用戶代理所需的身份驗(yàn)證信息。 -
ProxyHTTPS
控制HTTP請(qǐng)求是針對(duì)HTTPS頁(yè)面還是針對(duì)普通HTTP頁(yè)面颇玷。如果未指定代理服務(wù)器笨农,則忽略此屬性。此屬性將目標(biāo)系統(tǒng)上的默認(rèn)端口更改為代理端口443帖渠。 -
ProxyTunes
指定是否通過(guò)代理建立到目標(biāo)HTTP服務(wù)器的隧道谒亦。如果為true,則請(qǐng)求使用HTTP CONNECT命令建立隧道空郊。代理服務(wù)器的地址取自ProxyServer
和ProxyPort
屬性份招。如果ProxyHttps
為true,則隧道建立后狞甚,系統(tǒng)間IRIS將協(xié)商SSL連接锁摔。在這種情況下,由于隧道與目標(biāo)系統(tǒng)建立直接連接入愧,因此將忽略https屬性鄙漏。
使用SSL進(jìn)行連接
%Net.HttpRequest
類支持SSL連接。要通過(guò)SSL發(fā)送請(qǐng)求棺蛛,請(qǐng)執(zhí)行以下操作:
將
SSLConfiguration
屬性設(shè)置為要使用的已激活SSL/TLS配置的名稱。還要執(zhí)行以下操作之一巩步,具體取決于是否使用代理服務(wù)器:
- 如果未使用代理服務(wù)器旁赊,請(qǐng)將
https
屬性設(shè)置為true。 - 如果使用的是代理服務(wù)器椅野,請(qǐng)將
ProxyHTTPS
屬性設(shè)置為true终畅。
在這種情況下,要使用到代理服務(wù)器本身的SSL
連接竟闪,請(qǐng)將https屬性設(shè)置為true离福。
請(qǐng)注意,當(dāng)使用到給定服務(wù)器的SSL
連接時(shí)炼蛤,該服務(wù)器上的默認(rèn)端口假定為443(HTTPS端口)妖爷。例如,如果沒有使用代理服務(wù)器理朋,并且https為true絮识,則會(huì)將Default Port屬性更改為443绿聘。
服務(wù)器身份檢查
默認(rèn)情況下,當(dāng)%Net.HttpRequest
實(shí)例連接到SSL/TLS安全的Web服務(wù)器時(shí)次舌,它會(huì)檢查證書服務(wù)器名稱是否與用于連接到服務(wù)器的DNS
名稱匹配熄攘。如果這些名稱不匹配,則不允許連接彼念。此默認(rèn)行為可防止“中間人”攻擊挪圾,在RFC 2818的3.1節(jié)中進(jìn)行了描述;另請(qǐng)參閱RFC 2595的2.4節(jié)逐沙。
若要禁用此檢查洛史,請(qǐng)將SSLCheckServerIdentity
屬性設(shè)置為0。
HTTPVersion
酱吝、Timeout
也殖、WriteTimeout
和FollowRedirect
屬性
%Net.HttpRequest
還提供以下屬性:
HTTPVersion
指定請(qǐng)求頁(yè)面時(shí)使用的HTTP版本。默認(rèn)值是"HTTP/1.1"
务热。你也可以使用“HTTP/1.0”
忆嗜。
Timeout
指定等待web服務(wù)器響應(yīng)的時(shí)間,以秒為單位崎岂。
缺省值是30秒捆毫。
WriteTimeout
指定等待Web服務(wù)器完成寫入的時(shí)間(以秒為單位)。默認(rèn)情況下冲甘,它將無(wú)限期等待绩卤。可接受的最小值為2秒江醇。
FollowRedirect
指定是否自動(dòng)跟蹤來(lái)自Web服務(wù)器的重定向請(qǐng)求(由300-399范圍內(nèi)的HTTP狀態(tài)代碼發(fā)出信號(hào))濒憋。如果使用的是GET或HEAD,則默認(rèn)值為TRUE陶夜;否則為FALSE凛驮。
指定HTTP請(qǐng)求的默認(rèn)值
可以為%Net.HttpRequest
的所有屬性指定默認(rèn)值。
- 要指定適用于所有名稱空間的默認(rèn)值条辟,請(qǐng)?jiān)O(shè)置全局節(jié)
^%SYS("HttpRequest","propname")
黔夭,其中“PropName”
是屬性的名稱。 - 要為一個(gè)名稱空間指定默認(rèn)值羽嫡,請(qǐng)轉(zhuǎn)到該名稱空間并設(shè)置節(jié)點(diǎn)
^SYS("HttpRequest","propname")
(^%SYS
全局設(shè)置會(huì)影響整個(gè)安裝本姥,^SYS
全局設(shè)置會(huì)影響當(dāng)前命名空間。)
例如杭棵,要為所有名稱空間指定默認(rèn)代理服務(wù)器婚惫,請(qǐng)?jiān)O(shè)置全局節(jié)^%SYS("HttpRequest","ProxyServer")