Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

APIs wildcards and simple arithmetic. #5402

Merged
merged 1 commit into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion parity/cli/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ API and Console Options:
(default: {flag_jsonrpc_cors:?})
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
interface. APIS is a comma-delimited list of API
name. Possible name are web3, eth, net, personal,
name. Possible name are all, safe, web3, eth, net, personal,
parity, parity_set, traces, rpc, parity_accounts.
You can also disable a specific API by putting '-' in the front: all,-personal
(default: {flag_jsonrpc_apis}).
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will
validate the Host header sent by the browser, it
Expand Down
17 changes: 6 additions & 11 deletions parity/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use ethcore::miner::{MinerOptions, Banning, StratumOptions};
use ethcore::verification::queue::VerifierSettings;

use rpc::{IpcConfiguration, HttpConfiguration};
use rpc_apis::ApiSet;
use ethcore_rpc::NetworkSettings;
use cache::CacheConfig;
use helpers::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_price, replace_home, replace_home_for_db,
Expand Down Expand Up @@ -716,16 +717,7 @@ impl Configuration {
.collect();

if self.args.flag_geth {
apis.push("personal");
}

if self.args.flag_public_node {
apis.retain(|api| {
match *api {
"eth" | "net" | "parity" | "rpc" | "web3" => true,
_ => false
}
});
apis.insert(0, "personal");
}

apis.join(",")
Expand Down Expand Up @@ -786,7 +778,10 @@ impl Configuration {
enabled: self.rpc_enabled(),
interface: self.rpc_interface(),
port: self.args.flag_rpcport.unwrap_or(self.args.flag_jsonrpc_port),
apis: self.rpc_apis().parse()?,
apis: match self.args.flag_public_node {
false => self.rpc_apis().parse()?,
true => self.rpc_apis().parse::<ApiSet>()?.retain(ApiSet::PublicContext),
},
hosts: self.rpc_hosts(),
cors: self.rpc_cors(),
threads: match self.args.flag_jsonrpc_threads {
Expand Down
100 changes: 87 additions & 13 deletions parity/rpc_apis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,17 @@ impl FromStr for Api {

#[derive(Debug, Clone)]
pub enum ApiSet {
// Safe context (like token-protected WS interface)
SafeContext,
// Unsafe context (like jsonrpc over http)
UnsafeContext,
// Public context (like public jsonrpc over http)
PublicContext,
// All possible APIs
All,
// Local "unsafe" context and accounts access
IpcContext,
// Fixed list of APis
List(HashSet<Api>),
}

Expand All @@ -105,10 +113,30 @@ impl FromStr for ApiSet {
type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.split(',')
.map(Api::from_str)
.collect::<Result<_, _>>()
.map(ApiSet::List)
let mut apis = HashSet::new();

for api in s.split(',') {
match api {
"all" => {
apis.extend(ApiSet::All.list_apis());
},
"safe" => {
// Safe APIs are those that are safe even in UnsafeContext.
apis.extend(ApiSet::UnsafeContext.list_apis());
},
// Remove the API
api if api.starts_with("-") => {
let api = api[1..].parse()?;
apis.remove(&api);
},
api => {
let api = api.parse()?;
apis.insert(api);
},
}
}

Ok(ApiSet::List(apis))
}
}

Expand Down Expand Up @@ -152,21 +180,41 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
}

impl ApiSet {
/// Retains only APIs in given set.
pub fn retain(self, set: Self) -> Self {
ApiSet::List(&self.list_apis() & &set.list_apis())
}

pub fn list_apis(&self) -> HashSet<Api> {
let mut safe_list = vec![Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc]
.into_iter().collect();
let mut public_list = vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Rpc,
].into_iter().collect();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in places like these I wish we had an "iter" macro in the standard library: http://play.integer32.com/?gist=d0bf3fcbfcbb35ad8752ed5be30bda64&version=undefined

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could skip the vec! and just use an array.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, that too. but then you have to either have a HashSet<&Api> or add a Clone impl

match *self {
ApiSet::List(ref apis) => apis.clone(),
ApiSet::UnsafeContext => safe_list,
ApiSet::PublicContext => public_list,
ApiSet::UnsafeContext => {
public_list.insert(Api::Traces);
public_list
},
ApiSet::IpcContext => {
safe_list.insert(Api::ParityAccounts);
safe_list
public_list.insert(Api::Traces);
public_list.insert(Api::ParityAccounts);
public_list
},
ApiSet::SafeContext => {
safe_list.insert(Api::ParityAccounts);
safe_list.insert(Api::ParitySet);
safe_list.insert(Api::Signer);
safe_list
public_list.insert(Api::Traces);
public_list.insert(Api::ParityAccounts);
public_list.insert(Api::ParitySet);
public_list.insert(Api::Signer);
public_list
},
ApiSet::All => {
public_list.insert(Api::Traces);
public_list.insert(Api::ParityAccounts);
public_list.insert(Api::ParitySet);
public_list.insert(Api::Signer);
public_list.insert(Api::Personal);
public_list
},
}
}
Expand Down Expand Up @@ -340,4 +388,30 @@ mod test {
].into_iter().collect();
assert_eq!(ApiSet::SafeContext.list_apis(), expected);
}

#[test]
fn test_all_apis() {
assert_eq!("all".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
Api::Personal
].into_iter().collect()));
}

#[test]
fn test_all_without_personal_apis() {
assert_eq!("personal,all,-personal".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
Api::ParityAccounts,
Api::ParitySet, Api::Signer,
].into_iter().collect()));
}

#[test]
fn test_safe_parsing() {
assert_eq!("safe".parse::<ApiSet>().unwrap(), ApiSet::List(vec![
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
].into_iter().collect()));
}
}