Skip to content

Commit

Permalink
Update hyper to version 0.12.
Browse files Browse the repository at this point in the history
* Replace `tokio_core` with `tokio`.

* `server_utils::reactor::Remote` has been renamed to `Executor`.
  The `Shared` variant now contains a `tokio::runtime::TaskExecutor`.
  This may need to be changed to a trait object (of
  `tokio::executor::Executor`) or be otherwise abstracted to conceal the
  type in the public API.

* Bump crate versions to 0.9
  • Loading branch information
c0gent committed Sep 14, 2018
1 parent 2ebc530 commit 615e04a
Show file tree
Hide file tree
Showing 33 changed files with 527 additions and 464 deletions.
4 changes: 2 additions & 2 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ homepage = "https://github.com/paritytech/jsonrpc"
repository = "https://github.com/paritytech/jsonrpc"
license = "MIT"
name = "jsonrpc-core"
version = "8.0.2"
version = "9.0.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
keywords = ["jsonrpc", "json-rpc", "json", "rpc", "serde"]
documentation = "https://paritytech.github.io/jsonrpc/jsonrpc_core/index.html"
Expand All @@ -19,7 +19,7 @@ categories = [

[dependencies]
log = "0.4"
futures = "0.1.6"
futures = "~0.1.6"
serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion core/src/calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use futures::{Future, IntoFuture};
use BoxFuture;

/// Metadata trait
pub trait Metadata: Clone + Send + 'static {}
pub trait Metadata: Clone + Send + Sync + 'static {}
impl Metadata for () {}
impl<T: Metadata> Metadata for Option<T> {}
impl<T: Metadata> Metadata for Box<T> {}
Expand Down
8 changes: 4 additions & 4 deletions http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ homepage = "https://github.com/paritytech/jsonrpc"
repository = "https://github.com/paritytech/jsonrpc"
license = "MIT"
name = "jsonrpc-http-server"
version = "8.0.1"
version = "9.0.0"
authors = ["debris <marek.kotewicz@gmail.com>"]
keywords = ["jsonrpc", "json-rpc", "json", "rpc", "server"]
documentation = "https://paritytech.github.io/jsonrpc/jsonrpc_http_server/index.html"

[dependencies]
hyper = "0.11"
jsonrpc-core = { version = "8.0", path = "../core" }
jsonrpc-server-utils = { version = "8.0", path = "../server-utils" }
hyper = "0.12"
jsonrpc-core = { version = "9.0", path = "../core" }
jsonrpc-server-utils = { version = "9.0", path = "../server-utils" }
log = "0.4"
net2 = "0.2"
unicase = "2.0"
Expand Down
8 changes: 3 additions & 5 deletions http/examples/http_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ extern crate jsonrpc_http_server;

use jsonrpc_http_server::{ServerBuilder, hyper, RestApi};
use jsonrpc_http_server::jsonrpc_core::*;
use self::hyper::header;

#[derive(Default, Clone)]
struct Meta {
Expand All @@ -26,10 +25,9 @@ fn main() {
let server = ServerBuilder::new(io)
.rest_api(RestApi::Unsecure)
// You can also implement `MetaExtractor` trait and pass a struct here.
.meta_extractor(|req: &hyper::Request| {
let auth = req.headers()
.get::<header::Authorization<header::Bearer>>();
let auth = auth.map(|h| h.token.clone());
.meta_extractor(|req: &hyper::Request<hyper::Body>| {
let auth = req.headers().get(hyper::header::AUTHORIZATION)
.map(|h| h.to_str().expect("Invalid authorization value").to_owned());

Meta { auth }
})
Expand Down
4 changes: 2 additions & 2 deletions http/examples/http_middleware.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fn main() {

let server = ServerBuilder::new(io)
.cors(DomainsValidation::AllowOnly(vec![AccessControlAllowOrigin::Null]))
.request_middleware(|request: hyper::server::Request| {
if request.path() == "/status" {
.request_middleware(|request: hyper::Request<hyper::Body>| {
if request.uri() == "/status" {
Response::ok("Server running OK.").into()
} else {
request.into()
Expand Down
114 changes: 59 additions & 55 deletions http/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ use Rpc;
use std::{fmt, mem, str};
use std::sync::Arc;

use hyper::{self, mime, server, Method};
use hyper::header::{self, Headers};
use unicase::Ascii;
use hyper::{self, service::Service, Body, Method};
use hyper::header::{self, HeaderMap, HeaderValue};

use jsonrpc::{self as core, FutureResult, Metadata, Middleware, NoopMiddleware};
use jsonrpc::{self as core, FutureResult, Metadata, Middleware, NoopMiddleware, FutureRpcResult};
use jsonrpc::futures::{Future, Poll, Async, Stream, future};
use jsonrpc::serde_json;
use response::Response;
Expand Down Expand Up @@ -52,13 +51,13 @@ impl<M: Metadata, S: Middleware<M>> ServerHandler<M, S> {
}
}

impl<M: Metadata, S: Middleware<M>> server::Service for ServerHandler<M, S> {
type Request = server::Request;
type Response = server::Response;
impl<M: Metadata, S: Middleware<M>> Service for ServerHandler<M, S> {
type ReqBody = Body;
type ResBody = Body;
type Error = hyper::Error;
type Future = Handler<M, S>;

fn call(&self, request: Self::Request) -> Self::Future {
fn call(&mut self, request: hyper::Request<Self::ReqBody>) -> Self::Future {
let is_host_allowed = utils::is_host_allowed(&request, &self.allowed_hosts);
let action = self.middleware.on_request(request);

Expand Down Expand Up @@ -102,11 +101,11 @@ impl<M: Metadata, S: Middleware<M>> server::Service for ServerHandler<M, S> {
pub enum Handler<M: Metadata, S: Middleware<M>> {
Rpc(RpcHandler<M, S>),
Error(Option<Response>),
Middleware(Box<Future<Item=server::Response, Error=hyper::Error> + Send>),
Middleware(Box<Future<Item = hyper::Response<Body>, Error = hyper::Error> + Send>),
}

impl<M: Metadata, S: Middleware<M>> Future for Handler<M, S> {
type Item = server::Response;
type Item = hyper::Response<Body>;
type Error = hyper::Error;

fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
Expand Down Expand Up @@ -140,7 +139,7 @@ impl<M, F> RpcPollState<M, F> where
}

type FutureResponse<F> = future::Map<
future::Either<future::FutureResult<Option<core::Response>, ()>, F>,
future::Either<future::FutureResult<Option<core::Response>, ()>, FutureRpcResult<F>>,
fn(Option<core::Response>) -> Response,
>;

Expand All @@ -149,7 +148,7 @@ enum RpcHandlerState<M, F> where
F: Future<Item = Option<core::Response>, Error = ()>,
{
ReadingHeaders {
request: server::Request,
request: hyper::Request<Body>,
cors_domains: CorsDomains,
continue_on_invalid_cors: bool,
},
Expand Down Expand Up @@ -196,23 +195,23 @@ pub struct RpcHandler<M: Metadata, S: Middleware<M>> {
jsonrpc_handler: Rpc<M, S>,
state: RpcHandlerState<M, S::Future>,
is_options: bool,
cors_header: cors::CorsHeader<header::AccessControlAllowOrigin>,
cors_header: cors::CorsHeader<header::HeaderValue>,
cors_max_age: Option<u32>,
rest_api: RestApi,
health_api: Option<(String, String)>,
max_request_body_size: usize,
}

impl<M: Metadata, S: Middleware<M>> Future for RpcHandler<M, S> {
type Item = server::Response;
type Item = hyper::Response<Body>;
type Error = hyper::Error;

fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
let new_state = match mem::replace(&mut self.state, RpcHandlerState::Done) {
RpcHandlerState::ReadingHeaders { request, cors_domains, continue_on_invalid_cors, } => {
// Read cors header
self.cors_header = utils::cors_header(&request, &cors_domains);
self.is_options = *request.method() == Method::Options;
self.is_options = *request.method() == Method::OPTIONS;
// Read other headers
RpcPollState::Ready(self.read_headers(request, continue_on_invalid_cors))
},
Expand Down Expand Up @@ -268,7 +267,7 @@ impl<M: Metadata, S: Middleware<M>> Future for RpcHandler<M, S> {
let (new_state, is_ready) = new_state.decompose();
match new_state {
RpcHandlerState::Writing(res) => {
let mut response: server::Response = res.into();
let mut response: hyper::Response<Body> = res.into();
let cors_header = mem::replace(&mut self.cors_header, cors::CorsHeader::Invalid);
Self::set_response_headers(
response.headers_mut(),
Expand All @@ -291,7 +290,7 @@ impl<M: Metadata, S: Middleware<M>> Future for RpcHandler<M, S> {
}

// Intermediate and internal error type to better distinguish
// error cases occuring during request body processing.
// error cases occurring during request body processing.
enum BodyError {
Hyper(hyper::Error),
Utf8(str::Utf8Error),
Expand All @@ -307,7 +306,7 @@ impl From<hyper::Error> for BodyError {
impl<M: Metadata, S: Middleware<M>> RpcHandler<M, S> {
fn read_headers(
&self,
request: server::Request,
request: hyper::Request<Body>,
continue_on_invalid_cors: bool,
) -> RpcHandlerState<M, S::Future> {
if self.cors_header == cors::CorsHeader::Invalid && !continue_on_invalid_cors {
Expand All @@ -317,34 +316,34 @@ impl<M: Metadata, S: Middleware<M>> RpcHandler<M, S> {
let metadata = self.jsonrpc_handler.extractor.read_metadata(&request);

// Proceed
match *request.method() {
match request.method().clone() {
// Validate the ContentType header
// to prevent Cross-Origin XHRs with text/plain
Method::Post if Self::is_json(request.headers().get::<header::ContentType>()) => {
Method::POST if Self::is_json(request.headers().get("content-type")) => {
let uri = if self.rest_api != RestApi::Disabled { Some(request.uri().clone()) } else { None };
RpcHandlerState::ReadingBody {
metadata,
request: Default::default(),
uri,
body: request.body(),
body: request.into_body(),
}
},
Method::Post if self.rest_api == RestApi::Unsecure && request.uri().path().split('/').count() > 2 => {
Method::POST if self.rest_api == RestApi::Unsecure && request.uri().path().split('/').count() > 2 => {
RpcHandlerState::ProcessRest {
metadata,
uri: request.uri().clone(),
}
},
// Just return error for unsupported content type
Method::Post => {
Method::POST => {
RpcHandlerState::Writing(Response::unsupported_content_type())
},
// Don't validate content type on options
Method::Options => {
Method::OPTIONS => {
RpcHandlerState::Writing(Response::empty())
},
// Respond to health API request if there is one configured.
Method::Get if self.health_api.as_ref().map(|x| &*x.0) == Some(request.uri().path()) => {
Method::GET if self.health_api.as_ref().map(|x| &*x.0) == Some(request.uri().path()) => {
RpcHandlerState::ProcessHealth {
metadata,
method: self.health_api.as_ref()
Expand Down Expand Up @@ -479,48 +478,53 @@ impl<M: Metadata, S: Middleware<M>> RpcHandler<M, S> {
}

fn set_response_headers(
headers: &mut Headers,
headers: &mut HeaderMap,
is_options: bool,
cors_header: Option<header::AccessControlAllowOrigin>,
cors_header: Option<HeaderValue>,
cors_max_age: Option<u32>,
) {
if is_options {
headers.set(header::Allow(vec![
Method::Options,
Method::Post,
]));
headers.set(header::Accept(vec![
header::qitem(mime::APPLICATION_JSON)
]));
headers.append(header::ALLOW, Method::OPTIONS.as_str().parse().expect("`Method` will always parse; qed"));
headers.append(header::ALLOW, Method::POST.as_str().parse().expect("`Method` will always parse; qed"));

headers.append(header::ACCEPT, HeaderValue::from_static("application/json"));

}

if let Some(cors_domain) = cors_header {
headers.set(header::AccessControlAllowMethods(vec![
Method::Options,
Method::Post
]));
headers.set(header::AccessControlAllowHeaders(vec![
Ascii::new("origin".to_owned()),
Ascii::new("content-type".to_owned()),
Ascii::new("accept".to_owned()),
]));
if let Some(cors_max_age) = cors_max_age {
headers.set(header::AccessControlMaxAge(cors_max_age));
headers.append(header::ACCESS_CONTROL_ALLOW_METHODS, Method::OPTIONS.as_str().parse()
.expect("`Method` will always parse; qed"));
headers.append(header::ACCESS_CONTROL_ALLOW_METHODS, Method::POST.as_str().parse()
.expect("`Method` will always parse; qed"));

headers.append(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static("origin"));
headers.append(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static("content-type"));
headers.append(header::ACCESS_CONTROL_ALLOW_HEADERS, HeaderValue::from_static("accept"));

if let Some(cma) = cors_max_age {
headers.append(header::ACCESS_CONTROL_MAX_AGE, HeaderValue::from_str(&cma.to_string())
.expect("`u32` will always parse; qed"));
}
headers.set(cors_domain);
headers.set(header::Vary::Items(vec![
Ascii::new("origin".to_owned())
]));

headers.append(header::ACCESS_CONTROL_ALLOW_ORIGIN, cors_domain);

headers.append(header::VARY, HeaderValue::from_static("origin"));
}
}

fn is_json(content_type: Option<&header::ContentType>) -> bool {
const APPLICATION_JSON_UTF_8: &str = "application/json; charset=utf-8";

/// Returns true if the `content_type` header indicates a valid JSON
/// message.
fn is_json(content_type: Option<&header::HeaderValue>) -> bool {
match content_type {
Some(&header::ContentType(ref mime))
if *mime == mime::APPLICATION_JSON || *mime == APPLICATION_JSON_UTF_8 => true,
_ => false
Some(header_val) => {
match header_val.to_str() {
Ok(header_str) => {
header_str == "application/json" || header_str == "application/json; charset=utf-8"
},
Err(_) => false,
}
}
_ => false,
}
}
}
Loading

0 comments on commit 615e04a

Please sign in to comment.