NB5 Docs► Reference Section► Drivers▼ http 🖺

http

This driver allows you to make http requests using the native HTTP client that is bundled with the JVM. It supports free-form construction of requests.

You specify what a request looks like by providing a set of request parameters. They can be in either literal (static) form with no dynamic data binding, or they can each be in a string template form that draws from data bindings. Each cycle, a request is assembled from these parameters and executed.

Example Statements

The simplest possible statement form looks like this:

op: http://google.com/

Or, you can have a list:

# A list of statements
ops:
 - http://google.com/
 - http://amazon.com/

Or you can template the values used in the URI, and even add ratios:

# A list of named statements with variable fields and specific ratios:
ops:
    - s1: http://google.com/search?query={query}
      ratio: 3
    - s2: https://www.amazon.com/s?k={query}
      ratio: 2
bindings:
    query: >
        WeightedStrings('function generator;backup generator;static generator');
        UrlEncode();

You can even make a detailed request with custom headers and result verification conditions:

# Require that the result be status code 200-299 match regex "OK, account id is .*" in the body
ops:
    - get-from-google:
      method: GET
      uri: "https://google.com/"
      version: "HTTP/1.1"
      Content-Type: "application/json"
      ok-status: "2[0-9][0-9]"
      ok-body: "^(OK, account id is .*)$"

For those familiar with what an HTTP request looks like on the wire, the format below may be familiar. This isn't actually the content that is submitted, but it is recognized as a valid way to express the request parameters in a familiar and condensed form. A custom config parser makes this form available fo rhose who want to emulate a well-known pattern:

ops:
    - s1: |
          GET https://google.com/ HTTP/1.1
          Content-Type: application/json
      ok-status: 2[0-9][0-9]
      ok-body: ^(OK, account id is.*)$

Of course, in the above form, the response validators are still separate parameters.

Bindings

All request fields can be made dynamic with binding functions. To make a request that has all dynamic fields, you can do something like this:

ops:
    - s1: |
          {method} {scheme}://{host}:{port}/{path}?{query} {version}
          Content-Type: {content_type}
          Token: {mybearertoken}

          {body}

The above example is in the inline request form. It is parsed and interpreted internally as if you had configured your op template like this:

ops:
    - method: { method }
      uri: { scheme }://{host}:{port}/{path}?{query}
      version: { version }
      "Content-Type": { content_type }
      "Token": { mybearertoken }
      body: { body }

The above two examples are semantically identical, only the format is different. Notice that the expansion of the URI is still captured in a field called uri, with all the dynamic pieces stitched together in the value. You can't use arbitrary request fields. Every request field must from (method, uri, version, body, ok-status, ok-body) or otherwise be capitalized to signify an HTTP header.

The HTTP RFCs do not require headers to be capitalized, but they are capitalized ubiquitously in practice, so we follow that convention here for clarity. Headers are in-fact case-insensitive, so any issues created by this indicate a non-conformant server/application implementation.

For URIs which are fully static (There are no dynamic fields, request generation will be much faster, since the request is fully built and cached at startup.

Request Fields

At a minimum, a URI must be provided. This is enough to build a request with. All other request fields are optional and have reasonable defaults:

Any other statement parameter which is capitalized is taken as a request header. If additional fields are provided which are not included in the above list, or which are not capitalized, then an error is thrown.

Error Handling & Retries

By default, a request which encounters an exception is retried up to 10 times. If you want to change this, set another value to the retries= activity parameters.

Presently, no determination is made about whether an errored response should be retryable, but it is possible to configure this if you have a specific exception type that indicates a retryable operation.

The HTTP driver is the first NB driver to include a completely configurable error handler chain. This is explained in the error-handlers topic. By default, the HTTP activity's error handler is wired to stop the activity for any error encountered.

SSL Support

SSL should work for any basic client request that doesn't need custom SSL configuration. If needed, more configurable SSL support will be added.

Client Behavior

TCP Sessions & Clients

Client instances are created for each unique space value. NoSQLBench provides a way for all driver adapters to instance native clients according to a data from a binding. This is standardized under the op template parameter space, which is wired by default to the static value default. This means that each activity that uses the http driver shares a client instance across all threads by default. If you want to have a new http client per-thread, simply add a binding for space: ThreadNumToInteger() and reference it in an op template like space: {space}, OR use an inline op field in your op template like space: {(ThreadNumToInteger())}.

You can use any binding function you want for the space op field. However, if you were to assign it something like "space: {(Identity()}" you would not have a good result, as you would be spinning up and caching a new http client instance for every single cycle.

Chunked encoding and web sockets

Presently, this driver only does basic request-response style requests. Thus, adding headers which take TCP socket control away from the HttpClient will likely yield inconsistent (or undefined) results. Support may be added for long-lived connections in a future release. However, chunked encoding responses are supported, although they will be received fully before being processed further. Connecting to a long-lived connection that streams chunked encoding responses indefinitely will have undefined results.

HTTP Activity Parameters

Back to top