This documentation is for WSO2 Enterprise Integrator version 6.2.0 . View documentation for the latest release in the 6.x.x family and the latest release in the 7.x.x family.

All docs This doc
Skip to end of metadata
Go to start of metadata

You can create APIs that allow messages to be sent over the HTTP and HTTPS transports. For more information on creating APIs, see Working with APIs.

You can configure REST endpoints in an API by directly specifying HTTP verbs (such as POST and GET), URI templates, and URL mappings. Alternatively, you can use the HTTP Endpoint to define REST endpoints using URI templates.

Basic REST architectural principles

The structure of APIs in the ESB profile is based on REST architectural principles. This section highlights some of the basic architectural principles of REST based on the following resources:

Uniform interface

REST provides a uniform interface between clients and servers, which simplifies and decouples the architecture, allowing both to evolve independently. To achieve a uniform interface, the following constraints are applied:

  • Resource-based: Individual resources are identified in requests using URIs as resource identifiers.

  • Manipulation of resources through representations: When a client holds a representation of a resource including any metadata attached, it has enough information to modify or delete the resource on the server, provided it has the permission to do so.

  • Self-descriptive messages: Each message includes enough information to describe how to process the message.

  • Hypermedia as the engine of application state (HATEOAS): Clients deliver state via body contents, query-string parameters, request headers, and the requested URI. Services deliver state to clients via body content, response codes, and response headers. This is technically referred to as hypermedia (or hyperlinks within hypertext).

Stateless

The necessary state to handle the request is contained within the request itself, whether as part of the URI, query-string parameters, body, or headers.

Cacheable

As on the World Wide Web, clients can cache responses. Responses must therefore, implicitly or explicitly, define themselves as cacheable or non-cacheable to prevent clients from reusing stale or inappropriate data in response to further requests.

Client–server

The uniform interface separates clients from servers. For example, clients are not concerned with data storage, which remains internal to each server, so that the portability of client code is improved. Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable. Servers and clients may also be replaced and developed independently, as long as the interface is not altered.

Layered system

A client cannot ordinarily detect whether it is connected directly to the back-end server or to an intermediary along the way. This allows for load balancing and caching.

Best practices for designing APIs for use with REST

This section highlights some best practices from https://s3.amazonaws.com/tfpearsonecollege/bestpractices/RESTful+Best+Practices.pdf to keep in mind when designing your APIs.

  • Use meaningful resource names to clarify what a given request does. A RESTful URI should refer to a resource that is a thing instead of an action. The name and structure of URIs should convey meaning to those consumers.
  • Use plurals in node names to keep your API URIs consistent across all HTTP methods.
  • Use HTTP methods appropriately. Use POSTGETPUTDELETEOPTIONS and HEAD in requests to clarify the purpose of the request. The POSTGETPUT and DELETE methods map to the CRUD methods Create, Read, Update, and Delete, respectively. Each resource should have at least one method.
  • Create at most only one default resource (a resource with neither a uri-template nor a url-mapping) for each API.
  • Offer both XML and JSON whenever possible.
  • Use abstraction when it's helpful. The API implementation does not need to mimic the underlying implementation. 
  • Implement resource discoverability through links (HATEOAS). As mentioned in the previous section, the application state should be communicated via hypertext. The API should be usable and understandable given an initial URI without prior knowledge or out-of-band information.
  • Version your APIs as early as possible in the development cycle. At present, the ESB profile identifies each API by its unique context name. If you introduce a version in the API context (e.g., /Service/1.0.0), you can update it when you upgrade the same API (e.g., /Service/1.0.1).
  • Secure your services using OAuth2, OpenID, or another authentication/authorization mechanism. See also Securing APIs .

Unusual Scenarios for HTTP Methods in REST

When sending REST messages to an API , you typically use POST or PUT to send a message and GET to request a message. However, there are some unusual scenarios you might want to support, which are described in the following sections:

Using POST with No Body

Typically, POST is used to send a message that has data enclosed as a payload inside an HTML body. However, you can also use POST without a payload. WSO2 Enterprise Integrator (WSO2 EI) treats it as a normal message and forwards it to the endpoint without any extra configuration.  

The following diagram depicts a scenario where a REST client communicates with a REST service using the ESB profile. Apache Tcpmon is used solely for monitoring the communication between the ESB profile and the back-end service and has no impact on the messages passed between the ESB profile and back-end service. For this particular scenario, the cURL client is used as the REST client, and the basic JAX-RS sample is used as the back-end REST service.

 
 

   To implement this scenario:

  1. Configure and deploy the JAX-RS Basics sample by following the instructions for building and running the sample on the JAX-RS Basics page.
  2. Start the ESB profile  and change the configuration as follows:

    <definitions xmlns="http://ws.apache.org/ns/synapse">
       <sequence name="fault">
          <log level="full">
             <property name="MESSAGE" value="Executing default sequence"/>
             <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
             <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
          </log>
          <drop/>
       </sequence>
       <sequence name="main">
          <log/>
          <drop/>
       </sequence>
       <api name="testAPI" context="/customerservice">
          <resource methods="POST" url-mapping="/customers">
             <inSequence>
                <send>
                   <endpoint>
                      <address uri="http://localhost:8282/jaxrs_basic/services/customers/customerservice"/>
                   </endpoint>
                </send>
             </inSequence>
             <outSequence>
                <send/>
             </outSequence>
          </resource>
       </api>
    </definitions>

    In this proxy configuration, testAPI intercepts messages that are sent to the relative URL /customerservice/customers and sends them to the relevant endpoint by appending the url-mapping of the resource tag to the end of the endpoint URL.

  3. Start tcpmon and make it listen to port 8282 of your local machine. It is also important to set the target host name and the port as required. In this case, the target port needs to be set to 8280 (i.e. the port where the backend service is running).
    We will now test the connection by sending a POST message that includes a payload inside an HTML body.

  4. Go to the terminal and issue the following command:
    curl -v -H "Content-Type: application/xml" -d "<Customer><id>123</id><name>John</name></Customer>" http://localhost:8280/customerservice/customers 

  5. The following reply message appears in the console:

    <Customer>
       <id>132</id>
       <name>John</name>
    </Customer> 
  6. Now send the same POST message but without the enclosed data as follows:
    curl -v -H "Content-Type: application/xml" -d "" http://localhost:8280/customerservice/customer

    You would need to configure the backend service to handle such requests, if not the theESB profile will throw exceptions.

          The tcpmon output shows the same REST request that was sent by the client, demonstrating that the ESB profile handled the POST message regardless of whether it included a payload. 

Using POST with Query Parameters

Sending a POST message with query parameters is an unusual scenario, but the ESB supports it with no additional configuration. The ESB profile forwards the message like any other POST message and includes the query parameters.

To test this scenario, use the same setup as above, but instead of removing the data part from the request, add some query parameters to the URL as follows:

curl -v -H "Content-Type: text/xml" -d "<Customer><id>123</id><name>John</name></Customer>" 'http://localhost:8280/customerservice/customers?param1=value1&param2=value2'

When you execute this command, you can see the following output in tcpmon:

POST /jaxrs_basic/services/customers/customerservice/customers?param1=value1&param2=value2 HTTP/1.1
Content-Type: application/xml; charset=UTF-8
Accept: */*
Transfer-Encoding: chunked
Host: 127.0.0.1:8282
Connection: Keep-Alive
 
32
<Customer><id>123</id><name>John</name></Customer>
0

As you can see, the query parameters are present in the REST request, demonstrating that the ESB profile sent them along with the message. You could write resource methods to support this type of a request. In this example, the resource method accessed by this request simply ignores the parameters.

Using GET with a Body

Typically, a GET request does not contain a body, and the ESB profile does not support these types of requests. When it receives a GET request that contains a body, it drops the message body as it sends the message to the endpoint. You can test this scenario using the same setup as above, but this time the client command should look like this:

curl -v -H "Content-Type: text/xml" -d "<Customer><id>123</id><name>John</name></Customer>" 'http://localhost:8280/jaxrs_basic/services/customers/customerservice/customers/123' -X GET

The additional parameter -X replaces the original POST method with the specified method, which in this case is GET. This will cause the client to send a GET request with a message similar to a POST request. If you view the output in tcpmon, you will see that there is no message body in the request.

Using DELETE with a Body

Typically, DELETE is used to send a HTTP request that does not have data enclosed as a payload. However, if you send a DELETE request with a payload, and if the backend service accepts a DELETE request without a payload, you can drop the payload when the message flows through WSO2 EI.

Follow the steps below to implement this scenario.

  1. Start the ESB profile and create the API that is defined in the following configuration. For instructions, see Creating an API.

    DropPayloadFromDelete API
    <api xmlns="http://ws.apache.org/ns/synapse" name="DropPayloadFromDelete" context="/droppayloadfromdelete">
       <resource methods="DELETE OPTIONS POST PUT GET" url-mapping="/*">
          <inSequence>
             <log level="full"/>
             <property name="NO_ENTITY_BODY" value="true" scope="axis2" type="BOOLEAN"/>
             <call>
                <endpoint>
                   <address uri="http://localhost:8282/jaxrs_basic/services/customers/customerservice"/>
                </endpoint>
             </call>
             <log level="full"/>
             <respond/>
          </inSequence>
       </resource>
    </api>
  2. Start TCPMon and make it listen to port 8282 of your local machine. It is also important to set the target host name and the port as required. In this case, the target port of the TCPMon needs to be set to 8280. This is the port where the backend service (i.e., WSO2 EI) is running.
  3. Open a Terminal and execute the following command to test the connection by sending a DELETE message that includes a payload inside an HTML body:

    curl -X DELETE --header 'Content-type: application/json' --header 'Accept: application/json' --header 'Transfer-Encoding: chunked' --data '{ "Animal": { "id": "10" }}' 'http://localhost:8280/droppayloadfromdelete'

     The TCPMon output shows that the DELETE request sent from WSO2 EI to the backend service does not have the payload.

  • No labels