This service implements a generic http client. Preparing the body payload (or intercepting) for the http request is done via the TSInterceptor service.
docker pull registry.goingrid.io/services/httpclient:v0.1.0
This service implements the ingrid protocol message. Following properties are being used:
Property | Usage |
---|---|
Class | - |
Operation | - |
Control | - |
Data | Accepts any given data |
With the http service you can send HTTP requests to any web service (REST, SOAP, etc.). Mapping the incoming data from the hive to the web service’s data interface and back is done via the TSInterceptor.
POST https://rest.app.goingrid.io/user/create HTTP/1.1
content-type: application/json
Authorization: Basic admin nutz
{
"firstname": ["Clark"],
"lastname": ["Kent"]
}
import { Response, IngridResponse, IngridMsg, IngridResult, IngridData } from "https://raw.githubusercontent.com/itdistrict/ingrid-deno/master/lib/ingrid.ts";
export function createUserBefore(type: string, value: any, options: Record<string, string>): Response {
var resp = new Response();
// Before interceptor is always from type json, because the data is coming from the hive
if (type == "json") {
resp.data = {
"firstname": value.Data.firstname[0],
"lastname": value.Data.lastname[0]
};
}
return resp;
}
export function createUserAfter(type: string, value: any, options: Record<string, string>): IngridResponse {
let resp = new IngridResponse();
// After interceptor will be the same type as the provided ContentType from the http response.
// If no ContentType was found in the response, the default would be "text/plain; charset=utf-8".
if (type == "json") {
let ingMsg : IngridMsg = new IngridMsg();
let ingResult : IngridResult = new IngridResult();
let ingData: IngridData = {};
ingData["_id"] = [value._id];
ingResult.Code = 200;
ingResult.Message = "User created";
ingResult.Data = ingData;
ingMsg.Result = ingResult;
resp.data = ingMsg;
} else if (type == "text") {
resp.status = `Did not expect text: ${value}`
resp.status_code = 400
} else {
// not supported type, needs a custom reader
resp.status = "Not supported raw types"
resp.status_code = 400
}
return resp;
}
tsinterceptor:
image: ${ING_REGISTRY}/worker/tsinterceptor:latest
deploy:
restart_policy:
condition: on-failure
environment:
PORT: 8080
volumes:
- /srv/ingrid/storage/mapper/es:/app/static
depends_on:
- hive
networks:
- ing-entry
- ing-middle
create-user:
image: ${ING_REGISTRY}/worker/httpclient:latest
deploy:
restart_policy:
condition: on-failure
environment:
NAME: "create-user"
SERVERHOST: "hive"
SERVERAUTH: "file:///run/secrets/ing-hive-key"
INPUTCHANNEL: "user_create"
INTERCEPTBEFORE: "http://tsinterceptor:8080/createUserBefore"
INTERCEPTAFTER: "http://tsinterceptor:8080/createUserAfter"
METHOD: "POST"
URL: "https://elastic.app.goingrid.io/users/_doc"
HEADERS: "Authorization: ApiKey cjljT3BITUJNQkJPMVlEVzc1d3Y6RDVubUpfQ0tRMjJzaHpxWjFXSVlCZw=="
LOGLEVEL: "trace"
depends_on:
- hive
- tsinterceptor
secrets:
- ing-hive-key
networks:
- ing-middle
- ing-worker
POST https://rest.app.goingrid.io/user/create HTTP/1.1
content-type: application/json
Authorization: Basic admin nutz
{
"firstname": ["Clark"],
"lastname": ["Kent"]
}
// /srv/ingrid/storage/mapper/soap/func.ts
import { Response, IngridResponse, IngridResponseData, IngridData } from "https://raw.githubusercontent.com/itdistrict/ingrid-deno/master/lib/ingrid.ts";
import { xmlJS } from "../lib/xml-js.ts";
/*
* Funcs
*/
export function createUserBefore(type: string, value: IngridMsg, options: Record<string, string>): Response {
var resp = new Response();
// Before interceptor is always from type json, because the data is coming from the hive
if (type == "json") {
resp.data = xmlJS.js2xml(value, { compact: true, spaces: 0 });
}
resp.options = options;
return resp;
}
export function createUserAfter(type: string, value: any, options: Record<string, string>): IngridResponse {
let resp = new IngridResponse();
// After interceptor will be the same type as the ContentType from the http response.
// If no ContentType was found in the response, the type will be the one configured.
if (type == "text") {
let ingMsg : IngridMsg = new IngridMsg();
let ingResult : IngridResult = new IngridResult();
let ingData: IngridData = {};
let respData =JSON.parse(xmlJS.xml2json(value, { compact: true, spaces: 4 }));
ingData["_id"] = [respData.response.user.id._text];
ingResult.Code = 200;
ingResult.Message = "User created";
ingResult.Data = ingData;
ingMsg.Result = ingResult;
resp.data = ingMsg;
} else if (type == "json") {
resp.status = "Did not expect json:" + JSON.stringify(value})
resp.status_code = 400
} else {
// not supported type, needs a custom reader
resp.status = "Not supported raw types"
resp.status_code = 400
}
return resp;
}
tsinterceptor:
image: ${ING_REGISTRY}/worker/tsinterceptor:latest
deploy:
restart_policy:
condition: on-failure
environment:
PORT: 8080
volumes:
- /srv/ingrid/storage/mapper/soap:/app/static
depends_on:
- hive
networks:
- ing-entry
- ing-middle
create-user:
image: ${ING_REGISTRY}/worker/httpclient:latest
deploy:
restart_policy:
condition: on-failure
environment:
NAME: "create-user"
SERVERHOST: "hive"
SERVERAUTH: "file:///run/secrets/ing-hive-key"
INPUTCHANNEL: "user_create"
INTERCEPTBEFORE: "http://tsinterceptor:8080/createUserBefore"
INTERCEPTAFTER: "http://tsinterceptor:8080/createUserAfter"
METHOD: "POST"
URL: "https://soap.app.goingrid.io/users"
HEADERS: "Authorization: ApiKey cjljT3BITUJNQkJPMVlEVzc1d3Y6RDVubUpfQ0tRMjJzaHpxWjFXSVlCZw=="
CONTENTTYPE: "application/xml"
LOGLEVEL: "trace"
depends_on:
- hive
- tsinterceptor
secrets:
- ing-hive-key
networks:
- ing-middle
- ing-worker
import { Response, IngridResponse, IngridMsg, IngridResult, IngridData } from "https://raw.githubusercontent.com/itdistrict/ingrid-deno/master/lib/ingrid.ts";
export function before(type: string, value: IngridMsg, options: Record<string, string>): Response {
let resp = new Response();
// Following options are available and can change the course of the http request
options.method = "GET";
options.url = "example.com/api";
options.content_type = "text/plain; charset=utf-8";
let headers = JSON.parse(options.headers);
headers["Custom-Header"] = ["Custom-Value"];
options.headers = JSON.stringify(headers);
// Set the data to a type defined in the service config or in this case
// the one overwritten above (options.content_type)
resp.data = "some plain text";
resp.options = options; // needs to be specified to overwrite the current options from the service config
return resp
}
export function after(type: string, value: any, options: Record<string, string>): IngridResponse {
let resp = new IngridResponse();
// Following options are available after the http request was issued. Unlike the options in the before function
// those options are only for informative.
let http_request = JSON.parse(options.http_request); // The issued http request
let http_response_status_code = parseInt(options.http_response_status_code);
let http_response_status = options.http_response_status
let http_response_headers = JSON.parse(options.http_response_headers);
let ingMsg : IngridMsg = new IngridMsg();
let ingResult: IngridResult = new IngridResult();
ingResult.Status = http_response_status_code;
ingResult.Message = http_response_status;
if (type == "text") {
let ingData: IngridData = {};
ingData["message"] = [value];
ingResult.Data = ingData;
}
ingMsg.Result = ingResult;
resp.data = ingMsg;
return resp;
}
You can validate the data and stop the httpclient from sending it the actual http request. Every status NOT between 200
and 299
will abort further processing and send the response back to the caller.
import { Response, IngridResponse, IngridMsg, IngridResult, IngridData } from "https://raw.githubusercontent.com/itdistrict/ingrid-deno/master/lib/ingrid.ts";
export function before(type: string, value: IngridMsg, options: Record<string, string>): Response {
let resp = new Response();
if (type == "json" && "username" in value.Data && value.Data["username"][0] != "tony") {
resp.status = "Username not provided";
resp.status_code = 400;
return resp;
}
// do something
return resp;
}
Parameter | Default | Description |
---|---|---|
Method | "" |
HTTP Method used for the http request |
URL | "" |
URL used for the http request |
ContentType | "application/json" |
ContentType used for the http request. Setting ContentType in the Headers config parameter will overwrite this |
Headers | "" |
Additional http headers used for the http request (\r\n separated) |
InterceptBefore | "" |
URL to a mapper function before the actual http request |
InterceptAfter | "" |
URL to a mapper function after the actual http request |
Additionally the httpclient service includes all properties of the service configuration and the input configuration.
The configuration parameters InterceptBefore and InterceptAfter are being used to configure the endpoints of the used TSInterceptor service (e.g https://tsinterceptor/hello
). So in order to make the http service work, one or more TSInterceptor services need to be configured as well.