Networking

This module of the core library contains functionality for communicating with remote systems over a network.

Sub Modules

Requests

The Requests submodule provides an HTTP client for sending requests to web servers and APIs.

The current HTTP client is provided by:

>@ "net/requests/http"

The http submodule uses libcurl and supports:

  • HTTP and HTTPS
  • GET
  • POST
  • PUT
  • PATCH
  • DELETE
  • HEAD
  • OPTIONS
  • Custom HTTP methods
  • Request headers
  • Request bodies
  • Query parameters
  • Redirects
  • TLS certificate verification
  • Compressed responses
  • HTTP/2 negotiation when supported by the server and installed libcurl version

The module returns HTTP responses as Hachi strings containing the response headers followed by the response body.

Import

Import the Requests HTTP client before using its functions:

>@ "net/requests/http"

Example:

>@ "net/requests/http"

response: httpGET:
    "https://example.com"

print: response

Compile and run normally:

hachi main.hachi -go

The module automatically declares its libcurl dependency. A separate -cf option is not required.

Response Format

All request functions return a String.

A successful HTTP transaction returns the response headers followed by the response body:

HTTP/2 200
content-type: application/json
content-length: 27

{"message":"Hello Hachi"}

An HTTP error status, such as 404 or 503, is still returned as a normal HTTP response:

HTTP/2 404
content-type: application/json

{"error":"Not Found"}

A network or transport failure returns a string beginning with:

Hachi HTTP error:

Example:

Hachi HTTP error: Could not resolve host

HTTP status codes do not currently cause the Hachi program to exit with a nonzero status. The calling program must inspect the returned response when it needs to distinguish successful and unsuccessful HTTP status codes.

Headers

Custom request headers are provided as a newline-separated string:

headers: "Accept: application/json
Content-Type: application/json
X-Hachi-Client: example"

Each header must use the following format:

Header-Name: Header Value

A trailing newline is not required.

Request Bodies

Request bodies are supplied as Hachi strings.

Example JSON body:

body: "{
  \"language\": \"Hachi\",
  \"mascot\": \"wolf\",
  \"working\": true
}"

Double quotes inside the body must be escaped.

Example form body:

body: "language=Hachi&mascot=wolf"

The calling program is responsible for constructing JSON, form data, query strings, and other request formats.

Functions

httpRequest

Sends a fully configurable HTTP request.

Use httpRequest when a request requires custom headers, a request body, authorization, or a custom HTTP method.

Syntax:

httpRequest:
    <method>,
    <url>,
    <headers>,
    <body>

Parameters:

ParameterTypeDescription
methodStringHTTP method to send
urlStringComplete request URL
headersStringNewline-separated request headers
bodyStringRequest body, or an empty string

Returns:

String

Example:

>@ "net/requests/http"

headers: "Accept: application/json
Content-Type: application/json"

body: "{
  \"message\": \"Hello from Hachi\"
}"

response: httpRequest:
    "POST",
    "https://httpbingo.org/anything",
    headers,
    body

print: response

A request without custom headers or a body uses empty strings:

response: httpRequest:
    "GET",
    "https://example.com",
    "",
    ""

httpGET

Sends an HTTP GET request.

Syntax:

httpGET: <url>

Returns:

String

Example:

>@ "net/requests/http"

response: httpGET:
    "https://example.com"

print: response

GET With Query Parameters

Query parameters are included directly in the URL:

response: httpGET:
    "https://httpbingo.org/anything?language=Hachi&wolf=true"

The caller is responsible for URL-encoding query parameter names and values when necessary.

GET With Custom Headers

Use httpRequest when a GET request requires custom headers:

headers: "Accept: application/json
X-Hachi-Test: custom-get
X-Client-Version: 0.5.3"

response: httpRequest:
    "GET",
    "https://httpbingo.org/anything",
    headers,
    ""

print: response

httpPOST

Sends an HTTP POST request with a request body.

Syntax:

httpPOST:
    <url>,
    <body>

Returns:

String

Example:

>@ "net/requests/http"

response: httpPOST:
    "https://httpbingo.org/anything",
    "message=Hello"

print: response

Use httpRequest when the POST request requires a content type or other custom headers.

JSON POST

headers: "Content-Type: application/json
Accept: application/json"

body: "{
  \"language\": \"Hachi\",
  \"mascot\": \"wolf\"
}"

response: httpRequest:
    "POST",
    "https://httpbingo.org/anything",
    headers,
    body

print: response

Form-Encoded POST

headers: "Content-Type: application/x-www-form-urlencoded
Accept: application/json"

body: "language=Hachi&mascot=wolf"

response: httpRequest:
    "POST",
    "https://httpbingo.org/anything",
    headers,
    body

print: response

httpPUT

Sends an HTTP PUT request with a request body.

Syntax:

httpPUT:
    <url>,
    <body>

Returns:

String

Example:

>@ "net/requests/http"

response: httpPUT:
    "https://httpbingo.org/anything/resource/42",
    "replacement value"

print: response

PUT With JSON

headers: "Content-Type: application/json
Accept: application/json"

body: "{
  \"resource\": \"core-http-module\",
  \"operation\": \"replace\",
  \"enabled\": true
}"

response: httpRequest:
    "PUT",
    "https://httpbingo.org/anything/resource/42",
    headers,
    body

print: response

httpPATCH

Sends an HTTP PATCH request with a request body.

