From 1ec30751f5fca94b3e1c11c182c817d2d37a40a7 Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 15:17:41 +0200 Subject: [PATCH 1/7] Move to hyper --- Cargo.toml | 4 +- src/lib.rs | 162 ++++++++++++++++++++++++++--------------------------- 2 files changed, 81 insertions(+), 85 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 339ca20..729c7dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,6 @@ exclude = ["examples/*", "tests/*"] keywords = ["firebase", "rest", "api"] [dependencies] -url = "0.2.35" -curl = "0.2.10" +hyper = "0.9.5" +url = "1.1.0" rustc-serialize = "0.3.15" diff --git a/src/lib.rs b/src/lib.rs index 113799c..f9ec938 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,19 +3,19 @@ Please have a look at the ```Firebase``` struct to get started. */ -extern crate curl; +extern crate hyper; extern crate url; extern crate rustc_serialize; use std::str; use std::borrow::Cow; use std::collections::HashMap; -use std::sync::Arc; use std::thread; use std::thread::JoinHandle; - -use curl::http; +use hyper::Client; +use hyper::status::StatusCode; use url::Url; +use std::io::{self, Read}; use rustc_serialize::Decodable; use rustc_serialize::json; @@ -24,7 +24,7 @@ pub use rustc_serialize::json::{Json, BuilderError, DecoderError}; /// A Firebase instance to manage data. #[derive(Clone)] pub struct Firebase { - url: Arc, + url: Url, } // TODO: Change all instances of &str to Into @@ -44,13 +44,13 @@ impl Firebase { /// will be returned. pub fn new(url: &str) -> Result { let url = try!( parse(&url) ); - if url.scheme != "https" { + if url.scheme() != "https" { return Err(ParseError::UrlIsNotHTTPS); } try!( unwrap_path(&url) ); Ok(Firebase { - url: Arc::new(url), + url: url, }) } @@ -60,12 +60,11 @@ impl Firebase { /// will be returned. /// - If a url cannot be parsed into a valid url then a ```Err(ParseError::Parser(url::ParseError)``` /// will be returned. - pub fn from_url(url: &Url) -> Result { - let url = url.clone(); + pub fn from_url(url: Url) -> Result { try!( unwrap_path(&url) ); Ok(Firebase { - url: Arc::new(url), + url: url, }) } @@ -85,16 +84,15 @@ impl Firebase { /// will be returned. pub fn authed(url: &str, auth_token: &str) -> Result { let mut url = try!( parse(&url) ); - if url.scheme != "https" { + if url.scheme() != "https" { return Err(ParseError::UrlIsNotHTTPS); } try!( unwrap_path(&url) ); - let opts = vec![ (AUTH, auth_token) ]; - url.set_query_from_pairs(opts.into_iter()); + url.query_pairs_mut().append_pair(AUTH, auth_token).finish(); Ok(Firebase { - url: Arc::new(url), + url: url, }) } @@ -112,14 +110,14 @@ impl Firebase { /// // A new reference to /friends/yasha/messages /// let messages = yasha.at("messages").unwrap(); pub fn at(&self, add_path: &str) -> Result { - let mut url = (*self.url).clone(); + let mut url = self.url.clone(); { // Add path to original path, already checked for path. - let mut path = url.path_mut().unwrap(); // Remove .json from the old path's end. - if let Some(end) = path.pop() { - path.push(end.trim_right_matches(".json").to_string()); - } + let last = url.path_segments().expect("last segment").last().unwrap().to_string(); + let mut path = url.path_segments_mut().expect("path segments"); + path.pop().push(last.trim_right_matches(".json")); + let add_path = add_path.trim_matches('/'); let add_path = if !add_path.ends_with(".json") { Cow::Owned(add_path.to_string() + ".json") @@ -127,13 +125,13 @@ impl Firebase { Cow::Borrowed(add_path) }; - for component in add_path.split("/").into_iter() { - path.push(component.to_string()); + for component in add_path.split("/") { + path.push(component); } } Ok(Firebase { - url: Arc::new(url), + url: url, }) } @@ -161,13 +159,13 @@ impl Firebase { /// }); /// ``` pub fn ops(&self, opts: &FbOps) -> FirebaseParams { - FirebaseParams::from_ops(&self.url, opts) + FirebaseParams::from_ops(self.url.clone(), opts) } /// Returns the current URL as a string that will be used /// to make the REST call when talking to Firebase. - pub fn get_url(&self) -> String { - self.url.serialize() + pub fn get_url(&self) -> &str { + self.url.as_str() } /// Gets data from Firebase. @@ -245,35 +243,35 @@ impl Firebase { /// }); pub fn get_async(&self, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static { - Firebase::request_url_async(&self.url, Method::GET, None, callback) + Firebase::request_url_async(self.url.clone(), Method::GET, None, callback) } /// Asynchronous version of the set method, takes a callback /// and returns a handle to the thread making the request to Firebase. pub fn set_async(&self, data: S, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static, S: Into { - Firebase::request_url_async(&self.url, Method::PUT, Some(data.into()), callback) + Firebase::request_url_async(self.url.clone(), Method::PUT, Some(data.into()), callback) } /// Asynchronous version of the push method, takes a callback /// and returns a handle to the thread making the request to Firebase. pub fn push_async(&self, data: S, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static, S: Into { - Firebase::request_url_async(&self.url, Method::POST, Some(data.into()), callback) + Firebase::request_url_async(self.url.clone(), Method::POST, Some(data.into()), callback) } /// Asynchronous version of the update method, takes a callback /// and returns a handle to the thread making the request to Firebase. pub fn update_async(&self, data: S, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static, S: Into { - Firebase::request_url_async(&self.url, Method::PATCH, Some(data.into()), callback) + Firebase::request_url_async(self.url.clone(), Method::PATCH, Some(data.into()), callback) } /// Asynchronous version of the remove method, takes a callback /// and returns a handle to the thread making the request to Firebase. pub fn remove_async(&self, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static { - Firebase::request_url_async(&self.url, Method::DELETE, None, callback) + Firebase::request_url_async(self.url.clone(), Method::DELETE, None, callback) } /// Creates a ```FirebaseParams``` instance, a Firebase struct that only @@ -333,48 +331,40 @@ impl Firebase { #[inline] fn request(&self, method: Method, data: Option<&str>) -> Result { - Firebase::request_url(&self.url, method, data) + Firebase::request_url(self.url.clone(), method, data) } - fn request_url(url: &Url, method: Method, data: Option<&str>) -> Result { - let mut handler = http::handle(); + fn request_url(url: Url, method: Method, data: Option<&str>) -> Result { + let client = Client::new(); let req = match method { - Method::GET => handler.get( url), - Method::POST => handler.post( url, data.unwrap()), - Method::PUT => handler.put( url, data.unwrap()), - Method::PATCH => handler.patch( url, data.unwrap()), - Method::DELETE => handler.delete(url), + Method::GET => client.get(url), + Method::POST => client.post(url).body(data.expect("data")), + Method::PUT => client.put(url).body(data.expect("data")), + Method::PATCH => client.patch(url).body(data.expect("data")), + Method::DELETE => client.delete(url), }; - let res = match req.exec() { - Ok(r) => r, - Err(e) => return Err(ReqErr::NetworkErr(e)), - }; + let mut res = try!(req.send()); - let body = match str::from_utf8(res.get_body()) { - Ok(b) => b, - Err(e) => return Err(ReqErr::RespNotUTF8(e)), - }; + let mut body = String::new(); + try!(res.read_to_string(&mut body)); Ok(Response { - body: body.to_string(), - code: res.get_code(), + body: body, + code: res.status, }) } - fn request_url_async(url: &Arc, method: Method, data: Option, callback: F) -> JoinHandle<()> + fn request_url_async(url: Url, method: Method, data: Option, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static { - // Fast, because its in an arc. - let url = url.clone(); - thread::spawn(move || { - callback(Firebase::request_url(&url, method, data.as_ref().map(|s| s as &str))); + callback(Firebase::request_url(url, method, data.as_ref().map(|s| s as &str))); }) } fn with_params(&self, key: &'static str, value: T) -> FirebaseParams { - FirebaseParams::new(&self.url, key, value) + FirebaseParams::new(self.url.clone(), key, value) } } @@ -405,7 +395,7 @@ impl Firebase { /// ``` #[derive(Clone)] pub struct FirebaseParams { - url: Arc, + url: Url, params: HashMap<&'static str, String>, } @@ -419,20 +409,20 @@ impl FirebaseParams { /// let first5 = alphabetic.get(); /// ``` pub fn get(&self) -> Result { - Firebase::request_url(&self.url, Method::GET, None) + Firebase::request_url(self.url.clone(), Method::GET, None) } /// Asynchronous version of the get method, takes a callback /// and returns a handle to the thread making the request to Firebase. pub fn get_async(&self, callback: F) -> JoinHandle<()> where F: Fn(Result) + Send + 'static { - Firebase::request_url_async(&self.url, Method::GET, None, callback) + Firebase::request_url_async(self.url.clone(), Method::GET, None, callback) } /// Returns the current URL as a string that will be used /// to make the REST call when talking to Firebase. - pub fn get_url(&self) -> String { - self.url.serialize() + pub fn get_url(&self) -> &str { + self.url.as_str() } // TODO: Wrap in quotes if not already. Or always wrap in quotes. @@ -499,38 +489,30 @@ impl FirebaseParams { } fn set_params(&mut self) { - // Only clones the url when edited. This is CoW - // Many threads can run requests without ever cloning the url. - let mut url = (*self.url).clone(); - url.set_query_from_pairs(self.params.iter().map(|(&k, v)| (k, v as &str))); - self.url = Arc::new(url); + self.url.query_pairs_mut() + .extend_pairs(self.params.iter().map(|(&k, v)| (k, v as &str))) + .finish(); } fn get_auth(url: &Url) -> HashMap<&'static str, String> { - let mut pair: HashMap<&'static str, String> = HashMap::new(); - - if let Some(queries) = url.query_pairs() { - for &(ref k, ref v) in queries.iter() { - if k == AUTH { - pair.insert(AUTH, v.to_string()); - } - } - } - pair + url.query_pairs() + .filter(|&(ref k,_)| k == AUTH) + .map(|(_, v)| (AUTH, v.into_owned())) + .collect() } - fn new(url: &Url, key: &'static str, value: T) -> Self { + fn new(url: Url, key: &'static str, value: T) -> Self { let me = FirebaseParams { - url: Arc::new(url.clone()), params: FirebaseParams::get_auth(&url), + url: url, }; me.add_param(key, value) } - fn from_ops(url: &Url, opts: &FbOps) -> Self { + fn from_ops(url: Url, opts: &FbOps) -> Self { let mut me = FirebaseParams { - url: Arc::new(url.clone()), params: FirebaseParams::get_auth(&url), + url: url, }; if let Some(order) = opts.order_by { me.params.insert(ORDER_BY, order.to_string()); @@ -614,9 +596,23 @@ impl<'l> Default for FbOps<'l> { pub enum ReqErr { ReqNotJSON, RespNotUTF8(str::Utf8Error), - NetworkErr(curl::ErrCode), + Network(hyper::Error), + Io(io::Error), +} + +impl From for ReqErr { + fn from(e: hyper::Error) -> Self { + ReqErr::Network(e) + } } +impl From for ReqErr { + fn from(e: io::Error) -> Self { + ReqErr::Io(e) + } +} + + #[derive(Debug)] pub enum ParseError { UrlHasNoPath, @@ -627,13 +623,13 @@ pub enum ParseError { #[derive(Debug)] pub struct Response { pub body: String, - pub code: u32, + pub code: StatusCode, } impl Response { /// Returns true if the status code is 200 pub fn is_success(&self) -> bool { - self.code == 200 + self.code == StatusCode::Ok } /// Turns the response body into a Json enum. @@ -666,8 +662,8 @@ fn parse(url: &str) -> Result { } } -fn unwrap_path(url: &Url) -> Result<&[String], ParseError> { - match url.path() { +fn unwrap_path(url: &Url) -> Result, ParseError> { + match url.path_segments() { None => return Err(ParseError::UrlHasNoPath), Some(p) => return Ok(p), } From dca0291e75ebcfb68eaddc523456b84a4f20cccc Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 15:46:12 +0200 Subject: [PATCH 2/7] Update tests --- tests/lib.rs | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index cb8fb19..d313b8f 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,9 +1,12 @@ extern crate firebase; extern crate url; extern crate rustc_serialize; +extern crate hyper; use firebase::*; use url::Url; +use hyper::status::StatusCode; +use std::collections::HashMap; use std::sync::{Arc, Mutex}; @@ -17,7 +20,7 @@ fn builds_auth_url() { fn extends_auth_url() { let f = Firebase::authed("https://db.rifebass.com/", "deadbeaf").ok().unwrap(); let f = f.at("/futurama/SpacePilot3000").ok().unwrap(); - let url_now = "https://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf"; + let url_now = "https://db.rifebass.com/futurama/SpacePilot3000.json?auth=deadbeaf"; assert_eq!(url_now, f.get_url()); } @@ -26,7 +29,7 @@ fn double_extends_url() { let f = Firebase::authed("https://db.rifebass.com", "deadbeaf").ok().unwrap(); let f = f.at("/futurama.json").ok().unwrap(); let f = f.at("SpacePilot3000").ok().unwrap(); - let url_now = "https://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf"; + let url_now = "https://db.rifebass.com/futurama/SpacePilot3000.json?auth=deadbeaf"; assert_eq!(url_now, f.get_url()); } @@ -35,13 +38,13 @@ fn handle_slashes() { let f = Firebase::authed("https://db.rifebass.com", "deadbeaf").ok().unwrap(); let f = f.at("futurama.json").ok().unwrap(); let f = f.at("SpacePilot3000.json").ok().unwrap(); - let url_now = "https://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf"; + let url_now = "https://db.rifebass.com/futurama/SpacePilot3000.json?auth=deadbeaf"; assert_eq!(url_now, f.get_url()); let f = Firebase::authed("https://db.rifebass.com/", "deadbeaf").ok().unwrap(); let f = f.at("/futurama/").ok().unwrap(); let f = f.at("/SpacePilot3000/").ok().unwrap(); - let url_now = "https://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf"; + let url_now = "https://db.rifebass.com/futurama/SpacePilot3000.json?auth=deadbeaf"; assert_eq!(url_now, f.get_url()); } @@ -58,7 +61,7 @@ fn handle_json_suffix() { .at("1.json").ok().unwrap().at("9.json").ok().unwrap() .at("7.json").ok().unwrap().at("2.json").ok().unwrap() .at("5.json").ok().unwrap().at("3.json").ok().unwrap(); - let url_now = "https://db.rifebass.com//0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json"; + let url_now = "https://db.rifebass.com/0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json"; assert_eq!(url_now, f.get_url()); } @@ -70,7 +73,7 @@ fn test_ops() { let correct = Url::parse("https://db.fe//lol.json?limitToFirst=4&endAt=13&equalTo=8&shallow=false").ok().unwrap(); let generated = Url::parse(&req.get_url()).ok().unwrap(); - assert_queries(&correct, &generated); + assert_queries_eq(&correct, &generated); } #[test] @@ -81,7 +84,7 @@ fn test_auth_ops() { let correct = Url::parse("https://db.fe/lol.json?auth=key&orderBy=pts&limitToLast=5&startAt=8").ok().unwrap(); let generated = Url::parse(&req.get_url()).ok().unwrap(); - assert_queries(&correct, &generated); + assert_queries_eq(&correct, &generated); } #[test] @@ -116,13 +119,13 @@ fn test_ops_ctor() { let corr = Url::parse("https://db.fb.com/?limitToFirst=5&orderBy=Hello+World&equalTo=3&format=export&shallow=true&endAt=7").ok().unwrap(); let this = Url::parse(&query.get_url()).ok().unwrap(); - assert_queries(&corr, &this); + assert_queries_eq(&corr, &this); } #[test] fn test_resp_json() { let response = Response { - code: 200, + code: StatusCode::Ok, body: "{ \"id\": \"mongo id\", \"data\": \"Hello World!\" @@ -145,7 +148,7 @@ fn test_resp_json() { #[test] fn test_resp_struct_easy() { let response = Response { - code: 200, + code: StatusCode::Ok, body: "{ \"fizz\": 3, \"buzz\": 5 @@ -158,15 +161,11 @@ fn test_resp_struct_easy() { assert_eq!(bee.buzz, 5); } -fn assert_queries(a: &Url, b: &Url) { - let param_a = a.query_pairs().expect("Url should have query params."); - let param_b = b.query_pairs().expect("Url should have query params."); +fn assert_queries_eq(a: &Url, b: &Url) { + let param_a = a.query_pairs().collect::>(); + let param_b = b.query_pairs().collect::>(); - assert_eq!(param_b.len(), param_a.len()); - - for pair in param_a.iter() { - assert!(param_b.contains(pair)); - } + assert_eq!(param_a, param_b); } #[derive(RustcDecodable)] From 4579f4c217076fa4ae906cbcc423626e16e0d5ed Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 16:02:40 +0200 Subject: [PATCH 3/7] Fix doc tests --- src/lib.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f9ec938..5469545 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -641,14 +641,20 @@ impl Response { /// # Examples /// /// ``` - /// # use firebase::Response; - /// let response = Response { - /// body: "324567898".to_string(), - /// code: 200, - /// }; + /// extern crate firebase; + /// extern crate hyper; + /// use hyper::status::StatusCode; + /// use firebase::Response; /// - /// let parsed: u32 = response.parse().unwrap(); - /// println!("Data is: {}", parsed); + /// fn main() { + /// let response = Response { + /// body: "324567898".to_string(), + /// code: StatusCode::Ok, + /// }; + /// + /// let parsed: u32 = response.parse().unwrap(); + /// println!("Data is: {}", parsed); + /// } /// ``` pub fn parse(&self) -> Result where D: Decodable { json::decode(&self.body) From 023310ae9ed04d4a17d22b7530da3e27e35a3054 Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 16:37:23 +0200 Subject: [PATCH 4/7] Properly create Firebase struct --- src/lib.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5469545..22136df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -44,14 +44,8 @@ impl Firebase { /// will be returned. pub fn new(url: &str) -> Result { let url = try!( parse(&url) ); - if url.scheme() != "https" { - return Err(ParseError::UrlIsNotHTTPS); - } - try!( unwrap_path(&url) ); - Ok(Firebase { - url: url, - }) + Firebase::from_url(url) } /// Creates a firebase reference from a borrow of a Url instance. @@ -63,6 +57,10 @@ impl Firebase { pub fn from_url(url: Url) -> Result { try!( unwrap_path(&url) ); + if url.scheme() != "https" { + return Err(ParseError::UrlIsNotHTTPS); + } + Ok(Firebase { url: url, }) From 767a133bfeea971eb4c80a3cbcedfbc52ebb8d05 Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 16:49:46 +0200 Subject: [PATCH 5/7] Get rid of Url parse method --- src/lib.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 22136df..1315b29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -43,7 +43,7 @@ impl Firebase { /// - If a url cannot be parsed into a valid url then a ```Err(ParseError::Parser(url::ParseError)``` /// will be returned. pub fn new(url: &str) -> Result { - let url = try!( parse(&url) ); + let url = try!(Url::parse(&url)); Firebase::from_url(url) } @@ -81,7 +81,7 @@ impl Firebase { /// - If a url cannot be parsed into a valid url then a ```Err(ParseError::Parser(url::ParseError)``` /// will be returned. pub fn authed(url: &str, auth_token: &str) -> Result { - let mut url = try!( parse(&url) ); + let mut url = try!(Url::parse(&url)); if url.scheme() != "https" { return Err(ParseError::UrlIsNotHTTPS); } @@ -618,6 +618,12 @@ pub enum ParseError { Parser(url::ParseError), } +impl From for ParseError { + fn from(e: url::ParseError) -> Self { + ParseError::Parser(e) + } +} + #[derive(Debug)] pub struct Response { pub body: String, @@ -659,13 +665,6 @@ impl Response { } } -fn parse(url: &str) -> Result { - match Url::parse(&url) { - Ok(u) => Ok(u), - Err(e) => Err(ParseError::Parser(e)), - } -} - fn unwrap_path(url: &Url) -> Result, ParseError> { match url.path_segments() { None => return Err(ParseError::UrlHasNoPath), From fcc4ce685a4bf0b79a6a90a1c7148808edd6b6d3 Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 16:50:46 +0200 Subject: [PATCH 6/7] Simplify Firebase::authed --- src/lib.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1315b29..06bd620 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,16 +82,9 @@ impl Firebase { /// will be returned. pub fn authed(url: &str, auth_token: &str) -> Result { let mut url = try!(Url::parse(&url)); - if url.scheme() != "https" { - return Err(ParseError::UrlIsNotHTTPS); - } - try!( unwrap_path(&url) ); - url.query_pairs_mut().append_pair(AUTH, auth_token).finish(); - Ok(Firebase { - url: url, - }) + Firebase::from_url(url) } /// Creates a new firebase instance that extends the path of an old firebase instance. From 0f69dad1b21429cb3d729ffdeb83eb44fcf3952b Mon Sep 17 00:00:00 2001 From: panicbit Date: Mon, 23 May 2016 17:22:54 +0200 Subject: [PATCH 7/7] Append initial .json extension --- src/lib.rs | 9 ++++++++- tests/lib.rs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 06bd620..cb57a40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,13 +54,20 @@ impl Firebase { /// will be returned. /// - If a url cannot be parsed into a valid url then a ```Err(ParseError::Parser(url::ParseError)``` /// will be returned. - pub fn from_url(url: Url) -> Result { + pub fn from_url(mut url: Url) -> Result { try!( unwrap_path(&url) ); if url.scheme() != "https" { return Err(ParseError::UrlIsNotHTTPS); } + { + // Append initial .json + let mut last = url.path_segments().expect("last segment").last().unwrap().to_string(); + let mut path = url.path_segments_mut().expect("path segments"); + path.pop().push(&(last + ".json")); + } + Ok(Firebase { url: url, }) diff --git a/tests/lib.rs b/tests/lib.rs index d313b8f..6ecdbe5 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -13,7 +13,7 @@ use std::sync::{Arc, Mutex}; #[test] fn builds_auth_url() { let f = Firebase::authed("https://db.rifebass.com/", "deadbeaf").ok().unwrap(); - assert_eq!(f.get_url(), "https://db.rifebass.com/?auth=deadbeaf"); + assert_eq!(f.get_url(), "https://db.rifebass.com/.json?auth=deadbeaf"); } #[test]