feat(ethapi): add eth cors settings#1021
Conversation
| allowed_origins = [] | ||
| # A list of methods the client is allowed to use with cross-domain requests | ||
| # Suggested methods if allowing origins: "GET", "OPTIONS", "HEAD", "POST" | ||
| allowed_methods = [] |
There was a problem hiding this comment.
I left these empty by default because there is no way to override them to be empty using an env var (empty strings are ignored by the config list parser).
fendermint/app/settings/src/lib.rs
Outdated
| } | ||
|
|
||
| impl TryInto<std::net::SocketAddr> for SocketAddress { | ||
| impl TryInto<SocketAddr> for SocketAddress { |
There was a problem hiding this comment.
Just some cleanups... can revert if annoying.
There was a problem hiding this comment.
I tend to prefer using fully-qualified type/trait names in trait implementations when they're stdlib or 3rd party types, to signal clearly that they're external. Will take the liberty to revert this in your branch.
There was a problem hiding this comment.
Makes sense! My IDE shows a warning if a trait/struct has a top level import, but the fully qualified path is used in the same file. That's what happened in this case.
| assert_eq!(settings.resolver.membership.static_subnets.len(), 2); | ||
| assert_eq!( | ||
| format!("{:?}", settings.eth.cors.allowed_origins), | ||
| "List([\"https://example.com\", \"https://www.example.org\"])" |
There was a problem hiding this comment.
Ugly, but no other way of testing this... there isn't a public API on AllowedOrigin to list its members.
There was a problem hiding this comment.
Just alphabetizing the dependencies... can revert if annoying. Some crates have ordered dependencies and other don't. I thought may as well clean up the ones I'm touching.
Signed-off-by: Sander Pick <[email protected]>
| { | ||
| let mut origins = Vec::new(); | ||
| while let Some(v) = seq.next_element::<String>()? { | ||
| if v == "*" { |
There was a problem hiding this comment.
A quick question, sometimes, there are situation such as wildcard subdomains, like *.examples.com, it seems it's not handled by the parsing here? Just curious will it work if it's only raw strings parsed here and the json rpc server can handle wildcard subdomain? Or actually we dont allow wildcard subdomains?
There was a problem hiding this comment.
Technically speaking wildcard subdomains aren't a proper origin. Given a request, the server can respond with one of...
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null
ie, "*", a specific domain, or none.
We could enable wildcard subdomains with some additional parsing + a predicate:
use tower_http::cors::{CorsLayer, AllowOrigin};
use http::{request::Parts as RequestParts, HeaderValue};
let layer = CorsLayer::new().allow_origin(AllowOrigin::predicate(
|origin: &HeaderValue, _request_parts: &RequestParts| {
origin.as_bytes().ends_with(b".rust-lang.org")
},
));
This way the server would respond with the full valid request origin. I don't have a strong opinion on how important it is to support this though.
There was a problem hiding this comment.
I guess my question is more like current RPC server library does not support AllowOrigin::from_str so that we have to parse the strings ourselves?
There was a problem hiding this comment.
You can parse a HeaderValue from string and then parse AllowOrigin from that, but that would only work if the parsing could handle String and Vec<String> as input:
"*"->HeaderValue->AllowOrigin"http://example.com"->HeaderValue->AllowOrigin["http://example.com", "http://example.org"]->Vec<HeaderValue>->AllowOrigin["*"]-> not parse-able without custom handling ("*"is not allowed in a list of you want to use theVec<HeaderValue>->AllowOriginparsing."*.example.org"-> not directly parse-able, need to use a predicate / closure
I originally took the String and Vec<String> as input approach, but it's not possible to provide a single String as input from the environment variables (they get parsed as Vec). Which means that without custom parsing, there would have been no way to use "*". The same applies to methods and headers. It's also less confusing to only allow a list in the config files (modeled after cometbft config).
|
@cryptoAtwill do we want to allow CORS requests that require authentication? If so, we'll need some additional handling:
|
fendermint/app/settings/src/lib.rs
Outdated
| } | ||
|
|
||
| impl TryInto<std::net::SocketAddr> for SocketAddress { | ||
| impl TryInto<SocketAddr> for SocketAddress { |
There was a problem hiding this comment.
I tend to prefer using fully-qualified type/trait names in trait implementations when they're stdlib or 3rd party types, to signal clearly that they're external. Will take the liberty to revert this in your branch.
|
Thanks for the contribution, @sanderpick! Looking forward to many more 💪 |
Second PR requested in a convo with @raulk.
This one adds eth CORS settings to control allowed origins, methods, and headers. It's modeled after the cometbft config, which includes the following settings under
[rpc]: