How to use HTTP in KDB-X
This page explains how to use KDB-X to serve and consume HTTP and HTTPS requests, build web services, and interact with external APIs.
- Build a simple JSON API: Create a JSON API in minutes
- Use KDB-X as an HTTP server: Configure KDB-X to handle incoming HTTP and HTTPS requests
- Make HTTP requests from KDB-X: Send requests to external services
Build a simple JSON API
Start a web server in less than a minute. This example creates an API that serves a table of trade data as JSON.
-
Start the server: Start a q process on port 5000:
$ q -p 5000 -
Define the logic: Define dummy data and a request handler:
q)// Create a dummy table q)trades:([] time:3#.z.t; sym:`AAPL`GOOG`MSFT; price:150.5 2800.0 300.0; size:100 50 200) q)// Define the HTTP GET handler (.z.ph) q)// .h.hy generates a valid HTTP response with the correct Content-Type q).z.ph:{[x] .h.hy[`json] .j.j trades} -
Test it: Open
http://localhost:5000in a web browser. The trade data displays as a JSON array
About the .h namespace
The code above uses .h.hy to construct the HTTP response. The .h namespace contains many utilities for handling HTTP, HTML, and URL encoding.
Use KDB-X as an HTTP server
Configure a KDB-X process as a web server to handle HTTP requests directly. This allows you to create custom APIs, serve data, and build web interfaces.
Setup and configuration
Configure the listening port and security options.
- Listening port: The built-in HTTP server shares the listening port with KDB-X IPC and WebSocket services. HTTP requires no separate configuration. KDB-X automatically detects the protocol (HTTP, WebSocket, or IPC) of incoming connections
- SSL/TLS for HTTPS: To handle
httpstraffic and secure the server, configure KDB-X to use SSL/TLS. This ensures all communication between the client and server is encrypted
Enable HTTPS in two steps:
- Configure certificates: Set the environment variables (such as
SSL_CERT_FILEandSSL_KEY_FILE) to point to the server's certificate and private key files - Enable TLS mode: Start the KDB-X process with the
-Ecommand-line option (for example,-E 1for optional TLS or-E 2for mandatory TLS) to enable the TLS server mode
For a comprehensive guide on generating certificates and configuring these options, refer to the SSL/TLS configuration guide.
Request processing
Define how the server authenticates clients and handles different HTTP methods.
Authenticate and authorize
Secure HTTP endpoints by implementing custom logic in the .z.ac callback. This function acts as a gateway to integrate security mechanisms like LDAP, OAuth2, or OpenID Connect.
Method handlers
Override callback functions to define server behavior for different HTTP methods:
.z.ph: Handles HTTPGETrequests.z.pp: Handles HTTPPOSTrequests.z.pm: HandlesOPTIONS,PATCH,PUT, andDELETErequests
Default request handling
If you do not override default callbacks, KDB-X provides a built-in web interface:
- View data: Navigate to the root URL (for example,
http://localhost:5000) to view all variables and views in the global namespace - Execute code: Pass a q expression as a URL argument. For example,
http://localhost:5000?1+1returns2 - Serve static files: Set
.h.HOMEto a directory path. For example, if.h.HOMEis"/webserver",http://localhost:5000/index.htmlserves theindex.htmlfile from that directory
Security risk
Executing arbitrary code from a URL is a security risk in production. Implement robust authentication and authorization, or disable this feature.
Explore a custom web server example
For a practical example of a customized web server, refer to the simongarland/doth project.
Server performance
KDB-X includes features to optimize server performance and resource management.
- Keep-alive: Set
.h.kato enable persistent connections and reduce latency for clients making multiple requests - Compression: KDB-X automatically applies
gzipcompression forform?…requests if:- The client request header includes
Accept-Encoding: gzip - The response payload is 2000 characters or larger
- The client request header includes
Version requirement
Automatic gzip compression is available in v4.0 2020.03.17 and later.
Make HTTP requests from KDB-X
KDB-X acts as an HTTP client to fetch or send data to external web services and APIs.
Simple requests with helper functions
Use the .Q namespace helpers for common requests:
Automatic decompression
The .Q.hg function automatically handles decompression of gzipped responses.
Send a POST request
q)// Send a POST request with "my data" as the body and a plain text content type.
q)// Expected output (a JSON string from httpbin.org confirming the request)
q).Q.hp[`:http://httpbin.org/post; .h.ty`txt; "my data"]
"{\n \"args\": {}, \n \"data\": \"my data\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Accept-Encoding\": \"gzip\", \n \"Content-Length\": \"7\", \n \"Content-Type\": \"text/plain\", \n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-665711e1-19e62fef6b6e4d192a9a7096\"\n }, \n \"json\": null, \n \"origin\": \"78.147.173.108\", \n \"url\": \"http://httpbin.org/post\"\n}\n"
Request and decode a gzipped response
q)// .Q.hg fetches the URL and automatically handles decompression.
q)// .j.k then decodes the resulting JSON response into a KDB-X dictionary.
q)// Expected output (a dictionary)
q).j.k .Q.hg "http://httpbin.org/gzip"
gzipped| 1b
headers| `Accept-Encoding`Host`X-Amzn-Trace-Id!("gzip";"httpbin.org";"Root=1-665710aa-50bd49d724b532913348a62a")
method | "GET"
origin | "78.147.173.108"
Send raw HTTP requests
For complete control over headers and methods (like DELETE or PUT), send a raw HTTP request string.
`:http://host:port "raw http request string"
A valid request string contains:
- A request line (for example,
METHOD /path HTTP/1.1) ending with\r\n - Zero or more header fields (for example,
Header-Name: value), each ending with\r\n - An empty line (
\r\n) to signal the end of the headers - An optional message body
Send a DELETE request
// Construct a raw HTTP DELETE request string and send it.
request: "DELETE /anything HTTP/1.1\r\n",
"Connection: close\r\n",
"Host: httpbin.org\r\n",
"\r\n";
`:http://httpbin.org request
// Expected response (a raw string)
"HTTP/1.1 200 OK\r\ndate: Thu, 04 Dec 2025 02:05:56 GMT\r\ncontent-type: application/json\r\ncontent-length: 287\r\nconnection: close\r\nserver: gunicorn/19.9.0\r\naccess-control-allow-origin: *\r\naccess-control-allow-credentials: true\r\n\r\n{\n \"args\": {}, \n \"data\": \"\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6930ec84-57d8e9635721a096476a167a\"\n }, \n \"json\": null, \n \"method\": \"DELETE\", \n \"origin\": \"24.57.14.96\", \n \"url\": \"http://httpbin.org/anything\"\n}\n"
Send a POST request with a dynamic body
// Define the data to be sent
postdata: "hello"
// Construct the full request string, calculating Content-Length dynamically
request: "POST /anything HTTP/1.1\r\n",
"Connection: close\r\n",
"Host: httpbin.org\r\n",
"Content-Length: ",(string count postdata),"\r\n",
"\r\n",
postdata
`:http://httpbin.org request
// Expected response (a raw string)
"HTTP/1.1 200 OK\r\ndate: Thu, 04 Dec 2025 02:06:31 GMT\r\ncontent-type: application/json\r\ncontent-length: 318\r\nconnection: close\r\nserver: gunicorn/19.9.0\r\naccess-control-allow-origin: *\r\naccess-control-allow-credentials: true\r\n\r\n{\n \"args\": {}, \n \"data\": \"hello\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Content-Length\": \"5\", \n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6930eca6-720b0c230412593a392f6fa9\"\n }, \n \"json\": null, \n \"method\": \"POST\", \n \"origin\": \"24.57.14.96\", \n \"url\": \"http://httpbin.org/anything\"\n}\n"
Parse the response body
The server response is a raw string. Parse it to separate the headers from the body.
q)// Execute the request and store the full raw response in 'x'
q)x: `:http://httpbin.org "DELETE /delete HTTP/1.1\r\nConnection: close\r\nHost: httpbin.org\r\n\r\n"
q)// Split the response string 'x' by the double newline ("\r\n\r\n")
q)// and take the second item (index 1), which is the body.
q)body: @["\r\n\r\n" vs x; 1];
q)// Expected output (the JSON body as a string)
q)show body;
"{\n \"args\": {}, \n \"data\": \"\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-66572924-7396cee34f268fcd406e94d5\"\n }, \n \"json\": null, \n \"origin\": \"78.147.173.108\", \n \"url\": \"http://httpbin.org/delete\"\n}\n"
Chunked transfer encoding
If a server uses chunked transfer encoding, KDB-X automatically reconstructs the full response from the chunks. This feature is available in v3.3 2014.07.31 and later.
Use HTTPS in client requests
Prerequisite for HTTPS
To send client requests over HTTPS, first configure KDB-X to use SSL/TLS.
Once configured, replace http with https in your target URL. All methods described above work over the secure connection.
Further reading
Refer to the .h namespace for utilities for HTTP protocol formatting, URL encoding, and HTML markup generation.
For more information, refer to:
Summary
In this guide, you:
- Configured a KDB-X process as an HTTP/S server
- Implemented custom logic for
GET,POST, and other requests - Used helper functions for simple client requests
- Sent low-level HTTP requests for advanced control
- Configured SSL/TLS for secure server and client operations