Add http client releated api, and add chinese docs

This commit is contained in:
2026-01-03 06:21:49 +08:00
parent 3e95c8f71a
commit a8e8063fe7
5 files changed
+200 -3

No files matched your search

+160
View File
@@ -0,0 +1,160 @@
# Kotlin cloudflare worker
纯Kotlin编写的库,可以在Cloudflare worker上运行Kotlin/JS
# 快速开始
## 配置
> 项目依赖于Kotlin协程库, 请确保协程库版本号大于`1.10.2`
```kotlin
plugins {
kotlin("multiplatform") version "2.2.21"
}
repositories {
mavenCentral()
maven("https://repo.maven.rtast.cn/releases")
}
```
```kotlin
// 最新版本请前往下方链接查看
// https://next.pkg.rtast.cn/#/releases/cn/rtast/kotlin-cfworker/kotlin-cloudflare-worker/
implementation("cn.rtast.kotlin-cfworker:kotlin-cloudflare-worker:1.0.2")
```
## Hello world程序
```kotlin
kotlin {
js(IR) {
nodejs {
outputModuleName = "kotlin-cloudflare-worker"
binaries.executable()
}
}
}
```
> Minimal hello world app
```kotlin
/**
* 不要修改这个函数的任何内容
*/
fun main() {
@Suppress("unused_expression")
val eventListener = EventListener { event ->
val dyn = event.asDynamic()
event.asDynamic().respondWith(handleRequest(dyn.request as Request))
Unit
}
js("addEventListener('fetch', eventListener)")
}
/**
* 这里是处理http请求的函数
*/
@JsExport
fun handleRequest(request: Request): Promise<Response> = GlobalScope.promise {
val server = WorkerApplication().apply {
route("/") {
respondText("Hello kotlin cloudflare worker")
}
}
return@promise server.handle(request)
}
```
> 在本地运行之前需要先安装wrangler
在项目根目录创建一个名为`wrangler.toml`的文件,然后将下面的内容复制进去并修改为你自己的信息
```toml
name = "kotlin-cloudflare-worker" # 可以是任何名字
account_id = "<your account id>"
workers_dev = false
preview_urls = false
compatibility_date = "2022-08-11"
main = "kotlin-cloudflare-worker.js" # 必须和`outputModuleName`一致
```
运行gradle任务编译出js `gradlew compileProductionExecutableKotlinJs`,
将wrangler.toml复制到 `build/compileSync/js/main/productionExecutable/kotlin`,
并且进入该目录下运行`wrangler dev`
## 部署
使用`wrangler deploy`来部署到cloudflare worker, 在此之前你需要先使用`wrangler login`来登录
# 注意事项
Cloudflare worker 使用V8引擎来驱动js脚本,线程模型为单线程,所有时间均有event loop(事件循环)驱动,在此之外的所有任务
都会被drop, 所以不要使用协程库中的launch或任何可以凭空创建出一个挂起作用域的函数来调用suspend函数, 取而代之的是你需要从
`handleRequest`方法中传播`CoroutineScope`(suspend), 就像下面这样
```kotlin
// 不要使用这种方法
val scope = CoroutineScope(Dispatcher.DEFAULT)
fun blockingFunction() {
scope.launch {
// 这里的代码永远不会被执行
}
}
// 使用下面的代码来正确的调用suspend函数
fun main() {
@Suppress("unused_expression")
val eventListener = EventListener { event ->
val dyn = event.asDynamic()
event.asDynamic().respondWith(handleRequest(dyn.request as Request))
Unit
}
js("addEventListener('fetch', eventListener)")
}
@JsExport
fun handleRequest(request: Request): Promise<Response> = GlobalScope.promise {
return Promise.resolve(Response("Hello"))
}
```
# Http 客户端
不要使用ktor来作为http客户端, 因为cloudflare worker不是一个标准的nodejs环境, 你需要使用 fetch
`cn.rtast.cfworker.client.fetch` 来发送http请求, 注意不是`window.fetch` `window.fetch`是浏览器API
# ByteArray 和 ByteBuffer 转换
```kotlin
import cn.rtast.cfworker.util.toByteArray
import cn.rtast.cfworker.util.toArrayBuffer
val bb: ByteBuffer = ...
// 将ByteBuffer转换为ByteArray
val ba: ByteArray = bb.toByteArray()
// 将ByteArray转换为ByteBuffer
val bb2: ByteBuffer = ba.toArrayBuffer()
```
# CPU时间限制
cloudflare worker 免费版本限制处理每个请求的CPU时间为10ms(不包括IO等待时间), 如果你需要执行CPU密集型任务或需要更高的配额,
请考虑升级到Workers paid或使用JS来减少标准库和协程库的加载时间.
即使使用此库注册了超过15个api端点,并且都具备文件处理功能,每个请求占用的cpu时间平均值不超过10ms+-2ms,
在冷启动时处理首次请求时间会大幅增加,最高可达50ms,但worker仍然可以处理并返回请求.
![avg-cpu-time](./images/avg-cpu-time.png)
> 上图反应了过去24小时每个请求的平均cpu时间(P50)
# 已经使用此项目的实例
https://repo.maven.rtast.cn
+20 -1
View File
@@ -2,6 +2,11 @@
A library to running kotlin/js on cloudflare worker.
<div style="display: block">
<a href="README.md">English</a>
<a href="README-zh.md">中文</a>
</div>
# Get started
## Setup
@@ -22,7 +27,7 @@ repositories {
```kotlin
// to get latest version of this lib, go to
// https://next.pkg.rtast.cn/#/releases/cn/rtast/kotlin-cfworker/kotlin-cloudflare-worker/
implementation("cn.rtast.kotlin-cfworker:kotlin-cloudflare-worker:1.0.1")
implementation("cn.rtast.kotlin-cfworker:kotlin-cloudflare-worker:1.0.2")
```
## Run app
@@ -148,6 +153,20 @@ val ba: ByteArray = bb.toByteArray()
val bb2: ByteBuffer = ba.toArrayBuffer()
```
# CPU Time limit
Cloudflare worker free tier have a limit of worker cpu limit (10ms, exclude IO waiting time), `kotlin cloudflare worker`
depends on `kotlin-stdlib` and `kotlinx.coroutines`, which are quite heavy*, When performing CPU-bound task,
please carefully consider whether to use JavaScript instead of Kotlin.
But it works for my maven repository, I registered over 15 api endpoints.
The avg cpu time for each endpoint does not exceed 10ms, but it may increase significantly during
cold start (Over 50-200ms, but still responsible)
![avg-cpu-time](./images/avg-cpu-time.png)
> This image shows last 24 hours avg cpu time, see `P50`
# Real instance
https://repo.maven.rtast.cn
+1 -1
View File
@@ -4,7 +4,7 @@ plugins {
}
group = "cn.rtast.kotlin-cfworker"
version = "1.0.1"
version = "1.0.2"
repositories {
mavenCentral()
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

@@ -7,11 +7,29 @@
package cn.rtast.cfworker.client
import cn.rtast.cfworker.util.toByteArray
import kotlinx.coroutines.await
import org.w3c.dom.url.URL
import org.w3c.fetch.Request
import org.w3c.fetch.RequestInit
import org.w3c.fetch.Response
import kotlin.js.Promise
/**
* define fetch function externally
*/
public external fun fetch(
input: String,
init: RequestInit = definedExternally,
): Promise<Response>
): Promise<Response>
/**
* Get request raw body, http POST
*/
public suspend fun Request.rawBody(): ByteArray =
this.arrayBuffer().await().toByteArray()
/**
* Get [URL] object
*/
public val Request.Url: URL get() = URL(this.url)