NodeJs surperagent API

題外話

superagent是nodejs里一個非常方便的客戶端請求代理模塊,當(dāng)你想處理get,post,put,delete,head請求時,你就應(yīng)該想起該用它了:)

SuperAgent

superagent 是一個輕量的,漸進(jìn)式的ajax api,可讀性好,學(xué)習(xí)曲線低,內(nèi)部依賴nodejs原生的請求api,適用于nodejs環(huán)境下.

一個簡單的post請求,并設(shè)置請求頭信息的例子

request.post('/api/pet').send({name:'Manny',species:'cat'}).set('X-API-Key','foobar').set('Accept','application/json').end(function(res){if(res.ok){alert('yay got '+JSON.stringify(res.body));}else{alert('Oh no! error '+res.text);}});

測試文檔

這個鏈接文檔,是用Mocha’s文檔自動輸出的,下面提供了這個測試文檔對應(yīng)的源文件

請求基礎(chǔ)

一個請求的初始化可以用請求對象里合適的方法來執(zhí)行,然后調(diào)用end()來發(fā)送請求,下面是一個簡單的get請求

request.get('/search').end(function(res){});

請求方法也可以通過參數(shù)傳遞:

request('GET','/search').end(callback);

node客戶端也允許提供絕對路徑:

request.get('http://example.com/search').end(function(res){});

delete,head,post,put和別的http動作都可以使用,來換個方法看看:

request.head('/favicon.ico').end(function(res){});

delete是一個特列,因為它是系統(tǒng)保留的關(guān)鍵字,所以應(yīng)該用.del()這個名字:

request.del('/user/1').end(function(res){});

http請求默認(rèn)的方法為get,所以就像你看到的,下面的這個例子也是可用的:

request('/search',function(res){});

設(shè)置頭字段

設(shè)置頭字段非常簡單,只需調(diào)用.set()方法,傳遞一個名稱和值就行:

request.get('/search').set('API-Key','foobar').set('Accept','application/json').end(callback);

你也可以直接傳遞一個對象進(jìn)去,這樣一次就可以修改多個頭字段:

request.get('/search').set({'API-Key':'foobar',Accept:'application/json'}).end(callback);

Get請求

當(dāng)使用get請求傳遞查詢字符串的時候,用.query()方法,傳遞一個對象就可以,下面的代碼將產(chǎn)生一個/search?query=Manny&range=1..5&order=desc請求:

request.get('/search').query({query:'Manny'}).query({range:'1..5'}).query({order:'desc'}).end(function(res){});

或者傳一個單獨的大對象:

request.get('/search').query({query:'Manny',range:'1..5',order:'desc'}).end(function(res){});

.query()方法也允許傳遞字符串:

request.get('/querystring').query('search=Manny&range=1..5').end(function(res){});

或者字符串拼接:

request.get('/querystring').query('search=Manny').query('range=1..5').end(function(res){});

POST/PUT請求

一個典型的json post請求看起來就像下面的那樣,設(shè)置一個合適的Content-type頭字段,然后寫入一些數(shù)據(jù),在這個例子里只是json字符串:

request.post('/user').set('Content-Type','application/json').send('{"name":"tj","pet":"tobi"}').end(callback)

因為json非常通用,所以就作為默認(rèn)的Content-type,下面的例子跟上面的一樣:

request.post('/user').send({name:'tj',pet:'tobi'}).end(callback)

或者調(diào)用多次.send()方法:

request.post('/user').send({name:'tj'}).send({pet:'tobi'}).end(callback)

默認(rèn)發(fā)送字符串,將設(shè)置Content-type為application/x-www-form-urlencoded,多次調(diào)用將會通過&來連接,這里的結(jié)果為name=tj&pet=tobi:

request.post('/user').send('name=tj').send('pet=tobi').end(callback);

superagent的請求數(shù)據(jù)格式化是可以擴(kuò)展的,不過默認(rèn)支持form和json兩種格式,想發(fā)送數(shù)據(jù)以application/x-www-form-urlencoded類型的話,則可以簡單的調(diào)用.type()方法傳遞form參數(shù)就行,這里默認(rèn)是json,下面的請求將會postname=tj&pet=tobi內(nèi)容:

request.post('/user').type('form').send({name:'tj'}).send({pet:'tobi'}).end(callback)

注意:form是form-data和urlencoded的別名,為了向后兼容

設(shè)置Content-Type

常見的方案是使用.set()方法:

request.post('/user').set('Content-Type','application/json')

一個簡便的方法是調(diào)用.type()方法,傳遞一個規(guī)范的MIME名稱,包括type/subtype,或者一個簡單的后綴就像xml,json,png這樣,例如:

request.post('/user').type('application/json')request.post('/user').type('json')request.post('/user').type('png')

設(shè)置接受類型

跟.type()簡便方法一樣,這里也可以調(diào)用.accept()方法來設(shè)置接受類型,這個值將會被request.types所引用,支持傳遞一個規(guī)范的MIME名稱,包括type/subtype,或者一個簡單的后綴就像xml,json,png這樣,例如:

request.get('/user').accept('application/json')request.get('/user').accept('json')request.get('/user').accept('png')

查詢字符串

當(dāng)用.send(obj)方法來發(fā)送一個post請求,并且希望傳遞一些查詢字符串,可以調(diào)用.query()方法,比如向?format=json&dest=/login發(fā)送post請求:

request.post('/').query({format:'json'}).query({dest:'/login'}).send({post:'data',here:'wahoo'}).end(callback);

解析響應(yīng)內(nèi)容

superagent會解析一些常用的格式給請求者,當(dāng)前支持application/x-www-form-urlencoded,application/json,multipart/form-data.

JSON/Urlencoded

res.body是解析后的內(nèi)容對象,比如一個請求響應(yīng)'{"user":{"name":"tobi"}}'字符串,res.body.user.name將會返回tobi,同樣的,x-www-form-urlencoded格式的user[name]=tobi解析完的值,也是一樣的.

Multipart

nodejs客戶端通過Formidable模塊來支持multipart/form-data類型,當(dāng)解析一個multipart響應(yīng)時,res.files屬性就可以用.假設(shè)一個請求響應(yīng)下面的數(shù)據(jù):

--whoopContent-Disposition:attachment;name="image";filename="tobi.png"Content-Type:image/png...data here...--whoopContent-Disposition:form-data;name="name"Content-Type:text/plainTobi--whoop--

你將可以獲取到res.body.name名為’Tobi’,res.files.image為一個file對象,包括一個磁盤文件路徑,文件名稱,還有其它的文件屬性.

響應(yīng)屬性

響應(yīng)一般會提供很多有用的標(biāo)識以及屬性,都在response對象里,按照respone.text,解析后的response.body,頭字段,一些標(biāo)識的順序來排列.

Response text

res.text包含未解析前的響應(yīng)內(nèi)容,一般只在mime類型能夠匹配text/,json,x-www-form-urlencoding的情況下,默認(rèn)為nodejs客戶端提供,這是為了節(jié)省內(nèi)存.因為當(dāng)響應(yīng)以文件或者圖片大內(nèi)容的情況下影響性能.

Response body

跟請求數(shù)據(jù)自動序列化一樣,響應(yīng)數(shù)據(jù)也會自動的解析,當(dāng)為一個Content-Type定義一個解析器后,就能自動解析,默認(rèn)解析包含application/json和application/x-www-form-urlencoded,可以通過訪問res.body來訪問解析對象.

Response header fields

res.header包含解析之后的響應(yīng)頭數(shù)據(jù),鍵值都是node處理成小寫字母形式,比如res.header['content-length'].

Response Content-Type

Content-Type響應(yīng)頭字段是一個特列,服務(wù)器提供res.type來訪問它,默認(rèn)res.charset是空的,如果有的話,則自動填充,例如Content-Type值為text/html; charset=utf8,則res.type為text/html,res.charst為utf8.

Response status

響應(yīng)狀態(tài)標(biāo)識可以用來判斷請求是否成功,除此之外,可以用superagent來構(gòu)建理想的restful服務(wù)器,這些標(biāo)識目前定義為:

vartype=status/100|0;// status / classres.status=status;res.statusType=type;// basicsres.info=1==type;res.ok=2==type;res.clientError=4==type;res.serverError=5==type;res.error=4==type||5==type;// sugarres.accepted=202==status;res.noContent=204==status||1223==status;res.badRequest=400==status;res.unauthorized=401==status;res.notAcceptable=406==status;res.notFound=404==status;res.forbidden=403==status;

中止請求

可以通過req.abort()來中止請求.

請求超時

可以通過req.timeout()來定義超時時間,然后當(dāng)超時錯誤發(fā)生時,為了區(qū)別于別的錯誤,err.timeout屬性被定義為超時時間,注意,當(dāng)超時錯誤發(fā)生后,后續(xù)的請求都會被重定向.不是每個請求.

基礎(chǔ)驗證

nodejs客戶端可以通過兩種方式來達(dá)到驗證的目的,第一個是傳遞一個像這樣的url,user:pass:

request.get('http://tobi:learnboost[@local](/user/local)').end(callback);

