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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! Rusqbin is a web server that stashes your requests for later retrieval. It is available as
//! both a binary and a library.
//!
//! Rusqbin's web API is the following :
//!
//! - POST /rusqbins To create a bin and get back bin_id
//! - GET /rusqbins To list bin summaries
//! - GET /rusqbins/${bin_id}/requests To get detailed request information for a bin
//! - GET /rusqbins/${bin_id} To get bin-specific information (lists all requests in the bin)
//! - DELETE /rusqbins/${bin_id} To delete a bin
//!
//! In any other case, send requests with a X-Rusqbin-Id header with a bin_id to have your requests
//! logged to a bin for later retrieval.
//!
//! To use it as a binary, simply install it using `cargo install rusqbin` and then `rusqbin`,
//! and follow the simple usage instructions.
//!
//! To use it as a library from within Rust code:
//!
//! ```
//! # extern crate rusqbin;
//! # extern crate hyper;
//! # extern crate serde_json;
//! # extern crate futures;
//! # extern crate tokio_core;
//! use rusqbin::storage::*;
//! use rusqbin::server::*;
//! use rusqbin::models::*;
//! use hyper::{Method, Uri};
//! use hyper::client::Client;
//! use hyper::client::Request as HyperRequest;
//! use std::io::Read;
//! use std::thread;
//! use std::time::Duration;
//! use std::sync::{Arc, Mutex};
//! use std::str::FromStr;
//! use futures::future;
//! # fn main() {
//! // Start a BinsServer on port 7000 in another thread, utilising
//! // a simple mutex for shutting it down
//! let server = Arc::new(BinsServer::new(7000, InMemoryBins::new()));
//! let arc_stay_alive = Arc::new(Mutex::new(true));
//! let bg_server = server.clone();
//! let bg_stay_alive = arc_stay_alive.clone();
//! thread::spawn(move || {
//! bg_server.run_until(future::poll_fn(|| {
//! if *bg_stay_alive.lock().unwrap() {
//! Ok(futures::Async::NotReady)
//! } else {
//! Ok(futures::Async::Ready(()))
//! }
//! }))
//! });
//! thread::sleep(Duration::from_millis(500)); // wait a bit for the server to come up
//!
//! let mut client_core = tokio_core::reactor::Core::new().unwrap();
//! let client = Client::new(&client_core.handle());
//!
//! // Create a bin via programmatically, making sure to scope the
//! // storage unlocking with braces properly
//! let bin = {
//! let mut server_storage = server.storage.lock().unwrap();
//! server_storage.create_bin()
//! };
//! let bin_id = bin.id.value();
//!
//! // Fire an HTTP request with the proper X-Rusqbin-Id header
//! let mut req = HyperRequest::new(Method::Post, Uri::from_str("http://localhost:7000/hello/world").unwrap());
//! req.headers_mut().set(XRusqBinId(bin_id.to_owned()));
//! let future_resp = client.request(req);
//!
//! // Here we use core.run to block on response, but you should never
//! // do this in production code.
//! client_core.run(future_resp);
//!
//! // Check to make sure our HTTP request was received and stashed
//! // in our rusqbin server
//! {
//! let mut server_storage = server.storage.lock().unwrap();
//! let bin_requests: &Bin = server_storage.get_bin(&bin.id).unwrap();
//! let req = &bin_requests[0];
//! assert_eq!(req.method, "POST".to_owned());
//! assert_eq!(req.path, "/hello/world".to_owned());
//! }
//!
//! // Cleanup by shutting down our server
//! *arc_stay_alive.lock().unwrap() = false;
//! # }
//! ```
//!
//! In the example above, we use the default `InMemoryBins` for storage, but you can pass any given implementation of
//! `rusqbin::storage::Bins` when creating a BinsServer.
//!
//! [Requestbin](https://requestb.in/) written in Rust. Inspired by [Requestinator](https://github.com/DonMcNamara/requestinator)
extern crate hyper;
extern crate futures;
extern crate uuid;
extern crate regex;
extern crate time;
extern crate url;
extern crate lazy_static;
extern crate serde_derive;
extern crate serde;
extern crate serde_json;
extern crate log;