Syntax:

httpPATCH:
    <url>,
    <body>

Returns:

String

Example:

>@ "net/requests/http"

response: httpPATCH:
    "https://httpbingo.org/anything/resource/42",
    "updated value"

print: response

PATCH With JSON

headers: "Content-Type: application/json
Accept: application/json"

body: "{
  \"operation\": \"partial-update\",
  \"enabled\": false
}"

response: httpRequest:
    "PATCH",
    "https://httpbingo.org/anything/resource/42",
    headers,
    body

print: response

httpDELETE

Sends an HTTP DELETE request without a request body.

Syntax:

httpDELETE: <url>

Returns:

String

Example:

>@ "net/requests/http"

response: httpDELETE:
    "https://httpbingo.org/anything/resource/42"

print: response

DELETE With a Body

Some APIs accept a request body with DELETE.

Use httpRequest for this case:

headers: "Content-Type: application/json
Accept: application/json"

body: "{
  \"reason\": \"resource no longer required\",
  \"force\": true
}"

response: httpRequest:
    "DELETE",
    "https://httpbingo.org/anything/resource/42",
    headers,
    body

print: response

Support for a DELETE request body depends on the remote server.


httpHEAD

Sends an HTTP HEAD request.

A HEAD request asks the server to return response headers without returning the normal response body.

Syntax:

httpHEAD: <url>

Returns:

String

Example:

>@ "net/requests/http"

response: httpHEAD:
    "https://example.com"

print: response

httpOPTIONS

Sends an HTTP OPTIONS request.

OPTIONS can be used to inspect the methods or capabilities advertised by a server.

Syntax:

httpOPTIONS: <url>

Returns:

String

Example:

>@ "net/requests/http"

response: httpOPTIONS:
    "https://httpbingo.org/anything"

print: response

The response may contain headers such as:

allow:
access-control-allow-methods:

The exact response depends on the server.

Custom HTTP Methods

httpRequest accepts methods other than the standard convenience functions.

Example using PROPFIND:

>@ "net/requests/http"

headers: "Content-Type: text/plain
X-Hachi-Test: custom-method"

response: httpRequest:
    "PROPFIND",
    "https://httpbingo.org/anything/custom-resource",
    headers,
    "Hachi custom HTTP method request body"

print: response

Other examples include:

response: httpRequest:
    "REPORT",
    url,
    headers,
    body
response: httpRequest:
    "LOCK",
    url,
    headers,
    body
response: httpRequest:
    "PURGE",
    url,
    headers,
    ""

The remote server must support the requested method.

Authorization

Authorization is provided through request headers.

Bearer Token

>@ "net/requests/http"

headers: "Accept: application/json
Authorization: Bearer hachi-example-token"

response: httpRequest:
    "GET",
    "https://httpbingo.org/anything",
    headers,
    ""

print: response

Basic Authorization

A preconstructed Basic authorization header can also be supplied:

headers: "Accept: application/json
Authorization: Basic <encoded-credentials>"

The module does not automatically encode credentials or retrieve tokens.

Applications should avoid storing production credentials directly in source code.

Redirects

Redirect following is enabled by default.

A redirected response may contain more than one HTTP header block:

HTTP/2 302
location: https://example.com/final

HTTP/2 200
content-type: text/html

<html>...</html>

The final header block normally describes the final response.

Compression

The module enables the response encodings supported by the installed libcurl build.

These may include:

  • gzip
  • deflate
  • Brotli
  • Zstandard

libcurl decompresses supported response bodies before they are returned to Hachi.

TLS

HTTPS certificate and hostname verification are enabled.

TLS verification failures are returned as transport errors:

Hachi HTTP error: <TLS error>

The current module does not provide a public option to disable TLS verification.

Timeouts

Requests currently use a 30-second total timeout.

A timeout returns an error similar to:

Hachi HTTP error: Operation timed out after 30000 milliseconds

The timeout is currently configured by the module and cannot be changed per request.

Default User Agent

The module sends the following default User-Agent:

Hachi-HTTP/1.0

A request can provide a different User-Agent through custom headers:

headers: "Accept: application/json
User-Agent: My-Hachi-Application/1.0"

Native Dependency

The http submodule declares its libcurl dependency internally:

nativePackage: "libcurl"

Hachi resolves the required compiler and linker flags automatically when the module is imported.

Normal usage requires only:

hachi main.hachi -go

The system must have libcurl, its development headers, and a working pkg-config package definition.

The installation can be checked with:

pkg-config --modversion libcurl

Complete Example

>@ "net/requests/http"

headers: "Content-Type: application/json
Accept: application/json
Authorization: Bearer example-token"

body: "{
  \"language\": \"Hachi\",
  \"mascot\": \"wolf\",
  \"working\": true
}"

response: httpRequest:
    "POST",
    "https://httpbingo.org/anything",
    headers,
    body

print: response

Run:

hachi main.hachi -go

Current Limitations

The current Requests module returns one raw response string.

It does not yet provide:

  • A structured response object
  • A numeric status-code accessor
  • Separate header and body return values
  • Automatic JSON encoding or decoding
  • Automatic URL encoding
  • Multipart form helpers
  • File upload helpers
  • Streaming downloads
  • Cookie or session management
  • Per-request timeout configuration
  • Proxy configuration through the Hachi API
  • Client certificate configuration through the Hachi API

These capabilities may be added in future versions.