小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

玩轉(zhuǎn) inet.http

 只怕想不到 2022-05-24 發(fā)布于湖北

一、快速入門

標(biāo)準(zhǔn)庫中的 inet.http 用于創(chuàng)建 HTTP  客戶端,用法其實(shí)非常簡單,先來個(gè)最簡單的例子:

//導(dǎo)入 inet.httpimport inet.http;
//創(chuàng)建 HTTP 客戶端對(duì)象var http = inet.http();
//發(fā)送 GET 請(qǐng)求var data = http.get('http://eu./get?username=user&password=pwd');
//發(fā)送 POST 請(qǐng)求var data = http.post('http://eu./post',{ username = 'user'; password = 'pwd';});

更多例子請(qǐng)參考「aardio 自帶范例 / 網(wǎng)絡(luò)應(yīng)用 / inet / http」。

圖片

二、分步請(qǐng)求


inet.http 還提供「分步請(qǐng)求」的寫法,可以更靈活地控制請(qǐng)求,例如讀取 HTTP 響應(yīng)頭:

import inet.http;
//首先創(chuàng)建 HTTP 客戶端對(duì)象var http = inet.http();
//創(chuàng)建 HTTP 請(qǐng)求,參數(shù) @2指定請(qǐng)求方法,更多參數(shù)請(qǐng)查看函數(shù)說明http.beginRequest('http://www.','GET');
//發(fā)送請(qǐng)求http.send();
//讀取 HTTP 響應(yīng)頭(要在發(fā)送請(qǐng)求頭后才能讀取 )。var headers = http.readHeader();

注意要在發(fā)送請(qǐng)求以后,請(qǐng)求結(jié)束以前讀取 HTTP 響應(yīng)頭。這就像電話接通以后、掛斷以前你才能聽到對(duì)方的聲音 —— 不難理解吧?!

這種方法看起來代碼多了一點(diǎn)點(diǎn),但是可以更靈活地控制細(xì)節(jié)。如果想把這些代碼簡化,只要封裝一個(gè)庫函數(shù)就可以了。aardio 做這些事特別簡單,來個(gè)動(dòng)畫演示一下:

圖片

用起來就簡單了:

import httpUtil;var ret = httpUtil.getHeader('http://www.')

另外 inet.http 也提供了直接讀取 HTTP 響應(yīng)頭的 http.head() 函數(shù):

import inet.http;
var http = inet.http();http.head('http://www.');var headers = http.readHeader();

只要調(diào)用 http.head() 發(fā)送 HEAD 請(qǐng)求,那么 inet.http 就會(huì)把全部 HTTP 響應(yīng)頭緩存起來,在請(qǐng)求結(jié)束后仍然可以使用 http.readHeader() 。

三、HTTP 方法


GET,POST,HEAD,PUT,DELETE,PATCH …… 這些都是 HTTP 方法( HTTP method ),如果將 HTTP 服務(wù)器比作銀行,那么 GET 就相當(dāng)于去銀行取款,POST 就相當(dāng)于去銀行存款,HEAD 就相當(dāng)于去銀行咨詢一下 —— 但什么也不干。

我們可以用 TCP 客戶端模擬一下 HTTP 協(xié)議的 HEAD 請(qǐng)求,代碼如下:

import wsock.tcp.client; var tcp = wsock.tcp.client() tcp.connect('www.',80)
sendData =/***********HEAD / HTTP/1.1Host: www. Connection: closeUser-Agent: Mozilla/5.0 Accept: */*; ***********/
tcp.write( sendData,'\r\n\r\n' );headers = tcp.readTo('\r\n\r\n');//HTTP頭以兩個(gè)回車換行結(jié)束tcp.close() ;
import console;console.log( headers )console.pause();

四、在請(qǐng)求結(jié)束后讀取 HTTP 響應(yīng)頭

那么如果說不想寫擴(kuò)展庫,也不想發(fā)送 HEAD 請(qǐng)求,也不想分步請(qǐng)求 …… 就是想要在 http.get() 或 http.post() 結(jié)束請(qǐng)求以后還能繼續(xù)讀取 HTTP 響應(yīng)頭行不行?!其實(shí)也是可以的,代碼如下:

