Skip to content

Commit

Permalink
Add a simple s3 lib
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jul 15, 2014
1 parent c61d3db commit a7e9cf2
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 7 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ git = "https://github.com/sfackler/rust-postgres"

path = "src/html"

[dependencies.s3]

path = "src/s3"

[dependencies.oauth2]

git = "https://github.com/alexcrichton/oauth2-rs"
Expand Down
26 changes: 20 additions & 6 deletions src/app.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use oauth2;
use std::any::AnyRefExt;
use std::fmt::Show;
use std::os;

use conduit::Request;
use conduit_middleware::Middleware;
use oauth2;
use pg::pool::{PostgresConnectionPool, PooledPostgresConnection};
use std::any::AnyRefExt;
use std::fmt::Show;
use s3;

use db;

Expand All @@ -12,6 +15,7 @@ use std::sync::Arc;
pub struct App {
db: PostgresConnectionPool,
pub github: oauth2::Config,
pub bucket: s3::Bucket,
}

pub struct AppMiddleware {
Expand All @@ -23,15 +27,25 @@ impl App {
let pool = db::pool();
db::setup(&*pool.get_connection());
let github = oauth2::Config::new(
"89b6afdeaa6c6c7506ec",
"7a4908a38c75dd12bce36931ad2dbdd951ce228b",
env("GH_CLIENT_ID").as_slice(),
env("GH_CLIENT_SECRET").as_slice(),
"https://github.com/login/oauth/authorize",
"https://github.com/login/oauth/access_token",
);

App {
return App {
db: db::pool(),
github: github,
bucket: s3::Bucket::new(env("S3_BUCKET"),
env("S3_ACCESS_KEY"),
env("S3_SECRET_KEY")),
};

fn env(s: &str) -> String {
match os::getenv(s) {
Some(s) => s,
None => fail!("must have `{}` defined", s),
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ extern crate curl;
extern crate html;
extern crate oauth2;
extern crate pg = "postgres";
extern crate s3;

extern crate conduit_router = "conduit-router";
extern crate conduit;
Expand Down
18 changes: 18 additions & 0 deletions src/s3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]

name = "s3"
version = "0.0.1"
authors = []

[[lib]]

name = "s3"
path = "lib.rs"

[dependencies.curl]

git = "https://github.com/carllerche/curl-rust"

[dependencies.openssl]

git = "https://github.com/sfackler/rust-openssl"
77 changes: 77 additions & 0 deletions src/s3/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
extern crate time;
extern crate curl;
extern crate serialize;
extern crate openssl;

use curl::http;
use curl::http::body::ToBody;
use openssl::crypto::{hmac, hash};
use serialize::base64::{ToBase64, STANDARD};

pub struct Bucket {
name: String,
access_key: String,
secret_key: String,
}

impl Bucket {
pub fn new(name: String,
access_key: String,
secret_key: String) -> Bucket {
Bucket {
name: name,
access_key: access_key,
secret_key: secret_key,
}
}

pub fn put<'a, T: ToBody<'a>>(&mut self, path: &str, content: T)
-> Result<http::Response, curl::ErrCode> {
let mut handle = http::handle();
let host = self.host();
let date = time::now().rfc822z();
let auth = self.auth("PUT", date.as_slice(), path, "",
"application/octet-stream");
let url = format!("https://{}/{}", host, path);
handle.put(url.as_slice(), content)
.header("Host", host.as_slice())
.header("Date", date.as_slice())
.header("Authorization", auth.as_slice())
.exec()
}

pub fn delete(&mut self, path: &str)
-> Result<http::Response, curl::ErrCode> {
let mut handle = http::handle();
let host = self.host();
let date = time::now().rfc822z();
let auth = self.auth("DELETE", date.as_slice(), path, "", "");
let url = format!("https://{}/{}", host, path);
handle.delete(url.as_slice())
.header("Host", host.as_slice())
.header("Date", date.as_slice())
.header("Authorization", auth.as_slice())
.exec()
}

fn host(&self) -> String {
format!("{}.s3.amazonaws.com", self.name)
}

fn auth(&self, verb: &str, date: &str, path: &str,
md5: &str, content_type: &str) -> String {
let string = format!("{verb}\n{md5}\n{ty}\n{date}\n{headers}{resource}",
verb = verb,
md5 = md5,
ty = content_type,
date = date,
headers = "",
resource = format!("/{}/{}", self.name, path));
let signature = {
let mut hmac = hmac::HMAC(hash::SHA1, self.secret_key.as_bytes());
hmac.update(string.as_bytes());
hmac.final().as_slice().to_base64(STANDARD)
};
format!("AWS {}:{}", self.access_key, signature)
}
}
2 changes: 1 addition & 1 deletion src/user/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl User {
}

pub fn new_api_token() -> String {
task_rng().gen_ascii_chars().take(16).collect()
task_rng().gen_ascii_chars().take(32).collect()
}

pub fn encodable(self) -> EncodableUser {
Expand Down

0 comments on commit a7e9cf2

Please sign in to comment.