lyng/docs/lyng.io.http.md

4.6 KiB

lyng.io.http — HTTP/HTTPS client for Lyng scripts

This module provides a compact HTTP client API for Lyng scripts. It is implemented in lyngio and backed by Ktor on supported runtimes.

Note: lyngio is a separate library module. It must be explicitly added as a dependency to your host application and initialized in your Lyng scopes.


Add the library to your project (Gradle)

If you use this repository as a multi-module project, add a dependency on :lyngio:

dependencies {
    implementation("net.sergeych:lyngio:0.0.1-SNAPSHOT")
}

For external projects, ensure you also use the Lyng Maven repository described in lyng.io.fs.


Install the module into a Lyng session

The HTTP module is not installed automatically. Install it into the session scope and provide a policy.

Kotlin (host) bootstrap example:

import net.sergeych.lyng.EvalSession
import net.sergeych.lyng.Scope
import net.sergeych.lyng.io.http.createHttpModule
import net.sergeych.lyngio.http.security.PermitAllHttpAccessPolicy

suspend fun bootstrapHttp() {
    val session = EvalSession()
    val scope: Scope = session.getScope()
    createHttpModule(PermitAllHttpAccessPolicy, scope)
    session.eval("import lyng.io.http")
}

Using from Lyng scripts

Simple GET:

import lyng.io.http

val r = Http.get(HTTP_TEST_URL + "/hello")
[r.status, r.text()]
>>> [200,hello from test]

Headers and response header access:

import lyng.io.http

val r = Http.get(HTTP_TEST_URL + "/headers")
[r.headers["X-Reply"], r.headers.getAll("X-Reply").size, r.text()]
>>> [one,2,header demo]

Programmatic request object:

import lyng.io.http

val q = HttpRequest()
q.method = "POST"
q.url = HTTP_TEST_URL + "/echo"
q.headers = Map("Content-Type" => "text/plain")
q.bodyText = "ping"

val r = Http.request(q)
r.text()
>>> "POST:ping"

HTTPS GET:

import lyng.io.http

val r = Http.get(HTTPS_TEST_URL + "/hello")
[r.status, r.text()]
>>> [200,hello from test]

API reference

Http (static methods)
  • isSupported(): Bool — Whether HTTP client support is available on the current runtime.
  • request(req: HttpRequest): HttpResponse — Execute a request described by a mutable request object.
  • get(url: String, headers...): HttpResponse — Convenience GET request.
  • post(url: String, bodyText: String = "", contentType: String? = null, headers...): HttpResponse — Convenience text POST request.
  • postBytes(url: String, body: Buffer, contentType: String? = null, headers...): HttpResponse — Convenience binary POST request.

For convenience methods, headers... accepts:

  • MapEntry, e.g. "Accept" => "text/plain"
  • 2-item lists, e.g. ["Accept", "text/plain"]
HttpRequest
  • method: String
  • url: String
  • headers: Map<String, String>
  • bodyText: String?
  • bodyBytes: Buffer?
  • timeoutMillis: Int?

Only one of bodyText and bodyBytes should be set.

HttpResponse
  • status: Int
  • statusText: String
  • headers: HttpHeaders
  • text(): String
  • bytes(): Buffer

Response body decoding is cached inside the response object.

HttpHeaders

HttpHeaders behaves like Map<String, String> for the first value of each header name and additionally exposes:

  • get(name: String): String?
  • getAll(name: String): List<String>
  • names(): List<String>

Header lookup is case-insensitive.


Security policy

The module uses HttpAccessPolicy to authorize requests before they are sent.

  • HttpAccessPolicy — interface for custom policies
  • PermitAllHttpAccessPolicy — allows all requests
  • HttpAccessOp.Request(method, url) — operation checked by the policy

Example restricted policy in Kotlin:

import net.sergeych.lyngio.fs.security.AccessContext
import net.sergeych.lyngio.fs.security.AccessDecision
import net.sergeych.lyngio.fs.security.Decision
import net.sergeych.lyngio.http.security.HttpAccessOp
import net.sergeych.lyngio.http.security.HttpAccessPolicy

val allowLocalOnly = object : HttpAccessPolicy {
    override suspend fun check(op: HttpAccessOp, ctx: AccessContext): AccessDecision =
        when (op) {
            is HttpAccessOp.Request ->
                if (op.url.startsWith("http://127.0.0.1:") || op.url.startsWith("http://localhost:"))
                    AccessDecision(Decision.Allow)
                else
                    AccessDecision(Decision.Deny, "only local HTTP requests are allowed")
        }
}

Platform support

  • JVM: supported
  • Other targets: implementation may be added later; use Http.isSupported() before relying on it