@@ -89,6 +89,7 @@ impl Transcription<'_> {
8989}
9090
9191#[ derive( Clone , PartialEq , Eq , PartialOrd , Ord ) ]
92+ /// A string wrapper that redacts its contents when formatted with `Debug`.
9293pub ( crate ) struct RedactedString ( pub String ) ;
9394
9495impl fmt:: Debug for RedactedString {
@@ -105,13 +106,35 @@ impl Deref for RedactedString {
105106 }
106107}
107108
109+ /// Authentication method for Deepgram API requests.
110+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
111+ pub ( crate ) enum AuthMethod {
112+ /// Use an API key with "Token" prefix (e.g., "Token dg_xxx").
113+ /// This is for permanent API keys created in the Deepgram console.
114+ ApiKey ( RedactedString ) ,
115+
116+ /// Use a temporary token with "Bearer" prefix (e.g., "Bearer dg_xxx").
117+ /// This is for temporary tokens obtained via token-based authentication.
118+ TempToken ( RedactedString ) ,
119+ }
120+
121+ impl AuthMethod {
122+ /// Get the authorization header value for this authentication method.
123+ pub ( crate ) fn header_value ( & self ) -> String {
124+ match self {
125+ AuthMethod :: ApiKey ( key) => format ! ( "Token {}" , key. 0 ) ,
126+ AuthMethod :: TempToken ( token) => format ! ( "Bearer {}" , token. 0 ) ,
127+ }
128+ }
129+ }
130+
108131/// A client for the Deepgram API.
109132///
110133/// Make transcriptions requests using [`Deepgram::transcription`].
111134#[ derive( Debug , Clone ) ]
112135pub struct Deepgram {
113136 #[ cfg_attr( not( feature = "listen" ) , allow( unused) ) ]
114- api_key : Option < RedactedString > ,
137+ auth : Option < AuthMethod > ,
115138 #[ cfg_attr( not( feature = "listen" ) , allow( unused) ) ]
116139 base_url : Url ,
117140 #[ cfg_attr( not( feature = "listen" ) , allow( unused) ) ]
@@ -200,11 +223,20 @@ impl Deepgram {
200223 ///
201224 /// Errors under the same conditions as [`reqwest::ClientBuilder::build`].
202225 pub fn new < K : AsRef < str > > ( api_key : K ) -> Result < Self > {
203- let api_key = Some ( api_key. as_ref ( ) . to_owned ( ) ) ;
226+ let auth = AuthMethod :: ApiKey ( RedactedString ( api_key. as_ref ( ) . to_owned ( ) ) ) ;
204227 // This cannot panic because we are converting a static value
205228 // that is known-good.
206229 let base_url = DEEPGRAM_BASE_URL . try_into ( ) . unwrap ( ) ;
207- Self :: inner_constructor ( base_url, api_key)
230+ Self :: inner_constructor ( base_url, Some ( auth) )
231+ }
232+
233+ /// Construct a new Deepgram client with a temporary token.
234+ ///
235+ /// This uses the "Bearer" prefix for authentication, suitable for temporary tokens.
236+ pub fn with_temp_token < T : AsRef < str > > ( temp_token : T ) -> Result < Self > {
237+ let auth = AuthMethod :: TempToken ( RedactedString ( temp_token. as_ref ( ) . to_owned ( ) ) ) ;
238+ let base_url = DEEPGRAM_BASE_URL . try_into ( ) . unwrap ( ) ;
239+ Self :: inner_constructor ( base_url, Some ( auth) )
208240 }
209241
210242 /// Construct a new Deepgram client with the specified base URL.
@@ -281,10 +313,23 @@ impl Deepgram {
281313 K : AsRef < str > ,
282314 {
283315 let base_url = base_url. try_into ( ) . map_err ( |_| DeepgramError :: InvalidUrl ) ?;
284- Self :: inner_constructor ( base_url, Some ( api_key. as_ref ( ) . to_owned ( ) ) )
316+ let auth = AuthMethod :: ApiKey ( RedactedString ( api_key. as_ref ( ) . to_owned ( ) ) ) ;
317+ Self :: inner_constructor ( base_url, Some ( auth) )
318+ }
319+
320+ /// Construct a new Deepgram client with the specified base URL and temp token.
321+ pub fn with_base_url_and_temp_token < U , T > ( base_url : U , temp_token : T ) -> Result < Self >
322+ where
323+ U : TryInto < Url > ,
324+ U :: Error : std:: fmt:: Debug ,
325+ T : AsRef < str > ,
326+ {
327+ let base_url = base_url. try_into ( ) . map_err ( |_| DeepgramError :: InvalidUrl ) ?;
328+ let auth = AuthMethod :: TempToken ( RedactedString ( temp_token. as_ref ( ) . to_owned ( ) ) ) ;
329+ Self :: inner_constructor ( base_url, Some ( auth) )
285330 }
286331
287- fn inner_constructor ( base_url : Url , api_key : Option < String > ) -> Result < Self > {
332+ fn inner_constructor ( base_url : Url , auth : Option < AuthMethod > ) -> Result < Self > {
288333 static USER_AGENT : & str = concat ! (
289334 env!( "CARGO_PKG_NAME" ) ,
290335 "/" ,
@@ -297,16 +342,17 @@ impl Deepgram {
297342 }
298343 let authorization_header = {
299344 let mut header = HeaderMap :: new ( ) ;
300- if let Some ( api_key) = & api_key {
301- if let Ok ( value) = HeaderValue :: from_str ( & format ! ( "Token {}" , api_key) ) {
345+ if let Some ( auth) = & auth {
346+ let header_value = auth. header_value ( ) ;
347+ if let Ok ( value) = HeaderValue :: from_str ( & header_value) {
302348 header. insert ( "Authorization" , value) ;
303349 }
304350 }
305351 header
306352 } ;
307353
308354 Ok ( Deepgram {
309- api_key : api_key . map ( RedactedString ) ,
355+ auth ,
310356 base_url,
311357 client : reqwest:: Client :: builder ( )
312358 . user_agent ( USER_AGENT )
@@ -334,3 +380,42 @@ async fn send_and_translate_response<R: DeserializeOwned>(
334380 } ) ,
335381 }
336382}
383+
384+ #[ cfg( test) ]
385+ mod tests {
386+ use super :: * ;
387+
388+ #[ test]
389+ fn test_auth_method_header_value ( ) {
390+ let api_key = AuthMethod :: ApiKey ( RedactedString ( "test_api_key" . to_string ( ) ) ) ;
391+ assert_eq ! ( api_key. header_value( ) , "Token test_api_key" . to_string( ) ) ;
392+
393+ let temp_token = AuthMethod :: TempToken ( RedactedString ( "test_temp_token" . to_string ( ) ) ) ;
394+ assert_eq ! (
395+ temp_token. header_value( ) ,
396+ "Bearer test_temp_token" . to_string( )
397+ ) ;
398+ }
399+
400+ #[ test]
401+ fn test_deepgram_new_with_temp_token ( ) {
402+ let client = Deepgram :: with_temp_token ( "test_temp_token" ) . unwrap ( ) ;
403+ assert_eq ! (
404+ client. auth,
405+ Some ( AuthMethod :: TempToken ( RedactedString (
406+ "test_temp_token" . to_string( )
407+ ) ) )
408+ ) ;
409+ }
410+
411+ #[ test]
412+ fn test_deepgram_new_with_api_key ( ) {
413+ let client = Deepgram :: new ( "test_api_key" ) . unwrap ( ) ;
414+ assert_eq ! (
415+ client. auth,
416+ Some ( AuthMethod :: ApiKey ( RedactedString (
417+ "test_api_key" . to_string( )
418+ ) ) )
419+ ) ;
420+ }
421+ }
0 commit comments