Supporting /api/ping for dapps server (#1543)

* Refactoring dapps to support API endpoints.

* Using ContentHandler for unauthorized requests

* Extracting url stuff

* Adding ping endpoint

* CORS support for ping request

* Fixing url.is_none()

* minor formatting fix

[ci:skip]
This commit is contained in:
Tomasz Drwięga
2016-07-07 03:42:49 -04:00
committed by Gav Wood
parent 8282c7dd50
commit 7af366c5b1
11 changed files with 233 additions and 52 deletions

View File

@@ -15,20 +15,23 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
use api::types::{App, ApiError};
use api::response::{as_json, as_json_error};
use hyper::{server, net, Decoder, Encoder, Next};
use api::types::{App, ApiError};
use api::response::{as_json, as_json_error, ping_response};
use handlers::extract_url;
use endpoint::{Endpoint, Endpoints, Handler, EndpointPath};
#[derive(Clone)]
pub struct RestApi {
local_domain: String,
endpoints: Arc<Endpoints>,
}
impl RestApi {
pub fn new(endpoints: Arc<Endpoints>) -> Box<Endpoint> {
pub fn new(local_domain: String, endpoints: Arc<Endpoints>) -> Box<Endpoint> {
Box::new(RestApi {
endpoints: endpoints
local_domain: local_domain,
endpoints: endpoints,
})
}
@@ -59,9 +62,28 @@ struct RestApiRouter {
impl server::Handler<net::HttpStream> for RestApiRouter {
fn on_request(&mut self, _request: server::Request<net::HttpStream>) -> Next {
self.handler = as_json(&self.api.list_apps());
Next::write()
fn on_request(&mut self, request: server::Request<net::HttpStream>) -> Next {
let url = extract_url(&request);
if url.is_none() {
// Just return 404 if we can't parse URL
return Next::write();
}
let url = url.expect("Check for None is above; qed");
let endpoint = url.path.get(1).map(|v| v.as_str());
let handler = endpoint.and_then(|v| match v {
"apps" => Some(as_json(&self.api.list_apps())),
"ping" => Some(ping_response(&self.api.local_domain)),
_ => None,
});
// Overwrite default
if let Some(h) = handler {
self.handler = h;
}
self.handler.on_request(request)
}
fn on_request_readable(&mut self, decoder: &mut Decoder<net::HttpStream>) -> Next {

View File

@@ -17,7 +17,7 @@
use serde::Serialize;
use serde_json;
use endpoint::Handler;
use handlers::ContentHandler;
use handlers::{ContentHandler, EchoHandler};
pub fn as_json<T : Serialize>(val: &T) -> Box<Handler> {
Box::new(ContentHandler::ok(serde_json::to_string(val).unwrap(), "application/json".to_owned()))
@@ -26,3 +26,11 @@ pub fn as_json<T : Serialize>(val: &T) -> Box<Handler> {
pub fn as_json_error<T : Serialize>(val: &T) -> Box<Handler> {
Box::new(ContentHandler::not_found(serde_json::to_string(val).unwrap(), "application/json".to_owned()))
}
pub fn ping_response(local_domain: &str) -> Box<Handler> {
Box::new(EchoHandler::cors(vec![
format!("http://{}", local_domain),
// Allow CORS calls also for localhost
format!("http://{}", local_domain.replace("127.0.0.1", "localhost")),
]))
}

View File

@@ -19,5 +19,3 @@ include!("types.rs.in");
#[cfg(not(feature = "serde_macros"))]
include!(concat!(env!("OUT_DIR"), "/types.rs"));

View File

@@ -48,4 +48,3 @@ pub struct ApiError {
pub detail: String,
}