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
use super::SpspResponse;
use bytes::Bytes;
use futures::future::{ok, FutureResult, IntoFuture};
use hyper::{service::Service as HttpService, Body, Error, Request, Response};
use interledger_packet::Address;
use interledger_stream::ConnectionGenerator;
use log::debug;
use std::error::Error as StdError;
use std::{fmt, str};
#[derive(Clone)]
pub struct SpspResponder {
ilp_address: Address,
connection_generator: ConnectionGenerator,
}
impl SpspResponder {
pub fn new(ilp_address: Address, server_secret: Bytes) -> Self {
let connection_generator = ConnectionGenerator::new(server_secret);
SpspResponder {
ilp_address,
connection_generator,
}
}
pub fn generate_http_response(&self) -> Response<Body> {
let (destination_account, shared_secret) = self
.connection_generator
.generate_address_and_secret(&self.ilp_address);
debug!(
"Generated address and secret for: {:?}",
destination_account
);
let response = SpspResponse {
destination_account,
shared_secret: shared_secret.to_vec(),
};
Response::builder()
.header("Content-Type", "application/spsp4+json")
.header("Cache-Control", "max-age=60")
.status(200)
.body(Body::from(serde_json::to_string(&response).unwrap()))
.unwrap()
}
}
impl HttpService for SpspResponder {
type ReqBody = Body;
type ResBody = Body;
type Error = Error;
type Future = FutureResult<Response<Body>, Error>;
fn call(&mut self, _request: Request<Self::ReqBody>) -> Self::Future {
ok(self.generate_http_response())
}
}
impl IntoFuture for SpspResponder {
type Item = Self;
type Error = Never;
type Future = FutureResult<Self::Item, Self::Error>;
fn into_future(self) -> Self::Future {
ok(self)
}
}
#[derive(Debug)]
pub enum Never {}
impl fmt::Display for Never {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
match *self {}
}
}
impl StdError for Never {
fn description(&self) -> &str {
match *self {}
}
}
#[cfg(test)]
mod spsp_server_test {
use super::*;
use futures::Future;
use std::str::FromStr;
#[test]
fn spsp_response_headers() {
let addr = Address::from_str("example.receiver").unwrap();
let mut responder = SpspResponder::new(addr, Bytes::from(&[0; 32][..]));
let response = responder
.call(
Request::builder()
.method("GET")
.uri("http://example.com")
.header("Accept", "application/spsp4+json")
.body(Body::empty())
.unwrap(),
)
.wait()
.unwrap();
assert_eq!(
response.headers().get("Content-Type").unwrap(),
"application/spsp4+json"
);
assert_eq!(
response.headers().get("Cache-Control").unwrap(),
"max-age=60"
);
}
}