Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add POST-requests handler to multichain-api-gateway #54

Merged
merged 18 commits into from
Jul 8, 2022

Conversation

kuksag
Copy link
Contributor

@kuksag kuksag commented Jul 4, 2022

This lets us make POST requests to our API (e.g. contract verify request).
It's done in the way that the incoming request body is passed through to the following calls.
Added 1 integration test that makes a call as described in an example here.

@kuksag kuksag requested a review from rimrakhimov July 4, 2022 12:13
@kuksag kuksag marked this pull request as draft July 6, 2022 09:49
@@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
actix-web = "4"
awc = { version = "3.0.0", features = ["openssl"] }
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Somehow default awc can't work with ssl
actix/actix-web#1045

App, HttpRequest, HttpServer, Responder,
};
use awc::Client;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I decided to try replace "reqwest" client with actix-web client (awc) since we use actix-web server. It takes almost the same lines of code.
Let me know what you think; it's easy to rollback to "reqwest" if needed.

headers: &HeaderMap,
) -> Vec<(Instance, String)> {
let client = Client::builder()
.timeout(std::time::Duration::from_secs(60))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Default value for a timeout is 1 second.
This request takes 48 second on my pc

Copy link
Member

Choose a reason for hiding this comment

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

I believe the timeout may greatly depend on the request. Is it possible to look at current Elixir implementation of those requests and check what the timeout is in their case and if there is any at all?

Just as an idea, it may be great to have that parameter configurable, however, I am still interested in current instances timeouts

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • Made it configurable from config
  • Clarified what is the default timeout: it's 60 seconds for all methods

Comment on lines 72 to 81
let str_response = match response {
Ok(mut response) => match response.body().await {
Ok(bytes) => match str::from_utf8(bytes.as_ref()) {
Ok(str) => str.to_string(),
Err(utf8_error) => utf8_error.to_string(),
},
Err(payload_error) => payload_error.to_string(),
},
Err(send_request_error) => send_request_error.to_string(),
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the whole block is looking kind of messy, but I don't know what to do with it, since:

  • response.body().await is needed to be called outside of any map
  • chain computation via and_then can't be used because we have different result and error types on every step

Copy link
Member

Choose a reason for hiding this comment

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

I suggest to create a new private method

async fn make_request(request: ClientRequest, body: Bytes) -> Result<String, Box<dyn Error>>

inside an ApiRequest and use ? to convert between errors there

Comment on lines 75 to 76
Ok(str) => str.to_string(),
Err(utf8_error) => utf8_error.to_string(),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can use unwrap_or_else here, but I'm not sure if it will add more readability

Copy link
Member

Choose a reason for hiding this comment

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

Personally, in my opinion, it would be more readable. You would just have to map success result into String before unwrapping

Comment on lines +101 to +102
serde_json::from_str(&value)
.unwrap_or_else(|e| Value::String(format!("{}: {}\n", e, value))),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before that, when the server returned an error, the error was replaced withexpected value at column 1 at row 1 (json parsing failed). Now we preserve both errors

@kuksag kuksag marked this pull request as ready for review July 6, 2022 11:44
@kuksag kuksag requested a review from sevenzing July 6, 2022 11:44
headers: &HeaderMap,
) -> Vec<(Instance, String)> {
let client = Client::builder()
.timeout(std::time::Duration::from_secs(60))
Copy link
Member

Choose a reason for hiding this comment

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

I believe the timeout may greatly depend on the request. Is it possible to look at current Elixir implementation of those requests and check what the timeout is in their case and if there is any at all?

Just as an idea, it may be great to have that parameter configurable, however, I am still interested in current instances timeouts

Comment on lines 75 to 76
Ok(str) => str.to_string(),
Err(utf8_error) => utf8_error.to_string(),
Copy link
Member

Choose a reason for hiding this comment

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

Personally, in my opinion, it would be more readable. You would just have to map success result into String before unwrapping

Comment on lines 72 to 81
let str_response = match response {
Ok(mut response) => match response.body().await {
Ok(bytes) => match str::from_utf8(bytes.as_ref()) {
Ok(str) => str.to_string(),
Err(utf8_error) => utf8_error.to_string(),
},
Err(payload_error) => payload_error.to_string(),
},
Err(send_request_error) => send_request_error.to_string(),
};
Copy link
Member

Choose a reason for hiding this comment

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

I suggest to create a new private method

async fn make_request(request: ClientRequest, body: Bytes) -> Result<String, Box<dyn Error>>

inside an ApiRequest and use ? to convert between errors there

@kuksag kuksag requested a review from rimrakhimov July 7, 2022 09:20
@rimrakhimov rimrakhimov merged commit bbf7125 into main Jul 8, 2022
@rimrakhimov rimrakhimov deleted the multichain-api branch July 8, 2022 08:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants