180 lines
5.1 KiB
Markdown
180 lines
5.1 KiB
Markdown
### 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`:
|
|
|
|
```kotlin
|
|
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:
|
|
|
|
```kotlin
|
|
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:
|
|
|
|
```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("https://127.0.0.1:") ||
|
|
op.url.startsWith("http://localhost:") ||
|
|
op.url.startsWith("https://localhost:")
|
|
)
|
|
AccessDecision(Decision.Allow)
|
|
else
|
|
AccessDecision(Decision.Deny, "only local HTTP/HTTPS requests are allowed")
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### Platform support
|
|
|
|
- **JVM:** supported
|
|
- **Android:** supported via the Ktor CIO client backend
|
|
- **JS:** supported via the Ktor JS client backend
|
|
- **Linux native:** supported via the Ktor Curl client backend
|
|
- **Windows native:** supported via the Ktor WinHttp client backend
|
|
- **Apple native:** supported via the Ktor Darwin client backend
|
|
- **Other targets:** may report unsupported; use `Http.isSupported()` before relying on it
|