2015-08-16 32 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); 
} 

恶补一切都变成结构也似乎不喜欢我不明白为什么不是最好的方式

相关问题