├── .gitignore ├── migrations ├── down.sql └── up.sql ├── Cargo.toml ├── LICENSE ├── README.md ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /migrations/down.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE urls; 2 | -------------------------------------------------------------------------------- /migrations/up.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE urls ( 2 | id INTEGER PRIMARY KEY, 3 | created_at TEXT NOT NULL, 4 | url TEXT NOT NULL UNIQUE, 5 | locator CHAR(7) NOT NULL UNIQUE 6 | ); 7 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "yaus" 3 | version = "0.3.0" 4 | authors = ["Garrett Squire "] 5 | 6 | [dependencies] 7 | chrono = "0.3" 8 | iron = "0.5" 9 | persistent = "0.3" 10 | r2d2 = "0.7" 11 | r2d2_sqlite = "0.1" 12 | router = "0.5" 13 | rusqlite = "0.11" 14 | rustc-serialize = "0.3" 15 | sha2 = "0.5" 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Garrett Squire 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **This website no longer exists, but the code will remain here. Please open an issue if you 2 | have any questions.** 3 | 4 | # yaus 5 | **Y**et **A**nother **URL** **S**hortener in Rust. 6 | 7 | YAUS was inspired by [this comment on HN](https://news.ycombinator.com/item?id=11957494). 8 | I had wanted to write a web service in Rust and thought it would be a simple exercise 9 | to demonstrate Rust's strengths in speed and safety. 10 | 11 | It is implemented using the Iron framework with SQLite for storing the urls. The site has NGINX 12 | sitting in front as a reverse proxy as well. 13 | 14 | ### Implementation 15 | This app uses Iron's persistent crate to share the SQLite connection between the handlers. The 16 | pooling is provided by r2d2. 17 | 18 | To generate the short URL identifier it uses the first seven bytes from the SHA-2 hash of the 19 | original URL. Again, I may have overlooked any issues with this, but the chance of collision 20 | is unlikely. 21 | 22 | ### API 23 | To shorten a URL you can hit the shorten endpoint: 24 | 25 | ```sh 26 | curl https://yaus.pw/shorten?url=[1] 27 | 28 | [1]: A valid URL 29 | ``` 30 | 31 | Responses: 32 | - 200 The shortened URL exists and has been returned. 33 | - 201 The new shortened URL has been created and returned. 34 | - 400 Invalid request, see the error message. 35 | 36 | To retrieve the shortened URL: 37 | 38 | ```sh 39 | curl https://yaus.pw/[1] 40 | 41 | [1]: A valid short identifier 42 | ``` 43 | 44 | Responses: 45 | - 301 The URL has been redirected. 46 | - 404 The identifier has not been found. 47 | 48 | ### Future Goals 49 | - Share the necessary packages used to build and run the service 50 | - Make the app configurable 51 | - Share NGINX configuration and how to install a certificate with LetsEncrypt 52 | - Add an HTML form to use through a browser 53 | - Add expiration to the links to keep the database from growing too big 54 | 55 | ### License 56 | MIT 57 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate chrono; 2 | extern crate iron; 3 | extern crate persistent; 4 | extern crate r2d2; 5 | extern crate r2d2_sqlite; 6 | extern crate router; 7 | extern crate rusqlite; 8 | extern crate rustc_serialize; 9 | extern crate sha2; 10 | 11 | use chrono::*; 12 | 13 | use iron::prelude::*; 14 | use iron::Url; 15 | use iron::modifiers::Redirect; 16 | use iron::status::Status; 17 | use iron::typemap::Key; 18 | 19 | use persistent::Read; 20 | 21 | use r2d2::Pool; 22 | 23 | use r2d2_sqlite::SqliteConnectionManager; 24 | 25 | use router::Router; 26 | 27 | use rusqlite::Connection; 28 | 29 | use rustc_serialize::hex::ToHex; 30 | 31 | use sha2::{Digest, Sha256}; 32 | 33 | use std::env; 34 | 35 | const HOST: &'static str = "https://yaus.pw/"; 36 | 37 | pub type SqlitePool = Pool; 38 | 39 | pub struct YausDb; 40 | impl Key for YausDb { 41 | type Value = SqlitePool; 42 | } 43 | 44 | // A simple macro to return early if the URL can't parse. 45 | macro_rules! try_url { 46 | ($url:expr) => { 47 | match Url::parse($url) { 48 | Ok(_) => { }, 49 | Err(_) => { 50 | return Ok(Response::with((Status::BadRequest, "Malformed URL"))); 51 | } 52 | } 53 | } 54 | } 55 | 56 | fn create_shortened_url(db: &Connection, long_url: &str) -> IronResult { 57 | let mut d = Sha256::default(); 58 | d.input(long_url.as_bytes()); 59 | let locator = d.result().as_slice().to_hex(); 60 | 61 | let timestamp = Local::now().to_rfc3339(); 62 | db.execute("INSERT INTO urls VALUES (NULL, ?1, ?2, ?3)", 63 | &[×tamp, &long_url, &&locator[0..7]]).unwrap(); 64 | 65 | Ok(Response::with((Status::Created, [HOST, &locator[0..7]].join("")))) 66 | } 67 | 68 | /// Given a long URL, see if it already exists in the table, else create an entry and return 69 | /// it. 70 | /// 71 | /// A 200 means that a shortened URL already exists and has been returned. A 201 72 | /// response means that a new shortened URL has been created. 73 | fn check_or_shorten_url(db: &Connection, long_url: &str) -> IronResult { 74 | let mut stmt = db.prepare("SELECT locator FROM urls WHERE url = (?)").unwrap(); 75 | let mut row = stmt.query_map::(&[&long_url], |r| r.get(0)).unwrap(); 76 | 77 | if let Some(l) = row.next() { 78 | return Ok(Response::with((Status::Ok, [HOST, &l.unwrap()].join("")))); 79 | } 80 | create_shortened_url(db, long_url) 81 | } 82 | 83 | /// The handler to shorten a URL. 84 | fn shorten_handler(req: &mut Request) -> IronResult { 85 | match req.url.clone().query() { 86 | None => { Ok(Response::with((Status::BadRequest, "URL missing in query"))) }, 87 | Some(s) => { 88 | let (k, v) = s.split_at(4); 89 | if k == "url=" { 90 | try_url!(v); 91 | let pool = req.get::>().unwrap().clone(); 92 | let db = pool.get().unwrap(); 93 | check_or_shorten_url(&db, v) 94 | } else { 95 | Ok(Response::with((Status::BadRequest, "Malformed query string"))) 96 | } 97 | } 98 | } 99 | } 100 | 101 | /// The handler that redirects to the long URL. 102 | fn redirect_handler(req: &mut Request) -> IronResult { 103 | let pool = req.get::>().unwrap().clone(); 104 | let db = pool.get().unwrap(); 105 | let locator = req.url.path()[0]; 106 | let mut stmt = db.prepare("SELECT url FROM urls WHERE locator = (?)").unwrap(); 107 | let mut row = stmt.query_map::(&[&locator], |r| r.get(0)).unwrap(); 108 | 109 | if let Some(u) = row.next() { 110 | let long_url = Url::parse(&u.unwrap()).unwrap(); 111 | Ok(Response::with((Status::MovedPermanently, Redirect(long_url)))) 112 | } else { 113 | Ok(Response::with((Status::NotFound, "Not found"))) 114 | } 115 | } 116 | 117 | fn index_handler(_: &mut Request) -> IronResult { 118 | Ok(Response::with((Status::Ok, "See https://github.com/gsquire/yaus for the API"))) 119 | } 120 | 121 | fn main() { 122 | let mut router = Router::new(); 123 | router.get("/shorten", shorten_handler, "shorten"); 124 | router.get("/:locator", redirect_handler, "locator"); 125 | router.get("/", index_handler, "index"); 126 | 127 | let config = r2d2::Config::default(); 128 | let db = env::var("SHORT_DB").unwrap(); 129 | let manager = SqliteConnectionManager::new(&db); 130 | let pool = r2d2::Pool::new(config, manager).unwrap(); 131 | 132 | let mut chain = Chain::new(router); 133 | chain.link_before(Read::::one(pool)); 134 | 135 | Iron::new(chain).http("localhost:3000").unwrap(); 136 | } 137 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "yaus" 3 | version = "0.3.0" 4 | dependencies = [ 5 | "chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 6 | "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | "persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 8 | "r2d2 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 9 | "r2d2_sqlite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 10 | "router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 11 | "rusqlite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 12 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 13 | "sha2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 14 | ] 15 | 16 | [[package]] 17 | name = "antidote" 18 | version = "1.0.0" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | 21 | [[package]] 22 | name = "base64" 23 | version = "0.5.2" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | dependencies = [ 26 | "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "bitflags" 31 | version = "0.7.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | 34 | [[package]] 35 | name = "byte-tools" 36 | version = "0.1.3" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | 39 | [[package]] 40 | name = "byteorder" 41 | version = "1.0.0" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | 44 | [[package]] 45 | name = "chrono" 46 | version = "0.3.1" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | dependencies = [ 49 | "num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 51 | ] 52 | 53 | [[package]] 54 | name = "conduit-mime-types" 55 | version = "0.7.3" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | dependencies = [ 58 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 59 | ] 60 | 61 | [[package]] 62 | name = "digest" 63 | version = "0.5.2" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | dependencies = [ 66 | "generic-array 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 67 | ] 68 | 69 | [[package]] 70 | name = "digest-buffer" 71 | version = "0.3.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | dependencies = [ 74 | "byte-tools 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 75 | "generic-array 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 76 | ] 77 | 78 | [[package]] 79 | name = "error" 80 | version = "0.1.9" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | dependencies = [ 83 | "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 84 | "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 85 | ] 86 | 87 | [[package]] 88 | name = "fake-simd" 89 | version = "0.1.2" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | 92 | [[package]] 93 | name = "generic-array" 94 | version = "0.7.2" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | dependencies = [ 97 | "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 98 | "typenum 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 99 | ] 100 | 101 | [[package]] 102 | name = "httparse" 103 | version = "1.2.2" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | 106 | [[package]] 107 | name = "hyper" 108 | version = "0.10.10" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | dependencies = [ 111 | "base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 112 | "httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 113 | "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 114 | "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 115 | "mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 116 | "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 117 | "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 118 | "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 119 | "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 120 | "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 121 | "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 122 | "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 123 | ] 124 | 125 | [[package]] 126 | name = "idna" 127 | version = "0.1.1" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | dependencies = [ 130 | "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 131 | "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 132 | "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 133 | ] 134 | 135 | [[package]] 136 | name = "iron" 137 | version = "0.5.1" 138 | source = "registry+https://github.com/rust-lang/crates.io-index" 139 | dependencies = [ 140 | "conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", 141 | "error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 142 | "hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)", 143 | "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 144 | "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 145 | "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 146 | "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 148 | "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 150 | ] 151 | 152 | [[package]] 153 | name = "kernel32-sys" 154 | version = "0.2.2" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 159 | ] 160 | 161 | [[package]] 162 | name = "language-tags" 163 | version = "0.2.2" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | 166 | [[package]] 167 | name = "lazy_static" 168 | version = "0.2.8" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | 171 | [[package]] 172 | name = "libc" 173 | version = "0.2.22" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | 176 | [[package]] 177 | name = "libsqlite3-sys" 178 | version = "0.8.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | dependencies = [ 181 | "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", 182 | ] 183 | 184 | [[package]] 185 | name = "linked-hash-map" 186 | version = "0.4.2" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | 189 | [[package]] 190 | name = "log" 191 | version = "0.3.7" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | 194 | [[package]] 195 | name = "lru-cache" 196 | version = "0.1.1" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | dependencies = [ 199 | "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 200 | ] 201 | 202 | [[package]] 203 | name = "matches" 204 | version = "0.1.4" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | 207 | [[package]] 208 | name = "mime" 209 | version = "0.2.3" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | dependencies = [ 212 | "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 213 | ] 214 | 215 | [[package]] 216 | name = "modifier" 217 | version = "0.1.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | 220 | [[package]] 221 | name = "nodrop" 222 | version = "0.1.9" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | dependencies = [ 225 | "odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", 226 | ] 227 | 228 | [[package]] 229 | name = "num" 230 | version = "0.1.37" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | dependencies = [ 233 | "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", 234 | "num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", 235 | "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 236 | ] 237 | 238 | [[package]] 239 | name = "num-integer" 240 | version = "0.1.34" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | dependencies = [ 243 | "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 244 | ] 245 | 246 | [[package]] 247 | name = "num-iter" 248 | version = "0.1.33" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | dependencies = [ 251 | "num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", 252 | "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 253 | ] 254 | 255 | [[package]] 256 | name = "num-traits" 257 | version = "0.1.37" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | 260 | [[package]] 261 | name = "num_cpus" 262 | version = "1.4.0" 263 | source = "registry+https://github.com/rust-lang/crates.io-index" 264 | dependencies = [ 265 | "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", 266 | ] 267 | 268 | [[package]] 269 | name = "odds" 270 | version = "0.2.25" 271 | source = "registry+https://github.com/rust-lang/crates.io-index" 272 | 273 | [[package]] 274 | name = "persistent" 275 | version = "0.3.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | dependencies = [ 278 | "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 279 | "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", 280 | ] 281 | 282 | [[package]] 283 | name = "pkg-config" 284 | version = "0.3.9" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | 287 | [[package]] 288 | name = "plugin" 289 | version = "0.2.6" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | dependencies = [ 292 | "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", 293 | ] 294 | 295 | [[package]] 296 | name = "r2d2" 297 | version = "0.7.2" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | dependencies = [ 300 | "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 301 | "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", 302 | "scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 303 | ] 304 | 305 | [[package]] 306 | name = "r2d2_sqlite" 307 | version = "0.1.4" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | dependencies = [ 310 | "r2d2 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 311 | "rusqlite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 312 | ] 313 | 314 | [[package]] 315 | name = "redox_syscall" 316 | version = "0.1.17" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | 319 | [[package]] 320 | name = "route-recognizer" 321 | version = "0.1.12" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | 324 | [[package]] 325 | name = "router" 326 | version = "0.5.1" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | dependencies = [ 329 | "iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 330 | "route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", 331 | "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 332 | ] 333 | 334 | [[package]] 335 | name = "rusqlite" 336 | version = "0.11.0" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | dependencies = [ 339 | "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 340 | "libsqlite3-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 341 | "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 342 | "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", 343 | ] 344 | 345 | [[package]] 346 | name = "rustc-serialize" 347 | version = "0.3.24" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | 350 | [[package]] 351 | name = "rustc_version" 352 | version = "0.1.7" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | dependencies = [ 355 | "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", 356 | ] 357 | 358 | [[package]] 359 | name = "scheduled-thread-pool" 360 | version = "0.1.0" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | dependencies = [ 363 | "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 364 | ] 365 | 366 | [[package]] 367 | name = "semver" 368 | version = "0.1.20" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | 371 | [[package]] 372 | name = "sha2" 373 | version = "0.5.2" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | dependencies = [ 376 | "byte-tools 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", 377 | "digest 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", 378 | "digest-buffer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 379 | "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", 380 | "generic-array 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 381 | ] 382 | 383 | [[package]] 384 | name = "time" 385 | version = "0.1.37" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | dependencies = [ 388 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 389 | "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", 390 | "redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", 391 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 392 | ] 393 | 394 | [[package]] 395 | name = "traitobject" 396 | version = "0.1.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | 399 | [[package]] 400 | name = "typeable" 401 | version = "0.1.2" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | 404 | [[package]] 405 | name = "typemap" 406 | version = "0.3.3" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | dependencies = [ 409 | "unsafe-any 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 410 | ] 411 | 412 | [[package]] 413 | name = "typenum" 414 | version = "1.5.2" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | 417 | [[package]] 418 | name = "unicase" 419 | version = "1.4.0" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | dependencies = [ 422 | "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 423 | ] 424 | 425 | [[package]] 426 | name = "unicode-bidi" 427 | version = "0.2.5" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | dependencies = [ 430 | "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 431 | ] 432 | 433 | [[package]] 434 | name = "unicode-normalization" 435 | version = "0.1.4" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | 438 | [[package]] 439 | name = "unsafe-any" 440 | version = "0.4.1" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | dependencies = [ 443 | "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 444 | ] 445 | 446 | [[package]] 447 | name = "url" 448 | version = "1.4.0" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | dependencies = [ 451 | "idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 452 | "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 453 | ] 454 | 455 | [[package]] 456 | name = "winapi" 457 | version = "0.2.8" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | 460 | [[package]] 461 | name = "winapi-build" 462 | version = "0.1.1" 463 | source = "registry+https://github.com/rust-lang/crates.io-index" 464 | 465 | [metadata] 466 | "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" 467 | "checksum base64 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "30e93c03064e7590d0466209155251b90c22e37fab1daf2771582598b5827557" 468 | "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" 469 | "checksum byte-tools 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0919189ba800c7ffe8778278116b7e0de3905ab81c72abb69c85cbfef7991279" 470 | "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" 471 | "checksum chrono 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d9123be86fd2a8f627836c235ecdf331fdd067ecf7ac05aa1a68fbcf2429f056" 472 | "checksum conduit-mime-types 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95ca30253581af809925ef68c2641cc140d6183f43e12e0af4992d53768bd7b8" 473 | "checksum digest 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a68d759d7a66a4f63d5bd2a2b14ad7e8cf93fe8c9be227031cd4e72ab0e9ee8" 474 | "checksum digest-buffer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f906a192397079534ffcfd17355e8c190c48dd9570bc93df61e8e0069c67fc6e" 475 | "checksum error 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e606f14042bb87cc02ef6a14db6c90ab92ed6f62d87e69377bc759fd7987cc" 476 | "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 477 | "checksum generic-array 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "330920f60726e8a1ca0129a40f0f0df0b8ee773945bf34895d578f35f31dc660" 478 | "checksum httparse 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77f756bed9ee3a83ce98774f4155b42a31b787029013f3a7d83eca714e500e21" 479 | "checksum hyper 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "36e108e0b1fa2d17491cbaac4bc460dc0956029d10ccf83c913dd0e5db3e7f07" 480 | "checksum idna 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac85ec3f80c8e4e99d9325521337e14ec7555c458a14e377d189659a427f375" 481 | "checksum iron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2440ae846e7a8c7f9b401db8f6e31b4ea5e7d3688b91761337da7e054520c75b" 482 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 483 | "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" 484 | "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" 485 | "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" 486 | "checksum libsqlite3-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "33e0b09db40cce5117daf908cd067e84ea7d8b14ae3a826a29e19cd11305677b" 487 | "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" 488 | "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" 489 | "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" 490 | "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" 491 | "checksum mime 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5514f038123342d01ee5f95129e4ef1e0470c93bc29edf058a46f9ee3ba6737e" 492 | "checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" 493 | "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" 494 | "checksum num 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "98b15ba84e910ea7a1973bccd3df7b31ae282bf9d8bd2897779950c9b8303d40" 495 | "checksum num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "ef1a4bf6f9174aa5783a9b4cc892cacd11aebad6c69ad027a0b65c6ca5f8aa37" 496 | "checksum num-iter 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d1891bd7b936f12349b7d1403761c8a0b85a18b148e9da4429d5d102c1a41e" 497 | "checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" 498 | "checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167" 499 | "checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" 500 | "checksum persistent 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c9c94f2ef72dc272c6bcc8157ccf2bc7da14f4c58c69059ac2fc48492d6916" 501 | "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" 502 | "checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" 503 | "checksum r2d2 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1dd448c29d0ed83cfe187ffb8608fa07c47abdd7997f3f478f3a6223ad3f97fb" 504 | "checksum r2d2_sqlite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e41e5700d731909b2d4b0851e555f374a3a45ba383fd37d65ed0218837e674a5" 505 | "checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b" 506 | "checksum route-recognizer 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3255338088df8146ba63d60a9b8e3556f1146ce2973bc05a75181a42ce2256" 507 | "checksum router 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9b1797ff166029cb632237bb5542696e54961b4cf75a324c6f05c9cf0584e4e" 508 | "checksum rusqlite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28df6ae60019445d95d7a5be417ae16923c156d90f7051727fe0a15eaa70fae0" 509 | "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" 510 | "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" 511 | "checksum scheduled-thread-pool 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d9fbe48ead32343b76f544c85953bf260ed39219a8bbbb62cd85f6a00f9644f" 512 | "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" 513 | "checksum sha2 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "84d24a04bbdb2b09512951fc4d13ac76bb309c63163a22394a92698183a31d67" 514 | "checksum time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd7ccbf969a892bf83f1e441126968a07a3941c24ff522a26af9f9f4585d1a3" 515 | "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" 516 | "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" 517 | "checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" 518 | "checksum typenum 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7242a7857c31d13620847d78af39ecac8d6c90aac23286e84aefe624c77c9c14" 519 | "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" 520 | "checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032" 521 | "checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff" 522 | "checksum unsafe-any 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b351086021ebc264aea3ab4f94d61d889d98e5e9ec2d985d993f50133537fd3a" 523 | "checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e" 524 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 525 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 526 | --------------------------------------------------------------------------------