Skip to content

Request Response API (R2)

David Hoa edited this page Jan 20, 2017 · 19 revisions

Introduction

R2 is the request / response API underlying Rest.li. It includes abstractions for REST requests and responses, filter chains for customized processing, and transport abstraction. It is designed so that it can be easily customized for non-open source use cases.

R2 can be used independently, with D2 (our Dynamic Discovery system), or with both D2 and Rest.li.

Contents

Layers

The following diagram shows the layers involved in the R2 system. Each layer will be described in detail below.

Requests and Responses

In this section, we describe messages in the R2 system. The message hierarchy has ben designed to make it possible to add and work with broader message abstractions when appropriate. Originally, REST was the basic type of message in R2, but with the addition of R2 Streaming, STREAM became the most basic type of messages in R2, with REST built on top of STREAM. Because REST is the most common use case, we will stick to describing the REST model here, and leave STREAM as a separate doc.

Messages have a few properties that are worth describing here:

  • They are immutable. It is not possible to change a message after it has been created. It is, however, possible to copy a message and make changes using builders, which will be described later.
  • They are thread-safe due to immutability.
  • New messages are created using builders.
  • Existing messages can be copied and modified using builders.

Messages

"RestMessage" is the root of the message hierarchy. All messages in R2 contain an "entity" (which may be empty), and corresponds to the request or response data. For REST, the R2 entity is equivalent to a REST entity. For Streaming, because of the nature of streaming, the R2 entity is replaced by an EntityStream. R2 Streaming will be discussed more fully in a separate doc.

RestMessage has the following interface (Note: all code snippets have been simplified here for documentation purposes, and may not reflect the full complexity of the class hierarchy):

public interface RestMessage
{
  /**
   * Returns the entity for this message.
   *
   * @return the entity for this message
   */
  ByteString getEntity();
 
  /**
   * Returns a {@link RestMessageBuilder}, which provides a means of constructing a new message using
   * this message as a starting point. Changes made with the builder are not reflected by this
   * message instance.
   *
   * @return a builder for this message
   */
  RestMessageBuilder extends RestMessageBuilder>> builder();
}

In addition to an entity, all messages provide a builder that can be used to copy the message and modify its copy. In the case of the Message above, the builder is a RestMessageBuilder. RestMessages are subdivided into RestRequests and RestResponses. The interfaces for these are described below.

RestRequest

A request has a URI. This provides information to the client about how to direct the request - for example, which protocol to use, which server to connect to, what service to invoke, etc. R2 can be used with D2 (Dynamic Discovery), so in those cases URNs will be used for the URI. These URNs will be resolved internally by the Dynamic Discovery system.

public interface RestRequest extends MessageHeaders
{
  /**
   * Returns the URI for this request.
   *
   * @return the URI for this request
   */
  URI getURI();

  /**
   * Returns the REST method for this request.
   *
   * @return the REST method for this request
   * @see com.linkedin.r2.message.rest.RestMethod
   */
  String getMethod();
 
  /**
   * Returns a {@link RestRequestBuilder}, which provides a means of constructing a new request using
   * this request as a starting point. Changes made with the builder are not reflected by this
   * request instance.
   *
   * @return a builder for this request
   */
  RestRequestBuilder builder();
}
Clone this wiki locally