Newer
Older
// Copyright 2019-2021 Parity Technologies (UK) Ltd.
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the
// Software without restriction, including without
// limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice
// shall be included in all copies or substantial portions
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
use std::convert::Infallible;
Niklas Adolfsson
committed
use std::net::{SocketAddr, TcpListener as StdTcpListener};
use std::pin::Pin;
use std::task::{Context, Poll};
use crate::response;
use crate::response::{internal_error, malformed};
use futures_channel::mpsc;
use futures_util::future::FutureExt;
use futures_util::stream::{StreamExt, TryStreamExt};
use futures_util::TryFutureExt;
use hyper::body::HttpBody;
use hyper::header::{HeaderMap, HeaderValue};
use hyper::server::{conn::AddrIncoming, Builder as HyperBuilder};
use hyper::service::{make_service_fn, Service};
use hyper::{Body, Error as HyperError, Method};
use jsonrpsee_core::error::{Error, GenericTransportError};
use jsonrpsee_core::http_helpers::{self, read_body};
use jsonrpsee_core::logger::{self, HttpLogger as Logger};
use jsonrpsee_core::server::access_control::AccessControl;
use jsonrpsee_core::server::helpers::{prepare_error, MethodResponse};
use jsonrpsee_core::server::helpers::{BatchResponse, BatchResponseBuilder};
use jsonrpsee_core::server::resource_limiting::Resources;
use jsonrpsee_core::server::rpc_module::{MethodKind, Methods};
use jsonrpsee_core::tracing::{rx_log_from_json, rx_log_from_str, tx_log_from_str, RpcTracing};
use jsonrpsee_core::TEN_MB_SIZE_BYTES;
use jsonrpsee_types::error::{ErrorCode, ErrorObject, BATCHES_NOT_SUPPORTED_CODE, BATCHES_NOT_SUPPORTED_MSG};
use jsonrpsee_types::{Id, Notification, Params, Request};
use serde::de::StdError;
use serde_json::value::RawValue;
Niklas Adolfsson
committed
use tokio::net::{TcpListener, ToSocketAddrs};
use tower::layer::util::Identity;
use tracing_futures::Instrument;
type Notif<'a> = Notification<'a, Option<&'a RawValue>>;
/// Builder to create JSON-RPC HTTP server.
#[derive(Debug)]
pub struct Builder<B = Identity, L = ()> {
/// Access control based on HTTP headers.
Quake Wang
committed
max_response_body_size: u32,
batch_requests_supported: bool,
Niklas Adolfsson
committed
/// Custom tokio runtime to run the server on.
tokio_runtime: Option<tokio::runtime::Handle>,
max_log_length: u32,
service_builder: tower::ServiceBuilder<B>,
}
impl Default for Builder {
fn default() -> Self {
Self {
access_control: AccessControl::default(),
Quake Wang
committed
max_response_body_size: TEN_MB_SIZE_BYTES,
batch_requests_supported: true,
resources: Resources::default(),
tokio_runtime: None,
max_log_length: 4096,
service_builder: tower::ServiceBuilder::new(),
/// Create a default server builder.
pub fn new() -> Self {
Self::default()
}
}
impl<B, L> Builder<B, L> {
/// Add a logger to the builder [`Logger`](../jsonrpsee_core/logger/trait.Logger.html).
/// # Examples
///
/// use std::{time::Instant, net::SocketAddr};
/// use jsonrpsee_core::logger::{HttpLogger, Headers, MethodKind, Params};
/// use jsonrpsee_http_server::HttpServerBuilder;
///
/// impl HttpLogger for MyLogger {
/// // Called once the HTTP request is received, it may be a single JSON-RPC call
/// // or batch.
/// fn on_request(&self, _remote_addr: SocketAddr, _request: &Request<hyper::Body>) -> Instant {
/// // Called once a single JSON-RPC method call is processed, it may be called multiple times
/// // on batches.
/// fn on_call(&self, method_name: &str, params: Params, kind: MethodKind) {
/// println!("Call to method: '{}' params: {:?}, kind: {}", method_name, params, kind);
/// }
///
/// // Called once a single JSON-RPC call is completed, it may be called multiple times
/// // on batches.
/// fn on_result(&self, method_name: &str, success: bool, started_at: Instant) {
/// println!("Call to '{}' took {:?}", method_name, started_at.elapsed());
/// }
/// // Called the entire JSON-RPC is completed, called on once for both single calls or batches.
/// fn on_response(&self, result: &str, started_at: Instant) {
/// println!("complete JSON-RPC response: {}, took: {:?}", result, started_at.elapsed());
/// let builder = HttpServerBuilder::new().set_logger(MyLogger);
pub fn set_logger<T: Logger>(self, logger: T) -> Builder<B, T> {
access_control: self.access_control,
max_request_body_size: self.max_request_body_size,
Quake Wang
committed
max_response_body_size: self.max_response_body_size,
batch_requests_supported: self.batch_requests_supported,
resources: self.resources,
tokio_runtime: self.tokio_runtime,
max_log_length: self.max_log_length,
service_builder: self.service_builder,
/// Sets the maximum size of a request body in bytes (default is 10 MiB).
pub fn max_request_body_size(mut self, size: u32) -> Self {
self.max_request_body_size = size;
self
}
Quake Wang
committed
/// Sets the maximum size of a response body in bytes (default is 10 MiB).
pub fn max_response_body_size(mut self, size: u32) -> Self {
self.max_response_body_size = size;
self
}
/// Sets access control settings.
pub fn set_access_control(mut self, acl: AccessControl) -> Self {
self.access_control = acl;
self
}
/// Enables or disables support of [batch requests](https://www.jsonrpc.org/specification#batch).
/// By default, support is enabled.
pub fn batch_requests_supported(mut self, supported: bool) -> Self {
self.batch_requests_supported = supported;
self
}
/// Register a new resource kind. Errors if `label` is already registered, or if the number of
/// registered resources on this server instance would exceed 8.
///
Niklas Adolfsson
committed
/// See the module documentation for [`resource_limiting`](../jsonrpsee_utils/server/resource_limiting/index.html#resource-limiting)
pub fn register_resource(mut self, label: &'static str, capacity: u16, default: u16) -> Result<Self, Error> {
self.resources.register(label, capacity, default)?;
Ok(self)
}
Loading full blame...