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

Add custom HttpStatusCodeProvider to adjust to JSON-RPC 2.0 conventions #1522

Merged

Conversation

marcciosilva
Copy link
Contributor

@marcciosilva marcciosilva commented May 5, 2021

Description

Since the jsonrpc4j keeps on returning internal error HTTP status codes upon JSON-RPC errors (it shouldn't, since the transport layer protocol should be agnostic to JSON-RPC), we add custom logic to handle them.

Inspired on this, any valid JSON-RPC request should generate a JSON-RPC response, the HTTP status code should be 200. No matter if the response is a success or error response.
Calling a method that hasn't been enabled or a method that doesn't exist are valid JSON-RPC requests, therefore the expected response is a JSON-RPC error (and status code = 200)
Any invalid JSON-RPC request (malformed JSON, etc.) should generate a 400 status code.

Motivation and Context

Issue #1387

How Has This Been Tested?

Unit testing

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • Tests for the changes have been added (for bug fixes / features)
  • Requires Activation Code (Hard Fork)

@marcciosilva marcciosilva force-pushed the fix-json-rpc-http-response-status branch from b5a0475 to 382315d Compare May 6, 2021 14:34
@marcciosilva marcciosilva marked this pull request as ready for review May 6, 2021 14:34
import static com.googlecode.jsonrpc4j.ErrorResolver.JsonError;
import static com.googlecode.jsonrpc4j.ErrorResolver.JsonError.*;

public class Web3HttpStatusCodeProvider implements HttpStatusCodeProvider {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Based on this class (which we used prior to this change).
FYI: version 1.6 of jsonrpc4j doesn't adjust error handling to the JSON-RPC guidelines, that's why I decided not to update it this PR.

*/
@Override
public Integer getJsonRpcCode(int httpStatusCode) {
throw new UnsupportedOperationException("Cannot possibly determine a single JSON RPC from an HTTP status code");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

jsonrpc4j maps each supported HTTP status code to a single JSON-RPC code - this is not entirely correct in my opinion, since a single HTTP code could map to N JSON-RPC codes (this even happens in jsonrpc4j).
Since we don't use this method in rskj, I decided to leave it like this.

Copy link
Contributor

Choose a reason for hiding this comment

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

Take into account that a JSON RPC request could be an array of valid JSON RPC requests. Is this case covered in the process of responses/responses code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since I just swapped the DefaultHttpStatusCodeProvider (from jsonrpc4j library) for a custom implementation that adheres to the same signatures (but mapping HTTP codes differently), the actual processing of requests is not involved (this is only used in the response handling part of the pipeline).

@marcciosilva
Copy link
Contributor Author

pipeline: run

@marcciosilva marcciosilva reopened this May 6, 2021
@fedejinich
Copy link
Contributor

pipeline:run

*/
@Override
public Integer getJsonRpcCode(int httpStatusCode) {
throw new UnsupportedOperationException("Cannot possibly determine a single JSON RPC from an HTTP status code");
Copy link
Contributor

Choose a reason for hiding this comment

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

Take into account that a JSON RPC request could be an array of valid JSON RPC requests. Is this case covered in the process of responses/responses code?

}

private boolean isBadRequestResultCode(int resultCode) {
Optional<JsonError> optionalJsonError = BAD_REQUEST_JSON_ERRORS
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not a simple contains? Or a map of JSON ERROR to boolean (true == it is a bad request result code)?

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 didn't use a contains because it's a list of JsonError and what I receive is an integer (somehow I have to reach the code member variable).
Let me know what you think about the change I just uploaded (instead of using a JsonError list y directly use a collection of the codes, then I just use a contains).

@marcciosilva marcciosilva requested a review from ajlopezrsk May 7, 2021 14:13
@nagarev
Copy link
Contributor

nagarev commented May 7, 2021

pipeline:run

Vovchyk
Vovchyk previously approved these changes May 7, 2021
Copy link
Contributor

@Vovchyk Vovchyk left a comment

Choose a reason for hiding this comment

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

lgtm

import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpHeaders.Values.APPLICATION_JSON;

public class Web3ResultHttpResponseHandler extends SimpleChannelInboundHandler<Web3Result> {

private HttpStatusCodeProvider httpStatusCodeProvider;

public Web3ResultHttpResponseHandler(HttpStatusCodeProvider httpStatusCodeProvider) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess using this 3rd-party interface is perfectly fine here, but as an option it could also be IntFunction<HttpResponseStatus> errorCodeToHttpStatusMapper

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 it's an interesting suggestion, but considering that we already depend on many classes of com.googlecode.jsonrpc4 for JSON-RPC handling, I think it'd be overkill (besides, I guess rskj shouldn't have the responsibility of defining stuff related to this). Is it ok if I leave it like this?

Vovchyk
Vovchyk previously approved these changes May 11, 2021
@marcciosilva
Copy link
Contributor Author

pipeline: run

fedejinich
fedejinich previously approved these changes May 11, 2021
Copy link
Contributor

@fedejinich fedejinich left a comment

Choose a reason for hiding this comment

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

lgtm!
It'd be nice to cover it also in the integration tests

@marcciosilva
Copy link
Contributor Author

pipeline: run

1 similar comment
@Vovchyk
Copy link
Contributor

Vovchyk commented Jun 10, 2021

pipeline: run

@marcciosilva marcciosilva dismissed stale reviews from fedejinich and Vovchyk via 6e6e16d June 10, 2021 14:21
@marcciosilva marcciosilva force-pushed the fix-json-rpc-http-response-status branch from fecfb31 to 6e6e16d Compare June 10, 2021 14:21
@marcciosilva marcciosilva force-pushed the fix-json-rpc-http-response-status branch from 6e6e16d to 7a619c1 Compare June 10, 2021 15:31
@marcciosilva
Copy link
Contributor Author

pipeline: run

@marcciosilva
Copy link
Contributor Author

pipeline:run

2 similar comments
@marcciosilva
Copy link
Contributor Author

pipeline:run

@nagarev
Copy link
Contributor

nagarev commented Jun 10, 2021

pipeline:run

@aeidelman aeidelman merged commit 33f0f6d into rsksmart:master Jun 10, 2021
@marcciosilva marcciosilva deleted the fix-json-rpc-http-response-status branch June 10, 2021 19:57
@aeidelman aeidelman added this to the Iris v3.1.0 milestone Jul 7, 2021
# 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.

6 participants