1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use curl::easy::{Easy, List}; use error::BTErr; use goauth::auth::Token; use method::{BigTable, ReadRows}; use protobuf_json; use serde_json; use serde_json::Value; use std; use std::io::Read; use support::Table; pub struct BTRequest<'a, T: BigTable> { pub base: Option<&'a str>, pub table: Table, pub method: T, } impl<'a> Default for BTRequest<'a, ReadRows> { fn default() -> Self { BTRequest { base: None, table: Default::default(), method: ReadRows::new(), } } } impl<'a, T: BigTable> BTRequest<'a, T> { pub fn form_url(&self) -> Result<String, BTErr> { let base = match self.base { Some(x) => x, None => "https://bigtable.googleapis.com/v2", }; Ok(format!( "{}/projects/{}/instances/{}/tables/{}{}", base, self.table.instance.project.name, self.table.instance.name, self.table.name, self.method.url_method() )) } pub fn execute(&self, token: &Token) -> Result<Value, BTErr> { let mut response_data: Vec<u8> = Vec::new(); let mut easy = Easy::new(); let payload = protobuf_json::proto_to_json(self.method.payload()); let s_payload = serde_json::to_string(&payload)?; let mut b_payload = s_payload.as_bytes(); easy.url(&self.form_url()?)?; if self.method.is_post() { easy.post(true)?; easy.post_field_size(b_payload.len() as u64)?; } easy.http_headers(gen_headers(token)?)?; { let mut transfer = easy.transfer(); transfer.read_function(|buf| Ok(b_payload.read(buf).unwrap_or(0)))?; transfer.write_function(|response| { response_data.extend_from_slice(response); Ok(response.len()) })?; transfer.header_function(|header| { debug!("header: {}", std::str::from_utf8(header).unwrap()); true })?; transfer.perform()?; } let response_str = std::str::from_utf8(&response_data)?; debug!("Bytes transfered: {}", response_data.len()); debug!("Response: {}", response_str); Ok(serde_json::from_str(response_str)?) } } fn gen_headers(token: &Token) -> Result<List, BTErr> { let mut list = List::new(); let auth = format!( "Authorization: {} {}", token.token_type(), token.access_token() ); list.append(&auth)?; list.append("Content-Type: application/json")?; Ok(list) }