第二種是調(diào)用.auth()方法:

request.get('http://local').auth('tobo','learnboost').end(callback);

跟隨重定向

默認(rèn)是向上跟隨5個重定向,不過可以通過調(diào)用.res.redirects(n)來設(shè)置個數(shù):

request.get('/some.png').redirects(2).end(callback);

管道數(shù)據(jù)

nodejs客戶端允許使用一個請求流來輸送數(shù)據(jù),比如請求一個文件作為輸出流:

varrequest=require('superagent'),fs=require('fs');varstream=fs.createReadStream('path/to/my.json');varreq=request.post('/somewhere');req.type('json');stream.pipe(req);

或者輸送一個響應(yīng)流到文件中:

varrequest=require('superagent'),fs=require('fs');varstream=fs.createWriteStream('path/to/my.json');varreq=request.get('/some.json');req.pipe(stream);

復(fù)合請求

superagent用來構(gòu)建復(fù)合請求非常不錯,提供了低級和高級的api方法.

低級的api是使用多個部分來表現(xiàn)一個文件或者字段,.part()方法返回一個新的部分,提供了跟request本身相似的api方法.

varreq=request.post('/upload');req.part().set('Content-Type','image/png').set('Content-Disposition','attachment; filename="myimage.png"').write('some image data').write('some more image data');req.part().set('Content-Disposition','form-data; name="name"').set('Content-Type','text/plain').write('tobi');req.end(callback);

附加文件

上面提及的高級api方法,可以通用.attach(name, [path], [filename])和.field(name, value)這兩種形式來調(diào)用.添加多個附件也比較簡單,只需要給附件提供自定義的文件名稱,同樣的基礎(chǔ)名稱也要提供.

request.post('/upload').attach('avatar','path/to/tobi.png','user.png').attach('image','path/to/loki.png').attach('file','path/to/jane.png').end(callback);

字段值

跟html的字段很像,你可以調(diào)用.field(name,value)方法來設(shè)置字段,假設(shè)你想上傳一個圖片的時候帶上自己的名稱和郵箱,那么你可以像下面寫的那樣:

request.post('/upload').field('user[name]','Tobi').field('user[email]','tobi[@learnboost](/user/learnboost).com').attach('image','path/to/tobi.png').end(callback);

壓縮

nodejs客戶端本身就提供了壓縮響應(yīng)內(nèi)容,所以你不需要做任何其它事情.

緩沖響應(yīng)

為了強(qiáng)迫緩沖res.text這樣的響應(yīng)內(nèi)容,可以調(diào)用req.buffer()方法,想取消默認(rèn)的文本緩沖響應(yīng)像text/plain,text/html這樣的,可以調(diào)用req.buffer(false)方法

當(dāng)緩沖res.buffered標(biāo)識提供了,那么就可以在一個回調(diào)函數(shù)里處理緩沖和沒緩沖的響應(yīng).

跨域資源共享

.withCredentials()方法可以激活發(fā)送原始cookie的能力,不過只有在Access-Control-Allow-Origin不是一個通配符(*),并且Access-Control-Allow-Credentials為’true’的情況下才行.

request.get('http://localhost:4001/').withCredentials().end(function(res){assert(200==res.status);assert('tobi'==res.text);next();})

異常處理

當(dāng)發(fā)送錯誤時,superagent首先會檢查回調(diào)函數(shù)的參數(shù)數(shù)量,當(dāng)err參數(shù)提供的話,參數(shù)就是兩個,如下:

request.post('/upload').attach('image','path/to/tobi.png').end(function(err,res){});

當(dāng)省略了回調(diào)函數(shù),或者回調(diào)只有一個參數(shù)的話,可以添加error事件的處理.

request.post('/upload').attach('image','path/to/tobi.png').on('error',handle).end(function(res){});

注意:superagent默認(rèn)情況下,對響應(yīng)4xx和5xx的認(rèn)為不是錯誤,例如當(dāng)響應(yīng)返回一個500或者403的時候,這些狀態(tài)信息可以通過res.error,res.status和其它的響應(yīng)屬性來查看,但是沒有任務(wù)的錯誤對象會傳遞到回調(diào)函數(shù)里或者emit一個error事件.正常的error事件只會發(fā)生在網(wǎng)絡(luò)錯誤,解析錯誤等.

當(dāng)產(chǎn)生一個4xx或者5xx的http錯誤響應(yīng),res.error提供了一個錯誤信息的對象,你可以通過檢查這個來做某些事情.

if(res.error){alert('oh no '+res.error.message);}else{alert('got '+res.status+' response');}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容