import inet.http;
//創(chuàng)建 HTTP 對(duì)象var http = inet.http();
//發(fā)送請(qǐng)求后會(huì)自動(dòng)讀取所有 HTTP 響應(yīng)頭http.afterSend = lambda() http.readHeader();
//發(fā)送 POST 請(qǐng)求var data = http.post('http://eu./post',{ username = 'user'; password = 'pwd';});
/*只要請(qǐng)求結(jié)束前讀取過全部 HTTP 響應(yīng)頭,aardio 就會(huì)緩存起來,請(qǐng)求結(jié)束后可以繼續(xù)讀取 HTTP 響應(yīng)頭*/var contentType = http.readHeader('Content-Type:')

只要請(qǐng)求結(jié)束前讀取過全部 HTTP 響應(yīng)頭,

aardio 就會(huì)緩存起來,請(qǐng)求結(jié)束后可以繼續(xù)讀取 HTTP 響應(yīng)頭。

五、擴(kuò)展庫而不是修改庫

那么如果不想多寫一句 http.afterSend …… 該怎么辦?!要不要打開 inet.http 修改一下源代碼,讓所有 HTTP 請(qǐng)求都讀取所有 HTTP 請(qǐng)求頭并緩存起來呢?!

其實(shí)大多數(shù) HTTP 請(qǐng)求不需要也不應(yīng)該執(zhí)行這個(gè)多余的步驟,這時(shí)候我們就要思考一下了:

1、某一時(shí)刻的單點(diǎn)需求,并不等于任何人任何時(shí)候都需要。  

2、把所有需求都盲目地塞進(jìn)一個(gè)庫,這會(huì)讓一個(gè)庫漸漸變得笨拙、復(fù)雜且難以擴(kuò)展。

“擴(kuò)展而不是修改庫” ——通常是更好的選擇。如果你不想多寫這句 http.afterSend … ,只要簡單地寫一個(gè)新庫擴(kuò)展一下 inet.http 就可以,代碼非常簡單,例如:

import inet.http;
class myHttp{ ctor( ... ){ this = ..inet.http( ... ); this.afterSend = lambda() this.readHeader(); }; }

web.rest.client 就是一個(gè)基于 inet.http 而封裝的上層庫。而基于 web.rest.client 又?jǐn)U展了更多的庫,如下:

web.rest.jsonClientweb.rest.jsonLiteClientweb.rest.xmlClient web.rest.htmlClient 

基于上面這些庫再次擴(kuò)展出來的庫就更多了…… 

aardio 基于 inet.http 擴(kuò)展的庫非常多,足見 inet.http 有良好的擴(kuò)展能力。可以設(shè)想一下,如果 inet.http 不是把更多的機(jī)會(huì)留給其他庫去發(fā)揮,而是什么事都搶著干,提前干,不管別人需不需要的功能都強(qiáng)行干了 —— 這多么可怕?!

inet.http 有個(gè)自動(dòng)解壓 gzip 壓縮數(shù)據(jù)的功能,同樣需要需要多寫一句代碼,先看例子:

import zlib;import inet.http;
var http = inet.http();var str = http.get('http://eu./gzip','Accept-Encoding:gzip');

只有提前多寫一句 import zlib ,inet.http 才會(huì)支持 gzip 自動(dòng)解壓。其實(shí)我們寫 HTTP 請(qǐng)求不像在瀏覽器里看網(wǎng)頁,大多時(shí)候我們不需要 gzip 壓縮傳輸。僅僅因?yàn)閭€(gè)例需要什么東西,就強(qiáng)制所有人在所有時(shí)候都帶上它 —— 這不是好習(xí)慣。

所以很多時(shí)候,我們不要害怕多寫了一兩句代碼。代碼簡潔是好習(xí)慣,但害怕多寫了一兩句代碼是壞習(xí)慣。不寫代碼我們還學(xué)編程干什么呢?!  

六、POST 用法

現(xiàn)在我們回到本文開始的代碼:

import inet.http;var http = inet.http();  //發(fā)送 POST 請(qǐng)求var data = http.post('http://eu./post',{    username = 'user'; password = 'pwd';});

上面 http.post 的第 2 個(gè)參數(shù)如果是一個(gè)表對(duì)象,會(huì)自動(dòng)轉(zhuǎn)換為如下的調(diào)用:

http.post('http://eu./post' ,'username=user&password=pwd');

如果要向服務(wù)器提交 JSON ,代碼需要修改如下:

import web.json;import inet.http; //發(fā)送 POST 請(qǐng)求 var http = inet.http(); var data = http.post('http://eu./post',  web.json.stringify({ username = 'user'; password = 'pwd' }));

上面我們使用 web.json.stringify() 函數(shù)將表對(duì)象轉(zhuǎn)換為了 JSON 字符串,http.post 如果檢測(cè)到 POST 數(shù)據(jù)是 JSON ,并且 HTTP 請(qǐng)求頭中不包含 Content-Type 的定義,就會(huì)自動(dòng)添加以下請(qǐng)求頭:

Content-Type: application/json; charset=utf-8

其實(shí) inet.http 已經(jīng)默默的做了很多事,以簡化我們的調(diào)用代碼,但仍然要注意這種簡化是有底線和邊界的。

七、web.rest 


如果我們希望更好地支持 JSON,使用基于 inet.http 的 web.rest.jsonClient 會(huì)更簡單:

import web.rest.jsonClient;var http = web.rest.jsonClient();
var data = http.post('http://eu./post' ,{ username = 'user'; password = 'pwd' });

web.rest.jsonClient 會(huì)將參數(shù)表自動(dòng)轉(zhuǎn)換為 JSON,并將服務(wù)器返回的 JSON 自動(dòng)解析為表對(duì)象。

如果 HTTP 請(qǐng)求需要發(fā)送 JSON,而服務(wù)器響應(yīng)并非 JSON,這時(shí)候只要把上面的  web.rest.jsonClient 替換為 web.rest.jsonLiteClient 就可以了。


web.rest 非常重要,請(qǐng)參考「aardio 范例 / Web 應(yīng)用 / REST」

圖片

強(qiáng)烈推薦大家仔細(xì)看看 aardio 開始頁的教程:《使用 web.rest 實(shí)現(xiàn) REST-RPC》 。不過還是先看完這篇文章再去看會(huì)更好。 

八、HTTP 請(qǐng)求返回值

實(shí)際上 inet.http 對(duì)象發(fā)送請(qǐng)求的函數(shù)基本都有 3 個(gè)返回值:響應(yīng)數(shù)據(jù),錯(cuò)誤信息,錯(cuò)誤代碼。我們前面的示例都只使用了第 1 個(gè)返回值。接收所有返回值的示例:

import console; import inet.http;
//創(chuàng)建 HTTP 對(duì)象var http = inet.http();
//3 個(gè)返回值:響應(yīng)數(shù)據(jù),錯(cuò)誤信息,錯(cuò)誤代碼var data,err,errCode = http.post( 'http://eu./post' ,'username=user&password=pwd' );
if( data ){ console.log(data);}else { if( http.statusCode ){ //服務(wù)端返回錯(cuò)誤信息 console.log( http.lastResponse(), 'HTTP錯(cuò)誤代碼:' + http.statusCode ) } else{ //本地內(nèi)部錯(cuò)誤 console.log( err,errCode ); }}
http.close();console.pause();

可以使用「 aardio 工具 / 網(wǎng)絡(luò) / HTTP 狀態(tài)碼檢測(cè)」查詢 HTTP 錯(cuò)誤代碼(  上面的 errCode )與 HTTP 狀態(tài)碼( http.statusCode )的詳細(xì)信息:

圖片

九、指定 HTTP 請(qǐng)求頭

前面我們講了如何獲取 HTTP 響應(yīng)頭,下面我們講一下如何自定義 HTTP 請(qǐng)求頭。其實(shí) inet.http 已經(jīng)默認(rèn)設(shè)置好了必要的 HTTP 請(qǐng)求頭,一般并不需要自己指定 HTTP 請(qǐng)求頭參數(shù)。我發(fā)現(xiàn)很多人在寫這類 HTTP 請(qǐng)求代碼時(shí),都喜歡復(fù)制粘貼一大堆根本就沒用的 HTTP 請(qǐng)求頭 —— 這又多寫一大堆代碼不嫌累。有時(shí)候明明沒問題還因?yàn)檫@些多余的請(qǐng)求頭搞出問題。 例如  inet.http,inet.whttp  都提供了專用的 referer 屬性( 自動(dòng)設(shè)置值,一般不應(yīng)修改 ),發(fā)送請(qǐng)求的 get,post 等函數(shù)也都可以指定 referer 參數(shù) ,很明顯通過 HTTP 頭去指定 referer 既不必要也會(huì)錯(cuò)亂。

 
inet.http 其實(shí)已經(jīng)幫我們做好了很多事,并不需要每一個(gè) HTTP 頭都去寫一遍。所以大家看前面我寫的代碼都沒有自定義任何 HTTP 請(qǐng)求頭,這沒有任何問題。

inet.http 對(duì)象的所有 HTTP 請(qǐng)求頭屬性、參數(shù)都會(huì)經(jīng)過 web.joinHeaders() 函數(shù)處理并轉(zhuǎn)化。這些 HTTP 請(qǐng)求頭都允許傳入字符串、表(鍵值對(duì)或數(shù)組)。先看個(gè)例子:

import inet.http;var http = inet.http();  //設(shè)置所有請(qǐng)求默認(rèn)添加的 HTTP 頭,請(qǐng)求結(jié)束不清空 http.addHeaders = 'Name1:value1\r\nName2:value2';

也可以使用表(鍵值對(duì))指定 HTTP 頭,例如:

http.addHeaders = { 'Name1':'value1', 'Name2':'value2'}

也可以在 beforeSend 事件回調(diào)內(nèi)寫 HTTP 請(qǐng)求頭。

http.beforeSend = function(){    http.writeHeader('Name2:value2'); //寫 HTTP 請(qǐng)求頭 }

也可以通過 http.get() , http.post() 等函數(shù)的參數(shù)指定 HTTP 請(qǐng)求頭:

var data = http.post('http://www./post', ,{ 'Accept-Language':'zh-CN,zh'; });

十、多線程與界面

如果在界面線程中調(diào)用 inet.http ,要注意 inet.http 執(zhí)行請(qǐng)求屬于耗時(shí)操作 —— 會(huì)阻塞界面線程。不過  aardio 創(chuàng)建多線程非常方便,將 HTTP 請(qǐng)求放到工作線程里就不會(huì)卡界面了,示例如下:

import win.ui;/*DSG{{*/var winform = win.form(text='獲取 HTML';right=759;bottom=469)winform.add(btnGetUrl={cls='button';text='獲取 HTML';left=481;top=376;right=713;bottom=432;color=14120960;db=1;dr=1;font=LOGFONT(h=-14);note='創(chuàng)建工作線程請(qǐng)求目標(biāo)網(wǎng)址';z=2};editHtml={cls='edit';left=29;top=24;right=735;bottom=361;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;vscroll=1;z=1};editUrl={cls='edit';text='http://www.';left=33;top=385;right=453;bottom=413;db=1;dl=1;dr=1;edge=1;multiline=1;z=3})/*}}*/
winform.btnGetUrl.oncommand = function(id,event){ winform.btnGetUrl.disabled = true; //創(chuàng)建工作線程 thread.invoke( function(winform){ import inet.http; var http = inet.http(); var data = http.get(winform.editUrl.text); //顯示抓取結(jié)果 winform.editHtml.text = data; //啟用按鈕 winform.btnGetUrl.disabled = false; },winform /*將窗口對(duì)象作為參數(shù)傳入線程函數(shù)*/ )}
winform.show();win.loopMessage();

圖片


在界面線程中簡單地請(qǐng)求一個(gè)網(wǎng)址也可以使用 inet.http.get( url ) ,這個(gè)函數(shù)也會(huì)創(chuàng)建線程執(zhí)行 HTTP 請(qǐng)求,不卡界面且代碼更少一些。

十一、斷點(diǎn)續(xù)傳

如果需要下載文件并支持?jǐn)帱c(diǎn)續(xù)傳,可以使用基于 inet.http 實(shí)現(xiàn)的 inet.httpFile,來個(gè)斷點(diǎn)續(xù)傳下載的例子:

import console;import console.progress;import inet.httpFile;
var remoteFile = inet.httpFile( 'http://wubi./update/wubiLex.7z' ,'/.download/')
var progress = console.progress();remoteFile.onReceive = function(data,downSize,contentLength){ progress.addProgress((downSize/contentLength)*100 ,'正在下載 文件大?。? + math.size64(contentLength).format() ) }
//下載文件if(remoteFile.download() ){ console.log('下載成功')}console.pause();

如果還想給下載點(diǎn)加個(gè)窗口界面什么的,我們不必改動(dòng)  inet.httpFile ,使用基于 inet.httpFile 的 inet.downBox 就可以方便地創(chuàng)建下載對(duì)話框:

import inet.downBox;
var downBox = inet.downBox(winform,'下載測(cè)試網(wǎng)頁...',true )if( downBox.download( 'http://download./v10.files/exlibs/tcc.tar.lzma' , '~/download/lib/tcc.tar.lzma' ) ){ win.msgbox('download complete');}

十二、下載并解壓遠(yuǎn)程壓縮包

如果我們不但要下載對(duì)話框,還想下載壓縮包,順帶解壓縮 …… 或者順帶安裝程序 —— 同樣不必修改  inet.downBox ,有很多基于  inet.downBox 的庫可以實(shí)現(xiàn)這些功能:

zlib.httpFile //下載 + zip 解壓縮sevenZip.lzma.httpFile //下載 + lzma 解壓縮sevenZip.decoder2.httpFile //下載 + 7z 解壓縮inet.installer //下載 + 自動(dòng)安裝程序

標(biāo)準(zhǔn)庫還有一個(gè) inet.whttp,用法與接口與 inet.http 基本相同,一般可相互替代。inet.http 基于 WinINet,而 inet.whttp 基于 WinHTTP。一般普通桌面客戶端軟件(非NT服務(wù))應(yīng)當(dāng)使用 inet.http。

十三、HTML 解析

對(duì)于服務(wù)器返回的 HTML ,我們可以使用 web.mshtml 或者 string.html 解析,調(diào)用 string.html 示例:

import console;import string.html;
var html = /* <!doctype html><html><head></head><body><table id='container'><tr><td rowspan='1' class='tab_time tab_time102540630'>06:30</td></tr></table></body>*/
var htmlDoc = string.html( html ) //獲取 body 節(jié)點(diǎn)var body = htmlDoc.queryEles( tagName = 'body');
//遍歷 body 節(jié)點(diǎn)的所有子節(jié)點(diǎn)for(index,tagName,childCount,xNode in body[1].eachChild() ){ console.log( index,tagName,childCount,xNode.outerXml() ) }
console.pause()

string.html 的更多用法請(qǐng)參考「范例 / Web 應(yīng)用 / HTML 」

當(dāng)然我們也可以使用 web.rest.htmlClient,一個(gè)簡單的例子:

import console; import web.rest.htmlClient;var http = web.rest.htmlClient();
var google = http.api('https://translate.*****.cn/m?hl=zh-CN');
var htmlDoc = google.get(q='hello',sl='en',tl='zh-CN');if(htmlDoc){ var resultContainer = htmlDoc.queryEle({'class':'result-container'}) if(resultContainer){ console.log(resultContainer.innerText()); }}
console.pause(true);

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多