Skip to content

hailer.http ​

Call third-party services through Hailer's server-side proxy instead of calling them directly from the iframe. The request goes to a Hailer API host, which authenticates the current user and forwards the request to the target service.

MethodHost opReturns
fetch(url, options?)http.fetchPromise<HTTPFetchResponse>
upload(url, entries)http.uploadPromise<HTTPFetchResponse>
openWebSocket(url)http.ws.open (streaming)HTTPWebSocket (synchronous)

Authentication ​

  • The app calls a Hailer API host (e.g. https://api.hailer.com) at the path /proxy/{serviceName}/.... The request is sent with the user's Hailer session cookie.
  • Hailer validates the session, then removes the session cookie before forwarding. The target service does not receive the user's Hailer credentials.
  • Hailer forwards the header x-hailer-user-id with the user's id. The target service identifies the user from this header.

Authenticating to the target service ​

The proxy authenticates the user to Hailer; it does not carry a token for the service you're calling. When the target needs its own API key or login, keep it in credential rather than in your bundle or app config, and read it just before the call:

ts
import { CredentialApiKeyData } from '@hailer/app-sdk';

const { secret } = await hailer.credential.get<CredentialApiKeyData>(credentialId);

const res = await hailer.http.fetch('https://api.hailer.com/proxy/myservice/things', {
  headers: { authorization: `Bearer ${secret.apiKey}` },
});

Fetch the secret per request instead of holding it in a long-lived variable, and never log the response of credential.get — headers you build from it end up in the proxied request only.

Allowed URLs and registration ​

Two constraints apply to the URL:

  1. Host allow-list. The URL must start with a Hailer API host — currently https://api.hailer.com, https://api.k8s.hailer.com, or https://api.hailer.local.gd. A URL outside the list is rejected before any request is made.
  2. Registration. The {serviceName} in /proxy/{serviceName}/... must be a service registered in Hailer's backend proxy configuration. Unregistered paths do not route.

Support for third-party targets is being expanded. To register a third-party service for proxying, contact info@hailer.com.

WebSocket URLs are matched against the same host allow-list with wss:///ws:// substituted for https:///http://, and only services registered with WebSocket support accept upgrades.

fetch(url, options?) ​

ts
const res = await hailer.http.fetch('https://api.hailer.com/proxy/myservice/things', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ hello: 'world' }),
});
// res: { status, statusText, headers, body }

options (HTTPFetchOptions): method (GET|POST|PUT|DELETE|PATCH, default GET), headers (string→string map), body (string). The response body is text; parse JSON yourself. Response headers come back as a plain object.

upload(url, entries) ​

postMessage serializes messages as JSON, which does not preserve File/Blob/FormData. File uploads pass base64 field entries; the host reconstructs FormData before forwarding.

ts
const res = await hailer.http.upload(url, [
  { name: 'title', value: 'My upload' },                        // plain field
  { name: 'file', value: base64String, filename: 'photo.png' }, // file field (base64)
]);

Each HTTPUploadEntry is { name, value, filename? }. An entry with filename is decoded from base64 into a file part; one without is appended as a plain form field. Returns the same HTTPFetchResponse shape as fetch.

openWebSocket(url) ​

Returns an HTTPWebSocket synchronously (not a promise). Hailer opens the proxied socket and streams events to the handlers.

ts
const ws = hailer.http.openWebSocket('wss://api.hailer.com/proxy/myservice/stream');
ws.onopen = () => ws.send('hello');
ws.onmessage = event => console.log(event.data);
ws.onclose = event => console.log(event.code, event.reason);
ws.onerror = () => {};
ws.send('ping');
ws.close(code, reason);

Handlers: onopen, onmessage, onclose, onerror. Methods: send(data: string), close(code?, reason?). Also exposes readyState and connectionId. The socket is torn down when the app is destroyed.

Hailer Developer Documentation · v1.8.0