mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-22 12:01:08 +03:00
1143d84238
* start of renamathon * api renaming * Rename UTXO-Output to lessen ambiguity * compile warning * compile error * readme fix * remove file commit in error
124 lines
3.4 KiB
Rust
124 lines
3.4 KiB
Rust
// Copyright 2018 The Grin Developers
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! RESTful API server to easily expose services as RESTful JSON/HTTP endpoints.
|
|
//! Fairly constrained on what the service API must look like by design.
|
|
//!
|
|
//! To use it, just have your service(s) implement the ApiEndpoint trait and
|
|
//! register them on a ApiServer.
|
|
|
|
use std::error;
|
|
use std::fmt::{self, Display, Formatter};
|
|
use std::net::ToSocketAddrs;
|
|
use std::string::ToString;
|
|
use std::mem;
|
|
|
|
use iron::prelude::*;
|
|
use iron::{status, Listening};
|
|
use iron::middleware::Handler;
|
|
use router::Router;
|
|
use mount::Mount;
|
|
|
|
use store;
|
|
|
|
/// Errors that can be returned by an ApiEndpoint implementation.
|
|
#[derive(Debug)]
|
|
pub enum Error {
|
|
Internal(String),
|
|
Argument(String),
|
|
NotFound,
|
|
}
|
|
|
|
impl Display for Error {
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
match *self {
|
|
Error::Argument(ref s) => write!(f, "Bad arguments: {}", s),
|
|
Error::Internal(ref s) => write!(f, "Internal error: {}", s),
|
|
Error::NotFound => write!(f, "Not found."),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl error::Error for Error {
|
|
fn description(&self) -> &str {
|
|
match *self {
|
|
Error::Argument(_) => "Bad arguments.",
|
|
Error::Internal(_) => "Internal error.",
|
|
Error::NotFound => "Not found.",
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<Error> for IronError {
|
|
fn from(e: Error) -> IronError {
|
|
match e {
|
|
Error::Argument(_) => IronError::new(e, status::Status::BadRequest),
|
|
Error::Internal(_) => IronError::new(e, status::Status::InternalServerError),
|
|
Error::NotFound => IronError::new(e, status::Status::NotFound),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<store::Error> for Error {
|
|
fn from(e: store::Error) -> Error {
|
|
match e {
|
|
store::Error::NotFoundErr => Error::NotFound,
|
|
_ => Error::Internal(e.to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// HTTP server allowing the registration of ApiEndpoint implementations.
|
|
pub struct ApiServer {
|
|
root: String,
|
|
router: Router,
|
|
mount: Mount,
|
|
server_listener: Option<Listening>,
|
|
}
|
|
|
|
impl ApiServer {
|
|
/// Creates a new ApiServer that will serve ApiEndpoint implementations
|
|
/// under the root URL.
|
|
pub fn new(root: String) -> ApiServer {
|
|
ApiServer {
|
|
root: root,
|
|
router: Router::new(),
|
|
mount: Mount::new(),
|
|
server_listener: None,
|
|
}
|
|
}
|
|
|
|
/// Starts the ApiServer at the provided address.
|
|
pub fn start<A: ToSocketAddrs>(&mut self, addr: A) -> Result<(), String> {
|
|
// replace this value to satisfy borrow checker
|
|
let r = mem::replace(&mut self.router, Router::new());
|
|
let mut m = mem::replace(&mut self.mount, Mount::new());
|
|
m.mount("/", r);
|
|
let result = Iron::new(m).http(addr);
|
|
let return_value = result.as_ref().map(|_| ()).map_err(|e| e.to_string());
|
|
self.server_listener = Some(result.unwrap());
|
|
return_value
|
|
}
|
|
|
|
/// Stops the API server
|
|
pub fn stop(&mut self) {
|
|
let r = mem::replace(&mut self.server_listener, None);
|
|
r.unwrap().close().unwrap();
|
|
}
|
|
|
|
/// Registers an iron handler (via mount)
|
|
pub fn register_handler<H: Handler>(&mut self, handler: H) -> &mut Mount {
|
|
self.mount.mount(&self.root, handler)
|
|
}
|
|
}
|