Skip to main content

Using the HTTP Inbound Adapter

This topic describes the default behavior of the HTTP inbound adapter (EnsLib.HTTP.InboundAdapterOpens in a new tab) and describes how to use this adapter in your productions.

Tip:

InterSystems IRIS® data platform also provides specialized business service classes that use this adapter, and one of those might be suitable for your needs. If so, no programming would be needed. See Connectivity Options.

Overall Behavior

EnsLib.HTTP.InboundAdapterOpens in a new tab is an HTTP listener for custom port listening, XML listening, and/or raw HTML handling. You use this adapter in cases when you prefer to listen on a private port rather than using a CSP page (which uses your configured web server to handle HTTP requests).

First, the class provides runtime settings that you use to specify items like the following:

  • A local port, where the adapter will listen for input

  • A list of IP addresses from which the adapter will accept input (if you want to restrict the possible sources)

  • Settings that specify whether to use the character set given in the inbound request, and if not, what other character set to use

The inbound HTTP adapter listens to a port on the local machine, reads the input, and sends the input as a stream to the associated business service. The business service, which you create and configure, uses this stream and communicates with the rest of the production. The following figure shows the overall flow:

On Connected method in inbound adapter sends stream to process input method in business service, then to on process input

In more detail:

  1. The adapter receives an HTTP message and opens a TCP connection. (HTTP is a format of header and body data that is sent over a TCP connection.)

  2. When the adapter connects, it executes its OnConnected() method, which first determines the character set to use. By default, it uses the character set specified in the inbound HTTP request. For details, however, see Specifying the Character Set to Use.

  3. The adapter chooses the appropriate translation table for the character set.

  4. The adapter reads the body of the input, translates it, and places it into a new stream object.

    Note that %GlobalCharacterStreamOpens in a new tab and %GlobalBinaryStreamOpens in a new tab are deprecated but are still supported for use in this way. It is not recommended to substitute different stream classes for this use case.

    The adapter also extracts each HTTP header and adds that header to the Attributes property of the stream; this property is a multidimensional array, as discussed later.

    Also, if the URL includes form parameters, these are passed as follows:

  5. The adapter then calls the internal ProcessInput() method of the business service class, passing the stream as an input argument.

  6. The internal ProcessInput() method of the business service class executes. This method performs basic production tasks such as maintaining internal information as needed by all business services. You do not customize or override this method, which your business service class inherits.

  7. The ProcessInput() method then calls your custom OnProcessInput() method, passing the stream object as input. The requirements for this method are described later in Implementing the OnProcessInput() Method.

  8. If ProcessInput() or OnProcessInput() returns an error, the production invokes the OnErrorStream() method of the business service.

The response message follows the same path, in reverse.

Creating a Business Service to Use the HTTP Inbound Adapter

To use this adapter in your production, create a new business service class as described here. Later, add it to your production and configure it. You must also create appropriate message classes, if none yet exist. See Defining Messages.

The following list describes the basic requirements of the business service class:

The following example shows the overall structure of your business service class. The details of the OnProcessInput() method depend on the character set that the adapter is using. If the adapter is using a non-binary character set, the general structure should be as follows:

Class EHTTP.NewService1 Extends Ens.BusinessService 
{
Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";

Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
{
   set tsc=$$$OK
   //your code here
   Quit tsc
}
}

Or, if the adapter is using a binary character set, the OnProcessInput() method should be as follows instead:

Method OnProcessInput(pInput As %GlobalBinaryStream, pOutput As %RegisteredObject) As %Status
{
   set tsc=$$$OK
   //your code here
   Quit tsc
}

Implementing the OnProcessInput() Method

Within your custom business service class, the signature of your OnProcessInput() method depends on the character set that the adapter is using:

  • If the adapter is using a non-binary character set, the signature should be as follows:

    Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
    
    
  • If the adapter is using a binary character set, the signature should be as follows:

    Method OnProcessInput(pInput As %GlobalBinaryStream, pOutput As %RegisteredObject) As %Status
    
    

Here pInput is the input that the adapter will send to this business service. Also, pOutput is the generic output argument required in the method signature.

Note that %GlobalCharacterStreamOpens in a new tab and %GlobalBinaryStreamOpens in a new tab are deprecated but are still supported for use in this way. It is not recommended to substitute different stream classes for this use case.

The OnProcessInput() method should do some or all of the following:

  1. Examine the input object and extract the needed data from it. See Using the HTTP Request.

  2. Create an instance of the request message, which will be the message that your business service sends.

    For information on creating message classes, see Defining Messages.

  3. For the request message, set its properties as appropriate, using values obtained from the input stream.

    If the attribute Content-Type is specified in the Attributes property, by default, that is used as the Content-Type of the request message. If Content-Type is not specified in the Attributes property, by default, the Content-Type of the request message is set to "text/html". If these defaults are not appropriate, be sure to set this attribute. For example, the following code checks the value of the attribute Content-Type of the input stream and uses "text/xml" if the value is missing:

     Set outputContentType=$GET(pInput.Attributes("Content-Type"),"text/xml")
  4. Call a suitable method of the business service to send the request to some destination within the production. Specifically, call SendRequestSync(), SendRequestAsync(), or (less common) SendDeferredResponse(). For details, see Sending Request Messages.

    Each of these methods returns a status (specifically, an instance of %StatusOpens in a new tab).

  5. Optionally check the status of the previous action and act upon it.

  6. Optionally examine the response message that your business service has received and act upon it.

  7. Make sure that you set the output argument (pOutput). This step is required.

  8. Return an appropriate status. This step is required.

The following shows a simple example:

Method OnProcessInput(pInput As %GlobalCharacterStream, Output pOutput As %RegisteredObject) As %Status
{
    //get contents of inbound stream
    //in this case, the stream contains a single value: a patient ID
    Set id=pInput.Read(,.tSC)

    //make sure Read went OK
    If $$$ISERR(tSC) do $System.Status.DisplayError(tSC)

    //create request object to send
   Set tRequest=##class(EHTTP.Request.Patient).%New()
    Set tRequest.patientID=id

   //send to lookup process
   Set tSC=..SendRequestSync("EHTTP.LookupProcess",tRequest,.tResponse)

    //define output for OnProcessInput
    Set pOutput=tResponse

    Quit tSC
}

Implementing the OnErrorStream() Method

If the ProcessInput() or OnProcessInput() method of your business service returns an error, the production invokes the OnErrorStream() method of the business service. You can implement this method to contain any desired error handling. The method should accept a status code as input and should return the desired output stream.

Using the HTTP Request

Within OnProcessInput(), the HTTP request is available as pInput, which is an instance of %GlobalCharacterStreamOpens in a new tab or %GlobalBinaryStreamOpens in a new tab, depending on your implementation. The following figure illustrates how this instance represents the HTTP request:

Purple box contains body of request. Green box contains URL parameters. Yellow box contains http headers

The body of the request is written to the pInput stream. For information on working with streams, see Defining and Using Stream Properties.

Additional data is available in the Attributes property of the pInput stream, as discussed in the following subsection. This includes the HTTP headers. If the request was a GET request, it also includes any form variables (URL parameters).

If the request was a POST request, then the form variables are available in the body.

About the Attributes Array

The Attributes property of the pInput stream is a multidimensional array that carries the following data:

Node Contents
Attributes(http_header_name) Where http_header_name is the header name in lowercase, for example, "content-length" Value of the given HTTP header
Attributes("Params",form_variable_name,n) Value of the nth instance of the given URL form variable (if the HTTP request was a GET request).
Attributes("URL") Complete URL of the HTTP request

So you can retrieve a header value as follows:

 set contentlength = pInput.Attributes("content-length") 

Or, to retrieve a URL form variable (for a GET request):

 set pResponse.MessageRequestTimeStamp = pInput.Attributes("Params","REQUESTTIMESTAMP",1)

Retrieving Form Variables from a POST Request

If the HTTP request was a POST request, then the form variables are available in the pInput stream. The form variables will be in key-value pairs, separated by an & delimiter. For example:

Q1=Answer1&Q2=Answer2&Q3=Answer3

Use ObjectScript string functions to retrieve the form variables. The following shows you an example of how to do this:

Method OnProcessInput(pInput As %GlobalCharacterStream, pOutput As %RegisteredObject) As %Status
{
    Set tData=pInput.Read(,.tSC)

    If $$$ISERR(tSC) {
      Do $System.Status.DisplayError(tSC)
    }

    Set tRequest=##class(EHTTP.Request.Patient).%New()

    //use a delimiter to separate the form variables
    Set list=$LISTFROMSTRING(tData,"&")

    //examine each element and extract the relevant data
    Set ptr=0
    While $LISTNEXT(list,ptr,key) {
      If $PIECE(key,"=") = "Q1" {
        Set tRequest.Q1 = $PIECE(key,"=",2)
      }
      Elseif $PIECE(key,"=") = "Q2" {
        SET tRequest.Q2 = $PIECE(key,"=",2)
      }
      Elseif $PIECE(key,"=") = "Q3" {
        Set tRequest.Q3 = $PIECE(key,"=",2)
      }
    }

    Set tSC=..SendRequestSync("EHTTP.LookupProcess",tRequest,.tResponse)

    Set pOutput=tResponse

    Quit tSC
}

You can also use the OnInit() callback method to parse the form variables of a POST request.

Adding and Configuring the Business Service

To add your business service to a production, use the Management Portal to do the following:

  1. Add an instance of your custom business service class to the production.

  2. Configure the adapter so that it can receive input. Specifically:

  3. Enable the business service.

  4. Run the production.

Specifying the Sources of HTTP Requests

You can configure the inbound HTTP adapter to recognize sources of HTTP requests in two different ways:

  • You can permit HTTP requests from any server. This is the default.

  • You can permit HTTP requests from a list of specific servers (optionally with specific ports).

    To do so, specify the Allowed IP Addresses setting. See HTTP Adapter Settings.

Specifying the Character Set to Use

When the EnsLib.HTTP.InboundAdapterOpens in a new tab receives input, it translates the characters in that input according to a translation table. To determine which translation table to use, the adapter first determines which character set the input uses.

In general, the HTTP Content-Type header of the input indicates which character set that request uses. By default, the adapter uses that character set.

However, you can control which character set the adapter uses, by using the following runtime settings:

See HTTP Adapter Settings.

For information on character sets and translation tables, see Translation Tables.

FeedbackOpens in a new tab