Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Support http requests #2

Merged
merged 6 commits into from
Apr 5, 2021
Merged

Conversation

njgheorghita
Copy link
Collaborator

@njgheorghita njgheorghita commented Mar 3, 2021

  • added clap library for cli arg parsing
  • added some tests for cli args
  • added support for http requests

@njgheorghita njgheorghita force-pushed the support-http branch 6 times, most recently from 9c128c9 to df818a8 Compare March 3, 2021 16:32
src/main.rs Outdated
T: Into<OsString> + Clone,
{
// TODO: things to configure:
// - infura project id (not just env var?)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Any further thoughts on this? At the moment, using just an env var makes testing slightly tricky. Some other options include a config file or a cli arg (i'm not a fan of the cli arg option, it would get rather tedious imo)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm okay leaving it as env var only for now. I think we'll want support for that at some point. (One plausible use case is as a colocated endpoint for a web server, where env var would be the nicest way to configure IMO)

So I guess we'll just have to figure out a way to test where we can mock out the env var.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, that seems reasonable. I think once we get CI setup, it'll help illuminate the best way forward. Also, from the docs...

Because the tests are running at the same time, make sure your tests don’t depend on each other or on any shared state, including a shared environment, such as the current working directory or environment variables.

Which seems to me rules out any tests that check for the presence of an env variable. From my tinkering around any test that manually cleared and reset the env var (to check for presence) would cause every other test to simultaneously fail.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, I think if we want to keep the env var long term, we would read the value in main() and pass it into the inner function call. Then, all layers beneath it are just tested with supplied arguments.

@njgheorghita njgheorghita marked this pull request as ready for review March 3, 2021 16:59
@njgheorghita
Copy link
Collaborator Author

First rust pr! So I'm sure there's plenty of room for improvement here, but it's ready for a first pass 👀

@njgheorghita
Copy link
Collaborator Author

ping @carver for 👀 ... not sure why, but you're not showing up in the Reviewers section at the top right of the pr. But maybe that's because this repo is still so fresh

@carver
Copy link
Collaborator

carver commented Mar 4, 2021

Thanks!

I assume you ran rustfmt or something. (I may not have) Just wondering why the IPC code is showing up as changed.

@carver
Copy link
Collaborator

carver commented Mar 4, 2021

First rust pr! So I'm sure there's plenty of room for improvement here, but it's ready for a first pass

Yeah, sort of the blind leading the blind here...

@carver
Copy link
Collaborator

carver commented Mar 4, 2021

I assume you ran rustfmt or something. (I may not have) Just wondering why the IPC code is showing up as changed.

Yeah, just confirmed that I left out the formatting last time. My bad, sorry for the extra work. Would you mind rebasing now? It will make the diff easier for me to read.

@carver
Copy link
Collaborator

carver commented Mar 5, 2021

A natural follow-up will be to figure out a way to do integration tests on the http and ipc servers. Maybe we can hit only the clientVersion endpoint for now, though we'll obviously want to test Infura endpoints eventually. Also, we'll probably want arbitrary backing URLs. That's important soon, so we don't hit Infura for real during tests, and later so we can support any type of endpoint (like alchemyapi.io).

(All for future PRs)

@carver
Copy link
Collaborator

carver commented Mar 5, 2021

Oh, also a reminder to update the README

@njgheorghita njgheorghita changed the title WIP - Support http requests Support http requests Mar 7, 2021
@njgheorghita
Copy link
Collaborator Author

@carver Ready for another 👀

Copy link
Collaborator

@carver carver left a comment

Choose a reason for hiding this comment

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

Looks good!

Cool that building the raw HTTP wasn't too bad.

For some of the comments, I mention follow-up work. Would you mind opening short issues for each of them that you don't end up fixing in this PR? (Including ones I said I'd do :P )

src/cli.rs Outdated
.default_value("2"),
)
.get_matches_from_safe(args)
.unwrap_or_else(|e| panic!("Unable to parse args: {}", e));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is equivalent to the simpler:

Suggested change
.unwrap_or_else(|e| panic!("Unable to parse args: {}", e));
.expect("Unable to parse args");

Notice that the expect panic includes the error message in this example: https://doc.rust-lang.org/std/result/enum.Result.html#method.expect

Copy link
Collaborator Author

@njgheorghita njgheorghita Mar 14, 2021

Choose a reason for hiding this comment

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

It turns out get_matches_from_safe has some peculiarities in terms of handling --help and --version and will panic if those are called. It felt weird to me to panic on help and version input (even though the help/version output is still displayed), so I added some handling to exit gracefully on those calls and panic for any other errors. Lmk if you feel differently about how this should be handled

Copy link
Collaborator

@carver carver Mar 16, 2021

Choose a reason for hiding this comment

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

Oh weird. Well I think if we're not going to do anything clever on a failure, maybe we should just use:
https://docs.rs/clap/2.33.3/clap/struct.App.html#method.get_matches_from . It seems to just have an implicit unwrap under the hood.

src/cli.rs Outdated
println!("Launching Trin...");
let protocol = matches.value_of("protocol").unwrap();
let endpoint = matches.value_of("endpoint").unwrap();
let endpoint = match endpoint.parse::<u32>() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Waiting to parse the http port until we know the protocol is http gives two benefits:

  1. in ipc case, we can compare http_port to "7878". That can now be a reused constant in the validation and the configuration setup, instead of duplicated in a couple places.
  2. tiny performance benefit on ipc runs

Copy link
Collaborator Author

@njgheorghita njgheorghita Mar 14, 2021

Choose a reason for hiding this comment

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

I found a clap macro (value_t!) that simplifies the code parsing/casting the cli args. How strongly do you feel about this? I see the benefit of a constant.. But, I've also tried a couple variants and haven't found a reasonably simple solution (but, my rust type-fu is weak so who knows what obvious solutions i'm missing).

  • since TrinConfig has defined http_port: u32, we eventually have to cast a const http_port: String = "8545" into an int when we use the default constant (in both the http & ipc cases)
  • the default_arg() param for the clap parser only accepts strings, so we have to do some casting if const http_port: u32 = 8545, and early tinkering has only resulted in a pandoras box of more complicated compiler errors
  • A performance benefit is somewhat irrelevant if a user selects ipc and a custom http_port since we error out. In the case that the user just selects ipc, we will still have to cast a const http_port: String = "8545" into an int to feed into TrinConfig

I'm happy to keep tinkering with this, just reporting my initial findings

Comment on lines +214 to +220
let obj = obj.unwrap();
assert!(obj.is_object());
assert_eq!(obj["jsonrpc"], "2.0");
let request_id = obj.get("id").unwrap();
let method = obj.get("method").unwrap();

let response = match method.as_str().unwrap() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I know the error handling was already this way in the IPC code, but it's bad news. Sending bad input data to trin should reply with an error, instead of crashing trin.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

👍 I've added this to be tackled in the refactor issue #6

@njgheorghita
Copy link
Collaborator Author

@carver Sorry, was a bit sporadic in wrapping this up. Just a couple of last comments if you have any thoughts, and then I'll get this merged

@njgheorghita
Copy link
Collaborator Author

@carver Ahh, I don't have write access to this repo - so for now I'll have to leave merging up to you if it checks out on your end

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants