|
一、快速入門 標(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)求
注意要在發(fā)送請(qǐng)求以后,請(qǐng)求結(jié)束以前讀取 HTTP 響應(yīng)頭。這就像電話接通以后、掛斷以前你才能聽到對(duì)方的聲音 —— 不難理解吧?!
import httpUtil;var ret = httpUtil.getHeader('http://www.')另外 inet.http 也提供了直接讀取 HTTP 響應(yīng)頭的 http.head() 函數(shù):
只要調(diào)用 http.head() 發(fā)送 HEAD 請(qǐng)求,那么 inet.http 就會(huì)把全部 HTTP 響應(yīng)頭緩存起來,在請(qǐng)求結(jié)束后仍然可以使用 http.readHeader() 。 三、HTTP 方法
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í)也是可以的,代碼如下:
只要請(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)求頭并緩存起來呢?! 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展了更多的庫,如下:
基于上面這些庫再次擴(kuò)展出來的庫就更多了…… 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í)慣。 六、POST 用法 現(xiàn)在我們回到本文開始的代碼:
上面 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 ,代碼需要修改如下:
上面我們使用 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
web.rest.jsonClient 會(huì)將參數(shù)表自動(dòng)轉(zhuǎn)換為 JSON,并將服務(wù)器返回的 JSON 自動(dòng)解析為表對(duì)象。
八、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 對(duì)象的所有 HTTP 請(qǐng)求頭屬性、參數(shù)都會(huì)經(jīng)過 web.joinHeaders() 函數(shù)處理并轉(zhuǎn)化。這些 HTTP 請(qǐng)求頭都允許傳入字符串、表(鍵值對(duì)或數(shù)組)。先看個(gè)例子:
也可以使用表(鍵值對(duì))指定 HTTP 頭,例如: http.addHeaders = { 'Name1':'value1', 'Name2':'value2'}也可以在 beforeSend 事件回調(diào)內(nèi)寫 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ǎ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ì)話框:
十二、下載并解壓遠(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 示例:
string.html 的更多用法請(qǐng)參考「范例 / Web 應(yīng)用 / HTML 」 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); |
|
|