1#![doc(html_root_url = "https://docs.rs/finchers-test/0.11.0")]
4#![deny(missing_docs)]
5#![deny(missing_debug_implementations)]
6#![deny(warnings)]
7
8extern crate finchers_core;
9extern crate futures;
10extern crate http;
11
12use futures::{Async, Future};
13use http::header::{HeaderName, HeaderValue};
14use http::{HttpTryFrom, Method, Request, Uri};
15use std::mem;
16
17use finchers_core::endpoint::ApplyRequest;
18use finchers_core::input::RequestBody;
19use finchers_core::{Endpoint, Error, Input, Never, Poll, Task};
20
21#[derive(Debug)]
23pub struct Client<E: Endpoint> {
24 endpoint: E,
25}
26
27impl<E: Endpoint> Client<E> {
28 pub fn new(endpoint: E) -> Client<E> {
30 Client { endpoint }
31 }
32
33 pub fn request<'a, M, U>(&'a self, method: M, uri: U) -> ClientRequest<'a, E>
35 where
36 Method: HttpTryFrom<M>,
37 Uri: HttpTryFrom<U>,
38 {
39 let mut client = ClientRequest {
40 client: self,
41 request: Request::new(()),
42 body: None,
43 };
44 client.method(method);
45 client.uri(uri);
46 client
47 }
48}
49
50macro_rules! impl_constructors {
51 ($(
52 $(#[$doc:meta])*
53 $METHOD:ident => $name:ident,
54 )*) => {$(
55 $(#[$doc])*
56 pub fn $name<'a, U>(&'a self, uri: U) -> ClientRequest<'a, E>
57 where
58 Uri: HttpTryFrom<U>,
59 {
60 self.request(Method::$METHOD, uri)
61 }
62 )*};
63}
64
65impl<E: Endpoint> Client<E> {
66 impl_constructors! {
67 GET => get,
69
70 POST => post,
72
73 PUT => put,
75
76 HEAD => head,
78
79 DELETE => delete,
81
82 PATCH => patch,
84 }
85}
86
87#[derive(Debug)]
89pub struct ClientRequest<'a, E: Endpoint + 'a> {
90 client: &'a Client<E>,
91 request: Request<()>,
92 body: Option<RequestBody>,
93}
94
95impl<'a, E: Endpoint> ClientRequest<'a, E> {
96 pub fn method<M>(&mut self, method: M) -> &mut ClientRequest<'a, E>
101 where
102 Method: HttpTryFrom<M>,
103 {
104 *self.request.method_mut() = Method::try_from(method).ok().unwrap();
105 self
106 }
107
108 pub fn uri<U>(&mut self, uri: U) -> &mut ClientRequest<'a, E>
113 where
114 Uri: HttpTryFrom<U>,
115 {
116 *self.request.uri_mut() = Uri::try_from(uri).ok().unwrap();
117 self
118 }
119
120 pub fn header<K, V>(&mut self, name: K, value: V) -> &mut ClientRequest<'a, E>
125 where
126 HeaderName: HttpTryFrom<K>,
127 HeaderValue: HttpTryFrom<V>,
128 {
129 let name = HeaderName::try_from(name).ok().unwrap();
130 let value = HeaderValue::try_from(value).ok().unwrap();
131 self.request.headers_mut().insert(name, value);
132 self
133 }
134
135 pub fn body(&mut self, body: RequestBody) -> &mut ClientRequest<'a, E> {
137 self.body = Some(body);
138 self
139 }
140
141 fn take(&mut self) -> ClientRequest<'a, E> {
142 mem::replace(
143 self,
144 ClientRequest {
145 client: self.client,
146 request: http::Request::new(()),
147 body: None,
148 },
149 )
150 }
151
152 pub fn run(&mut self) -> Result<E::Output, Error> {
154 let ClientRequest { client, request, body } = self.take();
155
156 let input = Input::new(request);
157 let body = body.unwrap_or_else(RequestBody::empty);
158
159 let apply = client.endpoint.apply_request(&input, body);
160 let task = TestFuture { apply, input };
161
162 task.wait().expect("Apply never fails")
164 }
165}
166
167struct TestFuture<T> {
168 apply: ApplyRequest<T>,
169 input: Input,
170}
171
172impl<T: Task> Future for TestFuture<T> {
173 type Item = Result<T::Output, Error>;
174 type Error = Never;
175
176 fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
177 match self.apply.poll_ready(&self.input) {
178 Poll::Pending => Ok(Async::NotReady),
179 Poll::Ready(ready) => Ok(Async::Ready(ready)),
180 }
181 }
182}