本文目錄:
- 簡(jiǎn)介
- 快速通道
- 翻譯--curl庫(kù)
- easy模塊
- multi模塊
1. 簡(jiǎn)介
雖然這個(gè)系列是屬于Rust使用庫(kù)翻譯計(jì)劃的系列之一,但是由于該庫(kù)官網(wǎng)提供的使用文檔幾乎等于沒(méi)有,所以本文實(shí)際上是簡(jiǎn)單翻譯一下api文檔后小生自己寫(xiě)的使用文檔,Orz。
2. 快速通道
所有的翻譯文章將集中導(dǎo)航于:Rust常用庫(kù)翻譯計(jì)劃
3.翻譯——curl庫(kù)
curl庫(kù)github快速通道
配套翻譯之curl中文api
該庫(kù)主要實(shí)現(xiàn)了網(wǎng)絡(luò)通信中作為客戶(hù)端會(huì)使用到的幾乎所有的函數(shù),其中常用的遇到的需求,幾乎都可以使用easy模塊來(lái)實(shí)現(xiàn)。在easy模塊中總共定義了八個(gè)Struct,十個(gè)枚舉以及數(shù)不清的函數(shù),其中函數(shù)按照功能大概可以分為以下幾類(lèi):
- 配置類(lèi)函數(shù)
- 構(gòu)建類(lèi)函數(shù)
- 信息獲取類(lèi)
- 純粹操作類(lèi)
- 回調(diào)類(lèi)函數(shù)
其中配置類(lèi)函數(shù)占了絕大多數(shù),這類(lèi)函數(shù)主要用于設(shè)置發(fā)送請(qǐng)求時(shí)的請(qǐng)求頭、驗(yàn)證信息等等一系列的配置選項(xiàng),幾乎全部是返回 Result<(), Error>,所以幾乎等于沒(méi)有返回值,直接每個(gè)函數(shù)調(diào)用后unwrap一下就可以了。構(gòu)建類(lèi)函數(shù)主要就是new和transfer,返回一個(gè)結(jié)構(gòu)體實(shí)例。信息獲取類(lèi)函數(shù)即調(diào)用后獲取頭信息之類(lèi)的相關(guān)信息的函數(shù).純粹操作類(lèi)的函數(shù)即類(lèi)似于perform這類(lèi),調(diào)用后會(huì)直接將請(qǐng)求發(fā)出,返回?zé)o意義的Result<(), Error>,也不需要傳入?yún)?shù),只是單純的提示系統(tǒng)該執(zhí)行某個(gè)操作了。最后回調(diào)類(lèi)函數(shù)即使類(lèi)似write_function這類(lèi),接受一個(gè)閉包作為參數(shù),在執(zhí)行固定操作完成后便會(huì)調(diào)用該閉包函數(shù)。
示例一:簡(jiǎn)單入門(mén)
extern crate curl;
use curl::easy::Easy;
use std::io::{
Write,
stdout
};
fn main() {
let mut easy = Easy::new();
easy.url("http://juejin.im").unwrap();
easy.write_function(|data| {
Ok(stdout().write(data).unwrap())
}).unwrap();
easy.perform().unwrap();
}
這個(gè)例子中使用了curl庫(kù),并且使用了easy模塊的命名空間,首先使用new函數(shù)新建了一個(gè)easy實(shí)例,然后通過(guò)url函數(shù)設(shè)置了訪問(wèn)的主機(jī)地址,然后繼續(xù)設(shè)置了拉取到數(shù)據(jù)后的回調(diào)函數(shù)write_function,傳入一個(gè)閉包函數(shù),參數(shù)data即為服務(wù)器返回的數(shù)據(jù),該閉包返回一個(gè)Result<usize, WriteError> + Send + 'static,所以直接一條語(yǔ)句順便輸出了服務(wù)器返回的data,然后調(diào)用perform函數(shù),讓請(qǐng)求正式發(fā)出。結(jié)果如下:
可以看出確實(shí)獲取到了服務(wù)器的返回的數(shù)據(jù),不過(guò)由于服務(wù)器做了3xx重定向,導(dǎo)致拉取到了一個(gè)無(wú)意義的重定向以前的頁(yè)面,所以要設(shè)置讓系統(tǒng)跟隨頭文件的設(shè)置一起跳轉(zhuǎn)
示例二:跟隨重定向
extern crate curl;
use curl::easy::Easy;
use std::io::{
Write,
stdout
};
fn main() {
let mut easy = Easy::new();
easy.nobody(true).unwrap();
easy.url("http://juejin.im").unwrap();
easy.follow_location(true).unwrap();
easy.write_function(|data| {
Ok(stdout().write(data).unwrap())
}).unwrap();
easy.perform().unwrap();
println!("last_Url:{:?}",easy.effective_url().unwrap().unwrap());
println!("response_code:{:?}",easy.response_code().unwrap());
println!("http_connectcode:{:?}",easy.http_connectcode().unwrap());
println!("filetime:{:?}",easy.filetime().unwrap());
println!("total_time:{:?}",easy.total_time().unwrap());
}
這個(gè)例子中,通過(guò)follow_location配置設(shè)置了跟隨重定向跳轉(zhuǎn),所以可以獲取到掘金首頁(yè)的html,不過(guò)由于內(nèi)容過(guò)大,影響觀看,所以這里調(diào)用了nobody函數(shù),配置不返回body體,然后順便在結(jié)束后打印出一部分相關(guān)的信息。
示例三:關(guān)于回調(diào)函數(shù)
fn main() {
let mut easy = Easy::new();
easy.url("http://www.yzyxw.online/api/round/getQuestion").unwrap();
easy.post(true).unwrap();
//easy.nobody(true).unwrap();
easy.header_function(|data| {
print!("header: {}", str::from_utf8(data).unwrap());
true
}).unwrap();
easy.write_function(|data| {
Ok(stdout().write(data).unwrap())
}).unwrap();
easy.read_function(|into| {
Ok(stdin().read(into).unwrap())
}).unwrap();
easy.perform().unwrap();
}
這里分別實(shí)現(xiàn)了讀寫(xiě)和頭三個(gè)回調(diào),其中頭回調(diào)函數(shù)會(huì)在獲得http頭的是后將頭信息作為參數(shù)傳入閉包中,這里打印出了頭信息,write回調(diào)會(huì)在獲得服務(wù)器返回?cái)?shù)據(jù)后調(diào)用閉包,將服務(wù)器返回?cái)?shù)據(jù)傳入閉包參數(shù)中。特別說(shuō)明:如果設(shè)置了show_header(true),那么返回信息中會(huì)同時(shí)包含頭信息。。關(guān)于讀回調(diào),主要是用于設(shè)置訪問(wèn)服務(wù)器時(shí)攜帶數(shù)據(jù)的方式之一,將標(biāo)準(zhǔn)輸入數(shù)據(jù)拷貝僅回調(diào)的參數(shù)中,該數(shù)據(jù)將會(huì)被攜帶至服務(wù)器,為了能攜帶數(shù)據(jù),這里將訪問(wèn)模式這是成了post。
當(dāng)然,由于這里的操作都是從標(biāo)準(zhǔn)輸入輸出中讀取的,在回調(diào)閉包中,對(duì)外部變量的借用是不被允許的,在回調(diào)外定義一個(gè)數(shù)據(jù),在讀回調(diào)中使用時(shí)不允許的,就像這樣:
{% codeblock lang:rust %}
let mut info = &b"tasdasdadad"[..];
easy.read_function(|data| {
Ok(info.read(data).unwrap())
}).unwrap();
easy.perform().unwrap();
{% endcodeblock %}
結(jié)果:
對(duì)于這種情況,該庫(kù)引入了Transfer,使用transfer()會(huì)返回一個(gè)transfer實(shí)例,該實(shí)例擁有著對(duì)easy實(shí)例的一個(gè)可變借用,所以在調(diào)用該函數(shù)后一直到transfer生命周期結(jié)束前都不可以再使用easy句柄來(lái)進(jìn)行一些操作,所以可以選擇用大括弧將對(duì)應(yīng)語(yǔ)句段包括起來(lái),人為控制其生命周期。transfer同樣實(shí)現(xiàn)了easy中所有的回調(diào)函數(shù),用transfer可以實(shí)現(xiàn)上述不能實(shí)現(xiàn)的功能:
關(guān)于Transfer:
fn main() {
let mut easy = Easy::new();
easy.url("http://www.yzyxw.online/api/round/getQuestion").unwrap();
easy.post(true).unwrap();
//easy.nobody(true).unwrap();
easy.header_function(|data| {
print!("header: {}", str::from_utf8(data).unwrap());
true
}).unwrap();
easy.write_function(|data| {
Ok(stdout().write(data).unwrap())
}).unwrap();
let mut info = &b"tasdasdadad"[..];
let mut tran=easy.transfer();
tran.read_function(|data| {
Ok(info.read(data).unwrap())
}).unwrap();
tran.perform().unwrap();
}
這時(shí)便可以在閉包內(nèi)獲取外部上下文引用
偽結(jié)語(yǔ)
在easy模塊中共定義了七個(gè)回調(diào)設(shè)置函數(shù),使用方式大同小異,剩下便是相關(guān)ssl驗(yàn)證,代理設(shè)置等等一系列的操作,基本全是通過(guò)一系列的設(shè)置函數(shù)實(shí)現(xiàn)的,就不一一贅述了。感興趣的pong友們可以參考我簡(jiǎn)單翻譯的api傳送門(mén),也可以參考官網(wǎng)比較詳盡的英文api傳送門(mén).
對(duì)于該庫(kù)另一個(gè)模塊multi將在本文的下篇部分詳細(xì)解釋?zhuān)瑫r(shí)也將整合各個(gè)api制作一份綜合實(shí)例給喜歡Rust這門(mén)目前比較小眾的語(yǔ)言的pong友們。
另外,更多Rust庫(kù)翻譯請(qǐng)關(guān)注Rust實(shí)用庫(kù)翻譯計(jì)劃