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

WebClient API improvements #378

Closed
InfoSec812 opened this issue May 30, 2018 · 9 comments
Closed

WebClient API improvements #378

InfoSec812 opened this issue May 30, 2018 · 9 comments
Assignees

Comments

@InfoSec812
Copy link

InfoSec812 commented May 30, 2018

Recently, while using the RxJava2 implementation of WebClient, I noticed something which is not intuitive.

client.get(somePath)
    .map(HttpResponse::bodyAsJsonObject)
    .map(Future::succeededFuture)
    .onErrorReturn(Future::failedFuture)
    .subscribe(handler::handle);

When the client gets a 4XX or a 5XX response from the server, that error does NOT trigger the onErrorReturn path. I think I understand this to be because of it being generated code which is not "smart" enough to understand that a 4XX or 5XX is an error. Instead, I had to create a mapToError method and put it into the mix:

client.get(somePath)
    .map(this::mapToError)
    .map(HttpResponse::bodyAsJsonObject)
    .map(Future::succeededFuture)
    .onErrorReturn(Future::failedFuture)
    .subscribe(handler::handle);

This works, but it is not intuitive.

I propose that the documentation for the WebClient API be updated to include examples for error handling. This probably needs to be done in many other places in the Vert.x documentation as well.

@vietj
Copy link

vietj commented May 30, 2018

good point, I've actually proposed a new feature for the web client "expectations" that would be something like:

client.get(path)
      .expect(200)
      ...

that produces an error if the code is not 200

there could be other expectations (around content type, etc...)

@InfoSec812
Copy link
Author

InfoSec812 commented May 30, 2018

@vietj I like the basic concept, but I'm not sure about that specific implementation. Perhaps static methods on a WebClientMappers class? Something like:

WebClientMappers.expectResponseCode(HttpResponse response, HttpResponseStatus status)
WebClientMappers.expectHeader(HttpResponse response, String headerName, String headerValue)

And then you could do something like:

client.get(somePath)
    .map(r -> WebClientMappers.expectResponse(r, INTERNAL_SERVER_ERROR)
    .map(r -> WebClientMappers.expectHeader(r, "Content-Type", APPLICATION_JSON)
    .map(HttpResponse::bodyAsJsonObject)
    .map(Future::succeededFuture)
    .onErrorReturn(Future::failedFuture)
    .subscribe(handler::handle);

@vietj
Copy link

vietj commented May 30, 2018

that would be on HttpRequest itself so you use it before hte map.

your code is incorrect because it should contains an rxSend call, so it would rather be:

client.get(somePath)
      .expect(200).
      .rxSend()
      ...
      .subscribe(res -> {});

@InfoSec812
Copy link
Author

@vietj OK, you're right. I missed the call to rxSend. It should be:

client.get(somePath)
    .rxSend()
    .map(r -> WebClientMappers.expectResponse(r, INTERNAL_SERVER_ERROR)
    .map(r -> WebClientMappers.expectHeader(r, "Content-Type", APPLICATION_JSON)
    .map(HttpResponse::bodyAsJsonObject)
    .map(Future::succeededFuture)
    .onErrorReturn(Future::failedFuture)
    .subscribe(handler::handle);

@InfoSec812
Copy link
Author

@vietj Thinking about the approach you are suggesting, perhaps something like:

client.get(somePath)
    .expectHeader(headerName, headerValue)
    .expectStatus(OK)
    .expectBody(matchesJsonPath("$.some.json.field"))
    .rxSend()
    .map(HttpResponse::bodyAsJsonObject)
    .map(Future::succeededFuture)
    .onErrorReturn(Future::failedFuture)
    .subscribe(handler::handle);

Thoughts?

@vietj
Copy link

vietj commented May 30, 2018

yes that seems fine, I did not have intention for body expectations first but why not ? it can help unit testing I guess.

@InfoSec812
Copy link
Author

Oh, wait... On the headers... We would need to support MultiMap, right?

@vietj
Copy link

vietj commented May 30, 2018

I think we can support rather per header checking, I don't think MultiMap support is needed.

@tsegismont
Copy link

Closing, now tracked by vert-x3/vertx-web#1013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants