HTTP Source

Start an HTTP server to receive messages via REST endpoints. Supports TLS, multiple authentication methods, and configurable route paths.

Overview

The HTTP source creates an embedded HTTP server that listens for incoming requests on a specified port and path. When a request arrives matching the configured methods, intu passes the request body to the channel's validator and transformer pipeline.

This source is well suited for receiving real-time event notifications, webhook callbacks, and REST-based integrations from EHR systems, lab information systems, and other healthcare applications that push data over HTTP.

Note When deploying in production, enable TLS and configure an appropriate authentication method to protect PHI in transit.

Configuration

The HTTP source is configured within the listener block of a channel.yaml file. Set type to http and provide the connection details under the http key.

yaml
listener:
  type: http
  http:
    port: 8080
    path: /api/v1/adt
    methods: [POST]
    tls:
      cert_file: /etc/intu/certs/server.crt
      key_file: /etc/intu/certs/server.key
    auth:
      type: bearer
      token: ${ADT_AUTH_TOKEN}

Properties

port int required
The TCP port the HTTP server listens on. Must be between 1 and 65535.
path string optional
The URL path to listen on. Defaults to /. Supports path parameters such as /api/v1/:resource.
methods string[] optional
Allowed HTTP methods. Valid values are GET, POST, and PUT. Defaults to [POST].
tls object optional
TLS configuration for HTTPS. Contains cert_file and key_file paths. When provided, the server requires HTTPS connections.
auth object optional
Authentication configuration. Supported types: basic, bearer, api_key, oauth2, mtls. Each type requires its own set of sub-properties.

Auth Type Details

Type Properties Description
basic username, password HTTP Basic authentication with username and password.
bearer token Bearer token authentication via the Authorization header.
api_key header, key API key sent in a custom request header.
oauth2 issuer, audience, jwks_url OAuth 2.0 JWT validation against a JWKS endpoint.
mtls ca_file Mutual TLS with client certificate verification.

Complete Example

A full channel.yaml that receives HL7 ADT messages via HTTP POST, validates the payload, transforms it, and forwards it to a Kafka destination.

yaml
id: adt-inbound
enabled: true

listener:
  type: http
  http:
    port: 8080
    path: /api/v1/adt
    methods: [POST]
    auth:
      type: bearer
      token: ${ADT_AUTH_TOKEN}

validator:
  runtime: node
  entrypoint: validator.ts

transformer:
  runtime: node
  entrypoint: transformer.ts

destinations:
  - kafka-output

TypeScript Transformer Example

This transformer receives an HL7 ADT (Admit/Discharge/Transfer) message from the HTTP source and maps it to a FHIR R4 Patient resource.

typescript
import { Message, TransformResult } from "@intu/sdk";

interface HL7Segment {
  fields: string[];
}

function parseHL7(raw: string): Map<string, HL7Segment[]> {
  const segments = new Map<string, HL7Segment[]>();
  const lines = raw.split("\r");
  for (const line of lines) {
    const fields = line.split("|");
    const name = fields[0];
    if (!segments.has(name)) segments.set(name, []);
    segments.get(name)!.push({ fields });
  }
  return segments;
}

export default function transform(msg: Message): TransformResult {
  const hl7 = parseHL7(msg.body as string);
  const pid = hl7.get("PID")?.[0]?.fields;

  if (!pid) {
    return { success: false, error: "Missing PID segment" };
  }

  const nameParts = (pid[5] || "").split("^");
  const patient = {
    resourceType: "Patient",
    identifier: [
      {
        system: "urn:oid:2.16.840.1.113883.19.5",
        value: pid[3]?.split("^")[0] || "",
      },
    ],
    name: [
      {
        family: nameParts[0] || "",
        given: [nameParts[1] || ""],
      },
    ],
    gender: mapGender(pid[8]),
    birthDate: formatHL7Date(pid[7]),
  };

  return {
    success: true,
    body: JSON.stringify(patient),
    contentType: "application/fhir+json",
  };
}

function mapGender(code: string | undefined): string {
  switch (code) {
    case "M": return "male";
    case "F": return "female";
    case "O": return "other";
    default:  return "unknown";
  }
}

function formatHL7Date(raw: string | undefined): string | undefined {
  if (!raw || raw.length < 8) return undefined;
  return `${raw.slice(0, 4)}-${raw.slice(4, 6)}-${raw.slice(6, 8)}`;
}