Rust 翻譯計劃——網路程式設計 curl 庫 (上)

被叫做可兒的逸軒發表於2017-06-07

本文目錄:

  1. 簡介
  2. 快速通道
  3. 翻譯--curl庫
    • easy模組
    • multi模組

1. 簡介

雖然這個系列是屬於Rust使用庫翻譯計劃的系列之一,但是由於該庫官網提供的使用文件幾乎等於沒有,所以本文實際上是簡單翻譯一下api文件後小生自己寫的使用文件,Orz。

2. 快速通道

所有的翻譯文章將集中導航於:Rust常用庫翻譯計劃

3.翻譯——curl庫

curl庫github快速通道
配套翻譯之curl中文api

該庫主要實現了網路通訊中作為客戶端會使用到的幾乎所有的函式,其中常用的遇到的需求,幾乎都可以使用easy模組來實現。在easy模組中總共定義了八個Struct,十個列舉以及數不清的函式,其中函式按照功能大概可以分為以下幾類:

  • 配置類函式
  • 構建類函式
  • 資訊獲取類
  • 純粹操作類
  • 回撥類函式

其中配置類函式佔了絕大多數,這類函式主要用於設定傳送請求時的請求頭、驗證資訊等等一系列的配置選項,幾乎全部是返回 Result<(), Error>,所以幾乎等於沒有返回值,直接每個函式呼叫後unwrap一下就可以了。構建類函式主要就是new和transfer,返回一個結構體例項。資訊獲取類函式即呼叫後獲取頭資訊之類的相關資訊的函式.純粹操作類的函式即類似於perform這類,呼叫後會直接將請求發出,返回無意義的Result<(), Error>,也不需要傳入引數,只是單純的提示系統該執行某個操作了。最後回撥類函式即使類似write_function這類,接受一個閉包作為引數,在執行固定操作完成後便會呼叫該閉包函式。

示例一:簡單入門

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();
}複製程式碼

這個例子中使用了curl庫,並且使用了easy模組的名稱空間,首先使用new函式新建了一個easy例項,然後通過url函式設定了訪問的主機地址,然後繼續設定了拉取到資料後的回撥函式write_function,傳入一個閉包函式,引數data即為伺服器返回的資料,該閉包返回一個Result + Send + 'static,所以直接一條語句順便輸出了伺服器返回的data,然後呼叫perform函式,讓請求正式發出。結果如下:

Rust 翻譯計劃——網路程式設計 curl 庫 (上)
upload successful

可以看出確實獲取到了伺服器的返回的資料,不過由於伺服器做了3xx重定向,導致拉取到了一個無意義的重定向以前的頁面,所以要設定讓系統跟隨標頭檔案的設定一起跳轉

示例二:跟隨重定向

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());
}複製程式碼

這個例子中,通過follow_location配置設定了跟隨重定向跳轉,所以可以獲取到掘金首頁的html,不過由於內容過大,影響觀看,所以這裡呼叫了nobody函式,配置不返回body體,然後順便在結束後列印出一部分相關的資訊。

Rust 翻譯計劃——網路程式設計 curl 庫 (上)
upload successful

示例三:關於回撥函式

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();

}複製程式碼

這裡分別實現了讀寫和頭三個回撥,其中頭回撥函式會在獲得http頭的是後將頭資訊作為引數傳入閉包中,這裡列印出了頭資訊,write回撥會在獲得伺服器返回資料後呼叫閉包,將伺服器返回資料傳入閉包引數中。特別說明:如果設定了show_header(true),那麼返回資訊中會同時包含頭資訊。。關於讀回撥,主要是用於設定訪問伺服器時攜帶資料的方式之一,將標準輸入資料拷貝僅回撥的引數中,該資料將會被攜帶至伺服器,為了能攜帶資料,這裡將訪問模式這是成了post。

當然,由於這裡的操作都是從標準輸入輸出中讀取的,在回撥閉包中,對外部變數的借用是不被允許的,在回撥外定義一個資料,在讀回撥中使用時不允許的,就像這樣:
{% codeblock lang:rust %}
let mut info = &b"tasdasdadad"[..];
easy.read_function(|data| {
Ok(info.read(data).unwrap())
}).unwrap();
easy.perform().unwrap();
{% endcodeblock %}
結果:

Rust 翻譯計劃——網路程式設計 curl 庫 (上)
upload successful

對於這種情況,該庫引入了Transfer,使用transfer()會返回一個transfer例項,該例項擁有著對easy例項的一個可變借用,所以在呼叫該函式後一直到transfer生命週期結束前都不可以再使用easy控制程式碼來進行一些操作,所以可以選擇用大括弧將對應語句段包括起來,人為控制其生命週期。transfer同樣實現了easy中所有的回撥函式,用transfer可以實現上述不能實現的功能:

關於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();

}複製程式碼

這時便可以在閉包內獲取外部上下文引用

偽結語

在easy模組中共定義了七個回撥設定函式,使用方式大同小異,剩下便是相關ssl驗證,代理設定等等一系列的操作,基本全是通過一系列的設定函式實現的,就不一一贅述了。感興趣的pong友們可以參考我簡單翻譯的api傳送門,也可以參考官網比較詳盡的英文api傳送門.
對於該庫另一個模組multi將在本文的下篇部分詳細解釋,同時也將整合各個api製作一份綜合例項給喜歡Rust這門目前比較小眾的語言的pong友們。
另外,更多Rust庫翻譯請關注Rust實用庫翻譯計劃

相關文章