In Apama 10.3.1, we added support for HTTP redirects, cookie handling for requests, HTTP request decoding, and HTML form encoding to the HTTP client transport. We also added support for HTTP requests and HTML form decoding to the HTTP server transport.
HTTP redirect support in the HTTP client transport
The HTTP client transport now supports HTTP redirects transparently. To enable this, set the followRedirects
configuration option to true
. If the URL you requested returns an HTTP redirect response, your request is made automatically on the URL to which you were redirected. For GET
requests, this will be another GET
request. POST
and PUT
requests will be converted to GET
requests instead (this is standard behavior and a lot of REST APIs rely on this behavior).
The following configuration example shows how to define followRedirects
in your HTTP client chain:
- httpClient:
host: www.example.com
followRedirects: true
HTTP cookies support in the HTTP client transport
The HTTP client transport can now transparently handle HTTP cookies for requests so that you no longer need to handle them in EPL. To enable this, set the cookieJar
configuration option to true
. The HTTP client then stores in memory all cookies received from the server and adds them to subsequent outgoing requests. Expired cookies are automatically removed from the internal cache. The HTTP client also honors additional cookie attributes such as path
,
expiry
and max-age
.
The following configuration example shows how to define cookieJar
in your HTTP client chain:
- httpClient:
host: www.example.com
cookieJar: true
Gzip/deflate decoding support in the HTTP client transport
The HTTP client transport can now decode HTTP responses that have been encoded with gzip or deflate compression format. It is able to accept compressed responses from servers and will automatically decompress the result. No configuration is needed to turn this on, the transport always permits the server to send encoded responses.
If the server chooses to compress the body of the response with gzip or deflate compression format, the HTTP client transport will decompress the body of the response. Warnings will be logged for all unsupported content encodings.
Gzip/deflate decoding support in the HTTP server transport
The HTTP server transport can now decode HTTP requests that have been encoded with gzip or deflate compression format. No configuration is needed to turn this on. The decoding is based on the Content-Encoding
header. If the client sends an encoded request, the HTTP server automatically decodes it. Warnings will be logged for all unsupported content encodings.
You can demonstrate the decoding with an HTTP server configuration like the one below. This configuration assumes that the Request
event type has fields directly matching those in the JSON payload of the request.
dynamicChains:
http:
- apama.eventMap:
defaultEventType: Request
defaultChannel: requests
- jsonCodec
- stringCodec
- httpServer:
automaticResponses: true
allowedMethods: [POST]
You can then use curl to send the gzip-compressed HTTP request to the HTTP server transport, with the body of the HTTP request in JSON format:
echo '{"dataStr": "testing http server decompression", "dataInt":"1234", "dataFloat":"123.456", "dataBool":"true"}' | gzip > body.gz
curl -v -i http://localhost:9090 -H'Content-Encoding: gzip' -H'Content-type: application/json' --data-binary @body.gz
The HTTP server transport will read the Content-Encoding
header and automatically decompress the payload.
HTML form decoding support in the HTTP server transport
The HTTP server transport now supports HTML form decoding and can decode multipart/form-data
or application/x-www-form-urlencoded
media types to a dictionary payload.
EXAMPLE: URL ENCODING
If the Content-Type
header field contains the application/x-www-form-urlencoded
media type, the request payload is decoded to a dictionary payload with string keys and string values.
The following configuration example for the HTTP server transport shows how you can make use of URL encoding:
dynamicChains:
http:
- apama.eventMap:
defaultEventType: URLEncodedData
defaultChannel: foo
- httpServer:
automaticResponses: true
allowedMethods: [PUT,POST]
The body of the HTTP request is directly decoded into a dictionary and mapped to a URLEncodedData
event type. We’re also assuming here that the fields in the URLEncodedData
event type match the fields in the form and no mapping is needed between them. You can also see that we don’t need a String codec and a JSON codec, since the transport is producing a dictionary payload directly.
The following code block shows the EPL event types and monitor code required to listen for the events from the above chain and then log the result:
event URLEncodedData{
string foo;
string abc;
}
monitor serverMonitor{
action onload()
{
monitor.subscribe("foo");
on all URLEncodedData() as urlData
{
log "EPL Received Event : " + urlData.toString() at INFO;
}
}
}
You can then use curl to send HTTP request to the HTTP server transport, with the request body containing two form fields:
curl -v -i http://localhost:9090 --data foo=value1 --data abc=value2
EXAMPLE: MULTIPART/FORM-DATA
If the Content-Type
header field contains the multipart/form-data
media type, the request payload is decoded to a dictionary payload with string keys and either string or binary values. For the parts that have binary data, additional metadata is created. This metadata contains the contentType
, charset
or filename
information for each binary part. You can get the metadata as follows:
metadata.http.form.name.contentTyp
metadata.http.form.name.charset
metadata.http.form.name.filename
where name corresponds to the data in payload.name
.
The following configuration example for the HTTP server transport shows how you can use the Mapper codec to map the metadata of a binary form field.
dynamicChains:
http:
- apama.eventMap:
defaultEventType: FormData
defaultChannel: foo
- mapperCodec:
"*":
towardsHost:
mapFrom:
- payload.contentType: metadata.http.form.file.contentType
- payload.filename: metadata.http.form.file.filename
- httpServer:
automaticResponses: true
allowedMethods: [PUT,POST]
The following code block shows the EPL event types and monitor code required to listen for the events from the above chain and then log the result:
event FormData{
string foo;
string abc;
string contentType;
string filename;
}
monitor serverMonitor{
action onload()
{
monitor.subscribe("foo");
on all FormData() as formData
{
log "EPL Received Event : " + formData.toString() at INFO;
}
}
}
You can then use curl to send an HTTP POST
request to the HTTP server transport, with the request payload containing three form fields:
curl -v -i http://localhost:2498 -F foo=value1 -F abc=value2 -F file=@./test.txt
Please note that the correlator can’t directly understand binary components, you will need to decode them with a codec like the String codec (provided with Apama) or a custom codec that you write yourself.
HTML form encoding support in the HTTP client transport
The HTTP client transport now supports HTML form encoding and can encode a dictionary payload to either multipart/form-data
or application/x-www-form-urlencoded
media types.
To encode the request as multipart/form-data
, you must set metadata.contentType
to multipart/form-data
and then map the payload to a dictionary with string keys and either string or binary payloads. You must use this method to send non-ASCII text or binary data. The binary data form fields should have the following additional metadata: filename
, contentType
and charset
. filename
is a required parameter. You can put these metadata items in a form dictionary as follows:
metadata.http.form.name.contentType
metadata.http.form.name.charset
metadata.http.form.name.filename
where name corresponds to the data in payload.name
.
You can also encode the request as application/x-www-form-urlencoded
by setting metadata.contentType
to application/x-www-form-urlencoded
and mapping the payload to a dictionary with string keys and values.
The following configuration shows how you can use the Mapper codec to map the metadata and payload:
- mapperCodec:
HTTPRequestMultiPartForm:
towardsTransport:
mapFrom:
- metadata.requestId: payload.id
- metadata.http.method: payload.method
- metadata.http.path: payload.path
- metadata.contentType: payload.contentType
- metadata.http.form.binary.contentType: payload.formMetadata.binary.contentType
- metadata.http.form.binary.filename: payload.formMetadata.binary.filename
- metadata.http.form.binary.charset: payload.formMetadata.binary.charset
- payload: payload.data
HTTPRequestURLEncoding:
towardsTransport:
mapFrom:
- metadata.requestId: payload.id
- metadata.http.method: payload.method
- metadata.http.path: payload.path
- metadata.contentType: payload.contentType
- payload: payload.data
The following is an example of an EPL application that shows the event types and monitor code for sending data with application/x-www-from-urlencoded
and multipart/form-data
.
//HTTPClient sending a dictionary payload request body having both key and value strings using application/x-www-form-urlencoded method
event HTTPRequestURLEncoding {
integer id;
string method;
string path;
string contentType;
dictionary<string, string> data;
}
//HTTPClient sending a dictionary payload request body having string key and string value using multipart/form-data method.
//Using formMetadata to provide the metadata for binary form data.
event HTTPRequestMultiPartForm {
integer id;
string method;
string path;
string contentType;
dictionary<string, string> data;
dictionary<string, dictionary<string,string> > formMetadata;
}
monitor TestFormEncoding {
action onload() {
dictionary<string, string> dataURL := {"string":"Hello World", "foo":"bar"};
integer id := integer.incrementCounter("HTTPClient.requestId");
//Sending application/x-www-form-urlencoded data
send HTTPRequestURLEncoding(id, "POST", "/", "application/x-www-form-urlencoded", dataURL) to "http";
dictionary<string, string> dataMultiPart := new dictionary<string, string>;
dataMultiPart.add("string": "Hello World");
string binaryData := ...; // got from some source
dataMultiPart.add("binary": binaryData);
//Metadata for form binary data field
dictionary<string,dictionary<string,string> > formMetadata := {
"binary":{
"filename":"file.txt",
"charset":"utf-8",
"contentType":"text/plain"
}
};
id := integer.incrementCounter("HTTPClient.requestId");
//Sending multipart/form-data
send HTTPRequestMultiPartForm(id, "POST", "/", "multipart/form-data", dataMultiPart, formMetadata) to "http";
}
}
Summary
The HTTP client transport can automatically handle HTTP redirects and HTTP cookies, and can encode HTML forms. The HTTP server transport can decode HTML forms. Both transports (HTTP client and HTTP server) support decompression.
For more information, see the following sections in the online documentation for Apama 10.3.1: “The HTTP Server Transport Connectivity Plug-in” and “The HTTP Client Transport Connectivity Plug-in”.
Feel free to post on our our stack exchange site with any questions you may have about this, or any other, topic.