Facebook最新Libra幣開發指南---接口服務器開發

在Libra Core中,官方提供了一個命令行工具,可以實現創建賬戶、挖礦和轉賬等基本操作,但是沒有提供Restful接口,使我們想要開發的應用系統,將區塊鏈邏輯移植到Libra Testnet上去。在本篇博文中,我們將利用Rust語言,將官方的命令行接口,改造成RESTful接口。由於我們只是臨時改造,相信官方的RESTful接口很快就會出現,因此我們在這裏僅使用最簡實現,實現一個單線程的Web服務器來完成這一工作。

最簡Web服務器

我們需要一個最簡單的Web服務器,來接收客戶端的請求,然後調用系統功能完成Libra Core中相關的區塊鏈操作操作。我們先開發一個獨立的應用,實現最基本的Web服務器功能,然後再將其集成到Libra Core的命令行工具中。
我們首先通過如下命令創建一個新工程:

cargo new libra_server --bin

我們創建一個名稱爲libra_server的工程,其爲可執行文件形式。上面的命令會在當前目錄下創建libra_server目錄,並創建libra_server/src/main.rs文件,這個文件就是整個項目的主程序文件。
下面我們創建一個Hello World的Web服務器:

use std::io::prelude::*;
use std::net::TcpStream;
use std::net::TcpListener;

fn main() {
    start_server();
}

fn start_server() {
    println!("Libra Server v0.0.2 Starting up ...");
    let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
    for stream in listener.incoming() {
        let stream = stream.unwrap();
        handle_connection(stream);
    }
}

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 512];
    stream.read(&mut buffer).unwrap();
    println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
    let contents = "Hello World!";
    let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);
    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

我們直接編譯運行程序:

cargo run

運行結果如下所示:
在這裏插入圖片描述
使用瀏覽器訪問如下地址:http://127.0.0.1:7878/account_list/88 ,會顯示Hello World信息,這就說明我們的Web服務器可以正常運行了。
下面我們在handle_connection方法中,求出cmd參數的值,根據cmd調用不同的處理函數,在這些函數中調用Libra Core的區塊鏈服務,解析區塊鏈服務的返回結果,最後再以Http響應的形式返回給客戶端。
我們要做的第一件事就是求出QueryString,代碼如下所示:

/**
* 獲取請求中的Query String,規定參數以?cmd=開頭
* @version v0.0.1 閆濤 2019.06.23
*/
fn get_query_string(request: &str) -> String {
    let pos = request.find("?cmd=");
    if pos <= Some(0) {
        return "Has no parameters in request".to_string();
    }
    let end_pos = request.find(" HTTP/1.1");
    return (&request[(pos.unwrap()+1)..end_pos.unwrap()]).to_string();
}

在這段代碼中,我們首先找到QueryString開始位置,如果沒找到則返回出錯信息。接着我們找到結束信息,最後我們截取出子字符串作爲QueryString返回。
在得到QueryString之後,我們需要找出參數cmd的值,這樣我們才能根據cmd參數的值調用對應的命令處理函數,如下所示:

/**
* 獲取請求cmd參數值
* @version v0.0.1 閆濤 2019.06.23
*/
fn get_cmd_param(query_string: String) -> String {
    let params: Vec<_> = query_string.split("&").collect();
    for param in params.iter() {
        println!("item: {}!", param);
        if param.find("cmd=") >= Some(0) {
            let cmd = &param[4..];
            return cmd.to_string();
        }
    }
    return "".to_string();
}

接下來我們定義生成賬戶的命令處理函數,如下所示:

/**
* 生成賬戶命令處理函數
* @version v0.0.1 閆濤 2019.06.23
*/
fn handle_account_create(_params: Vec<&str>) -> String {
    println!("生成新賬戶!");
    let rst: String = String::from("create account: 0");
    return rst;
}

實際中,這個函數需要調用Libra Core來創建賬戶,我們在這裏先簡單的返回一個字符串,在下一篇文章中我們再來具體講怎麼調用Libra Core服務以及解析響應結果。
接下來我們看handle_connection方法,這時這個方法的邏輯就變爲接到一個請求後,首先得到QueryString,然後從QueryString得到cmd參數,然後根據cmd的值調用對應的命令處理函數,如下所示:

fn handle_connection(mut stream: TcpStream) {
    let mut contents: String = String::from("Hello World!");
    let mut buffer = [0; 1024];
    // 獲取請求信息
    stream.read(&mut buffer).unwrap();
    println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
    let request = String::from_utf8_lossy(&buffer[..]);
    // 不處理請求網站圖標請求
    if request.find("GET /favicon.ico HTTP/1.1") >= Some(0) {
        return ;
    }
    // 請出請求中的query string
    let query_string = &get_query_string(&request);
    println!("query_string:{}", query_string);
    let cmd = get_cmd_param(query_string.to_string());
    println!("接收到命令:cmd={}!", cmd);
    let params: Vec<_> = query_string.split("&").collect();
    if cmd.find("account_create")>=Some(0) {
        contents = handle_account_create(params);
    } else if cmd.find("account_list")>=Some(0) {
        contents = handle_account_list(params);
    }
    let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);
    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

我們可以按照這種方式,將下列命令先以佔位符的形式寫出來,我在這裏就不重複貼代碼了,在下一篇文章中,我們將對每個命令,學習怎樣向Libra Core發送命令,以及怎樣解析命令的返回結果。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章