11extern crate clap;
22extern crate hyper;
3+ extern crate url;
34
45use clap:: { Arg , ArgMatches , App } ;
5- use hyper:: Uri ;
6+ use hyper:: { Method , Request , Uri } ;
7+ use hyper:: header:: Authorization ;
8+ use hyper:: header;
69use std:: str:: FromStr ;
10+ use url:: { Url } ;
711
812fn main ( ) {
913 match ClientConfig :: from_cli_args ( ) {
10- Ok ( config) => println ! ( "arguments are good: {:?}" , config) ,
14+ Ok ( config) => {
15+ println ! ( "arguments are good: {:?}" , config) ;
16+ make_test_request ( & config) ;
17+ } ,
1118 Err ( ConfigError :: MissingAuth ) => println ! ( "Authorization info missing or incomplete. Either an API Key or a Username + Password must be provided" ) ,
1219 Err ( ConfigError :: MissingUrl ) => println ! ( "Missing the Base URL" ) ,
1320 Err ( ConfigError :: InvalidUrl ) => println ! ( "Invalid Base URL" ) ,
1421 } ;
1522}
1623
24+ fn make_test_request ( config : & ClientConfig ) -> ( ) {
25+ let uri = config. api_uri ( & [ "x" , "projects" ] ) ;
26+
27+ let mut req = Request :: new ( Method :: Get , uri) ;
28+ config. auth_info . apply_to ( & mut req) ;
29+ println ! ( "Request:\n {:?}" , req) ;
30+ }
31+
1732/// Connection information for Code Dx.
1833#[ derive( Debug ) ]
1934struct ClientConfig {
20- base_url : hyper :: Uri ,
35+ base_url : Url ,
2136 auth_info : ClientAuthInfo
2237}
2338
39+ impl ClientConfig {
40+ fn api_uri ( & self , segments : & [ & str ] ) -> Uri {
41+ let mut url = self . base_url . clone ( ) ;
42+
43+ // open a scope to borrow the url mutably
44+ {
45+ let mut url_segments = url. path_segments_mut ( )
46+ . expect ( "Can't apply a path to base-url" ) ;
47+ for segment in segments {
48+ url_segments. push ( segment) ;
49+ }
50+ }
51+ // now that the mutable borrow is done, we can use url again
52+
53+ Uri :: from_str ( & url. into_string ( ) )
54+ . expect ( "Somehow failed to convert a valid URL to a URI" )
55+ }
56+ }
57+
2458/// Authentication credentials for connecting to Code Dx.
2559/// Both "basic auth" (username + password) and "api key" are supported.
2660#[ derive( Debug ) ]
@@ -29,6 +63,26 @@ enum ClientAuthInfo {
2963 ApiKey ( String ) ,
3064}
3165
66+ impl ClientAuthInfo {
67+ fn apply_to < ' a > ( & self , request : & ' a mut Request ) {
68+ match * self {
69+ ClientAuthInfo :: Basic { ref username, ref password } => {
70+ let mut headers = request. headers_mut ( ) ;
71+ headers. set ( Authorization (
72+ header:: Basic {
73+ username : username. to_owned ( ) ,
74+ password : Some ( password. to_owned ( ) )
75+ }
76+ ) ) ;
77+ } ,
78+ ClientAuthInfo :: ApiKey ( ref key) => {
79+ let mut headers = request. headers_mut ( ) ;
80+ headers. set_raw ( "API-Key" , key. to_owned ( ) ) ;
81+ } ,
82+ }
83+ }
84+ }
85+
3286/// Things that can go wrong when parsing a `ClientConfig`
3387#[ derive( Debug ) ]
3488enum ConfigError {
@@ -82,7 +136,7 @@ impl ClientConfig {
82136
83137 let base_uri = match matches. value_of ( "base-url" ) {
84138 None => Err ( ConfigError :: MissingUrl ) ,
85- Some ( raw) => Uri :: from_str ( raw) . map_err ( |_| ConfigError :: InvalidUrl ) ,
139+ Some ( raw) => Url :: parse ( raw) . map_err ( |_| ConfigError :: InvalidUrl ) ,
86140 } ;
87141
88142 let client_auth_info = match matches. value_of ( "api-key" ) {
0 commit comments