Code Monkey home page Code Monkey logo

vertx-client-builder-poc's Introduction

Proposal for Vert.x Http client builders

Future<String> world = httpClient(vertx)
   .withHost("world.io")
   .returningBodyAsString()
   .get("/world")
   
Future<String> result = httpClient(vertx)
   .withHost("hello.io")
   .returningBodyAsString()
   .post("/hello", world)
   
Observable<String> multipart_body = Observable.just("a","b","c")
Single<String> rxjava = httpClient(vertx)
   .withPort(8080)
   .returningBodyAsStringSingle()
   .post("/", multipart_body)

Follow up to a discussion during Vert.x community meeting. Code written in Groovy for sanity and because lack of time, but the concept is Java compatible.

See ClientSpec for a working prototype in action.

The main idea is to have 2 steps and at least 2 types. First step should allow to specify options:

HttpClientBuilder builder = HttpClientBuilder
   .httpClient(vertx)
   .withHost("localhost")
   .withPort(port)
   .withPipelining(true)
   .withKeepAlive(true)
   .withHeaders("Accept", "text/json", "TraceId","1")
   //...

Type here should be immutable (Copy on Write) so it can act as template. It should:

  • expose all settings from HttpClientOptions
  • have some extra methods to define common headers or auth, base path etc.
  • have methods that define the return type of actual call - those switch to next step

It should be side effect free. It could be made serializable if vertx would be provided as parameter of last method not the first one. There should be starting point for Vertx, HttpClientOptions and HttpClient. I think the one for HttpClient should have limited settings to those that can still be changed.

First type eventually switch to second stage by defining expected return type:

RequestExecutor<String> stringCall = builder.returningBodyAsString()
RequestExecutor<CompletedResponse> responseCall = builder.returningCompletedResponse()
RequestExecutor<Book> modelCall = builder.returning(Book.class)
RequestExecutor<HttpClientResponse> classicCall = builder.returningResponse()

Second type allow to do actual call and return expected response as per specification. It wraps a HttpClient instance. Cool thing is that the whole second stage can be done as a single type with all REST verbs by passing strategy to it, see returning* methods in HttpClientBuilder. It can support different types like RxJava Single, CompletableFuture without changes. Though splitting it to many types might make code simpler.

Once we have executor instance we can do the call and get future (or pass handlers)

Future<String> responseString = stringCall.get("/")
assert block(responseString) == "Hello"

Future<CompletedResponse> response = responseCall.get("/")
CompletedResponse r = block(response)

assert r.statusCode == 200
assert r.bodyAsString == "Hello"

This way once the executor is created, doing REST is trivial.

I chose to return Future, but concept would work the same if get is taking 2 Handlers or AsyncResult. Same for returning RxJava Single, CompletableFuture etc. RxJava observable should work nice with multipart post.

What next:

  • Split rx out of main code
    • Start moving stuff to Java
    • Move rx code to specific class - create FutureExecutor, RxExecutor etc
    • ? Provide builder with parametrised return type for with* methods ?
    • ? RxBuilder as extension of main builder ?
  • Support 3 stages, so one can construct client and then for the same client use different return types (String). Maybe getHttpClient() would be enough.
  • Check how it would look like if we provide Vert.x at the end not at the start of building?

Language specific (Groovy) ?:

  • Support map - typical for dynamic groovy
  • Build and request with closure - static typed
HttpClientBuilder builder = HttpClientBuilder.httpClient(vertx) {
   host "localhost"
   port 8080
   pipelining true
   keepAlive true
   headers Accept: "text/json", TraceId: "1"
}

Boring stuff:

  • Sending headers, query params from request methods (get(path, params, headers)) - support for map and multimap
  • Setting default headers on builder
  • Explicit support for authentication, i.e. withBasicAuth(user, password) for one off calls and get("/", basicAuth(user, password)) for recuring calls

vertx-client-builder-poc's People

Contributors

krzysztofkowalczyk avatar

Watchers

 avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.