2015-08-16 68 views
2

我正在爲使用兩個API密鑰的API編寫Rust綁定。有很多方法可以實現這一點。我特別不希望負擔發出請求像最常用的方式來處理Rust庫中的API密鑰?

myapi::requestThing(firstApiKey, SecondApiKey,...) 

我想有用戶只能在API密鑰傳遞一次,並把它記住它的用戶。問題是我試圖在功能上做到這一點,並將所有東西塞進一個結構中,似乎也不是最好的方法。

回答

5

你完全不想擁有某種神奇的全局配置。這將阻止多個用戶在同一進程中同時使用該API。

我會爲API端點構建一個構建器。這可以爲API URL提供默認值,也可以從環境變量中獲取API密鑰。您也可以通過編程方式覆蓋URL或密鑰。

use std::collections::HashMap; 

struct ApiEndpoint { 
    url: String, 
    api_key_1: String, 
    api_key_2: String, 
} 

impl ApiEndpoint { 
    fn add_money_to_account(&self, cents: u64) { 
     println!("Adding {} cents. Making a request to {} ({}, {})", cents, self.url, self.api_key_1, self.api_key_2); 
    } 
} 

struct ApiBuilder { 
    url: Option<String>, 
    api_key_1: Option<String>, 
    api_key_2: Option<String>, 
} 

impl ApiBuilder { 
    fn new() -> ApiBuilder { 
     ApiBuilder { 
      url: None, 
      api_key_1: None, 
      api_key_2: None, 
     } 
    } 

    fn url(mut self, url: &str) -> ApiBuilder { 
     self.url = Some(url.into()); 
     self 
    } 

    fn api_key_1(mut self, api_key_1: &str) -> ApiBuilder { 
     self.api_key_1 = Some(api_key_1.into()); 
     self 
    } 

    fn api_key_2(mut self, api_key_2: &str) -> ApiBuilder { 
     self.api_key_2 = Some(api_key_2.into()); 
     self 
    } 

    fn build(self) -> ApiEndpoint { 
     let mut env_vars: HashMap<_, _> = std::env::vars().collect(); 

     ApiEndpoint { 
      url: self.url.unwrap_or_else(|| "http://example.com/default".into()), 
      api_key_1: self.api_key_1.or_else(|| env_vars.remove("MYLIB_ENV_VAR_1")).unwrap(), 
      api_key_2: self.api_key_2.or_else(|| env_vars.remove("MYLIB_ENV_VAR_2")).unwrap(), 
     } 
    } 
} 

fn main() { 
    let endpoint = 
     ApiBuilder::new() 
     .url("https://test.example.com") 
     .api_key_1("SEEKRET") 
     .api_key_2("PASSWORD") 
     .build(); 

    endpoint.add_money_to_account(500); 
} 

惡補一切都變成結構也似乎不喜歡我不明白爲什麼不是最好的方式

相關問題