【问题标题】:Most idiomatic way to handle API keys in a Rust library?在 Rust 库中处理 API 密钥的最惯用方式?
【发布时间】:2015-08-16 06:20:47
【问题描述】:

我正在为一个接受两个 API 密钥的 API 编写 Rust 绑定。有很多方法可以做到这一点。我特别不想给用户带来诸如

之类的请求的负担
myapi::requestThing(firstApiKey, SecondApiKey,...)

我想让用户只传递一次 API 密钥并让它记住它。问题是我试图在功能上做到这一点,并且将所有内容都塞进一个结构中似乎也不是最好的方法。

【问题讨论】:

    标签: binding rust idioms


    【解决方案1】:

    您绝对不想拥有某种神奇地存储的全局配置。这将防止多个用户在同一进程中同时使用 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);
    }
    

    把所有东西都塞进一个结构似乎也不是最好的方法

    我不明白为什么不。

    【讨论】:

      猜你喜欢
      • 2016-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-26
      相关资源
      最近更新 更多