HTTP 服务器
您可以在脚本中启动一个本地 HTTP 服务器,用于接收外部请求,这在模拟 API、搭建临时 Web 服务等场景中非常有用。
启动和停止服务器
import com.m8test.script.GlobalVariables.*
// 确保脚本在后台运行
_threads.getMain().setBackground(true)
val scope = _coroutines.newScope(null)
val port = 8080
// 启动一个服务器
val httpServer = _httpServers.startServer(port) {
routing {
// get 的处理器是 HttpServerCall.(CoroutineScope) -> Job
// 所以 lambda 只有一个参数 s (CoroutineScope),HttpServerCall 是 this
get("/") { s ->
val request = getRequest() // 使用 this.getRequest()
_console.log("[服务器] 收到来自 ${request.getOriginConnectionPoint().getRemoteHost()} 的根路径请求")
// respondText 返回一个 Job
getResponse().respondText(s, "你好,世界!来自 M8Test HTTP 服务器.") { it.getTextPlain() }
}
get("/json") { s ->
_console.log("[服务器] 收到 /json 路径请求")
val jsonResponse = """{"status": "ok", "timestamp": ${System.currentTimeMillis()}}"""
getResponse().respondText(s, jsonResponse) { it.getApplicationJson() }
}
}
}
_console.log("HTTP 服务器已在 http://127.0.0.1:$port 启动")
// 创建客户端进行测试
val httpClient = _httpClients.newClient(null)
// 延迟1秒确保服务器已完全启动
scope.delay(1000).then { s, v ->
_console.log("[客户端] 开始测试服务器...")
val req1 = httpClient.get(s, "http://127.0.0.1:$port/", null, null)
val req2 = httpClient.get(s, "http://127.0.0.1:$port/json", null, null)
// 等待所有请求完成
s.awaitAll(listOf(req1, req2))
}.then { s, responses ->
val resp1Text = responses[0].getTextBody(s)
val resp2Text = responses[1].getTextBody(s)
s.awaitAll(listOf(resp1Text, resp2Text))
}.then { s, bodies ->
_console.log("[客户端] 根路径响应:", bodies[0])
_console.log("[客户端] /json 路径响应:", bodies[1])
s.resolve(null)
}.onError { error ->
_console.error("[客户端] 测试失败:", error)
}.onComplete {
_console.log("测试完成,正在关闭服务器...")
_httpServers.stopServer(httpServer)
}
// 确保脚本在后台运行
$threads.getMain().setBackground(true)
def scope = $coroutines.newScope(null)
def port = 8080
// 启动一个服务器
def httpServer = $httpServers.startServer(port, { config ->
config.routing({ route ->
route.get("/", { call, s ->
def request = call.getRequest()
$console.log("[服务器] 收到来自 ${request.getOriginConnectionPoint().getRemoteHost()} 的根路径请求")
// respondText 现在返回一个 Job,这成为 get 处理器块的返回值
call.getResponse().respondText(s, "你好,世界!来自 M8Test HTTP 服务器。", { it.getTextPlain() })
})
route.get("/json", { call, s ->
$console.log("[服务器] 收到 /json 路径请求")
def jsonResponse = '{"status": "ok", "timestamp": ' + System.currentTimeMillis() + '}'
call.getResponse().respondText(s, jsonResponse, { it.getApplicationJson() })
})
})
})
$console.log("HTTP 服务器已在 http://127.0.0.1:${port} 启动")
// 创建客户端进行测试
def httpClient = $httpClients.newClient(null)
// 延迟1秒确保服务器已完全启动
scope.delay(1000).then({ s, v ->
$console.log("[客户端] 开始测试服务器...")
def req1 = httpClient.get(s, "http://127.0.0.1:${port}/", null, null)
def req2 = httpClient.get(s, "http://127.0.0.1:${port}/json", null, null)
// 等待所有请求完成
s.awaitAll([req1, req2])
}).then({ s, responses ->
def resp1Text = responses[0].getTextBody(s)
def resp2Text = responses[1].getTextBody(s)
s.awaitAll([resp1Text, resp2Text])
}).then({ s, bodies ->
$console.log("[客户端] 根路径响应:", bodies[0])
$console.log("[客户端] /json 路径响应:", bodies[1])
s.resolve(null)
}).onError({ error ->
$console.error("[客户端] 测试失败:", error)
}).onComplete({
$console.log("测试完成,正在关闭服务器...")
$httpServers.stopServer(httpServer)
})
// 确保脚本在后台运行
$threads.getMain().setBackground(true);
const scope = $coroutines.newScope(null);
const port = 8080;
// 启动一个服务器
const httpServer = $httpServers.startServer(port, config => {
config.routing(route => {
route.get("/", (call, s) => {
const request = call.getRequest();
$console.log("[服务器] 收到来自 " + request.getOriginConnectionPoint().getRemoteHost() + " 的根路径请求");
// respondText 现在返回一个 Job,这成为 get 处理器块的返回值,必须返回
return call.getResponse().respondText(s, "你好,世界!来自 M8Test HTTP 服务器。", it => it.getTextPlain());
});
route.get("/json", (call, s) => {
$console.log("[服务器] 收到 /json 路径请求");
const jsonResponse = '{"status": "ok", "timestamp": ' + Date.now() + '}';
return call.getResponse().respondText(s, jsonResponse, it => it.getApplicationJson());
});
});
});
$console.log("HTTP 服务器已在 http://127.0.0.1:" + port + " 启动");
// 创建客户端进行测试
const httpClient = $httpClients.newClient(null);
// 延迟1秒确保服务器已完全启动
scope.delay(1000).then((s, v) => {
$console.log("[客户端] 开始测试服务器...");
const req1 = httpClient.get(s, "http://127.0.0.1:" + port + "/", null, null);
const req2 = httpClient.get(s, "http://127.0.0.1:" + port + "/json", null, null);
// 等待所有请求完成
return s.awaitAll([req1, req2]);
}).then((s, responses) => {
const resp1Text = responses[0].getTextBody(s);
const resp2Text = responses[1].getTextBody(s);
return s.awaitAll([resp1Text, resp2Text]);
}).then((s, bodies) => {
$console.log("[客户端] 根路径响应:", bodies[0]);
$console.log("[客户端] /json 路径响应:", bodies[1]);
return s.resolve(null);
}).onError(error => {
$console.error("[客户端] 测试失败:", error);
}).onComplete(() => {
$console.log("测试完成,正在关闭服务器...");
$httpServers.stopServer(httpServer);
});
-- 确保脚本在后台运行
_threads:getMain():setBackground(true)
local scope = _coroutines:newScope(nil)
local port = 8080
-- 引入 System 类用于获取时间戳
local System = require("m8test_java.java.lang.System")
-- 启动一个服务器
local httpServer = _httpServers:startServer(port, function(config)
config:routing(function(route)
route:get("/", function(call, s)
local request = call:getRequest()
_console:log("[服务器] 收到来自 " .. request:getOriginConnectionPoint():getRemoteHost() .. " 的根路径请求")
-- respondText 现在返回一个 Job,这成为 get 处理器块的返回值
return call:getResponse():respondText(s, "你好,世界!来自 M8Test HTTP 服务器。", function(it) return it:getTextPlain() end)
end)
route:get("/json", function(call, s)
_console:log("[服务器] 收到 /json 路径请求")
local jsonResponse = '{"status": "ok", "timestamp": ' .. tostring(System:currentTimeMillis()) .. '}'
return call:getResponse():respondText(s, jsonResponse, function(it) return it:getApplicationJson() end)
end)
end)
end)
_console:log("HTTP 服务器已在 http://127.0.0.1:" .. tostring(port) .. " 启动")
-- 创建客户端进行测试
local httpClient = _httpClients:newClient(nil)
-- 延迟1秒确保服务器已完全启动
scope:delay(1000):_then(function(s, v)
_console:log("[客户端] 开始测试服务器...")
local req1 = httpClient:get(s, "http://127.0.0.1:" .. tostring(port) .. "/", nil, nil)
local req2 = httpClient:get(s, "http://127.0.0.1:" .. tostring(port) .. "/json", nil, nil)
-- 等待所有请求完成
return s:awaitAll(_iterables:listOf(req1, req2))
end):_then(function(s, responses)
-- 修正:Java List 是 0-based 索引。第一个元素是 get(0),第二个是 get(1)。
local resp1Text = responses:get(0):getTextBody(s)
local resp2Text = responses:get(1):getTextBody(s)
-- 同样,这里也需要一个 Java List
return s:awaitAll(_iterables:listOf(resp1Text, resp2Text))
end):_then(function(s, bodies)
-- 修正:Java List 是 0-based 索引。
_console:log("[客户端] 根路径响应:", bodies:get(0))
_console:log("[客户端] /json 路径响应:", bodies:get(1))
return s:resolve(nil)
end):onError(function(error)
if error ~= nil then
_console:error("[客户端] 测试失败:", error:stackTraceToString())
else
_console:error("[客户端] 测试失败,但未提供错误详情。")
end
end):onComplete(function()
_console:log("测试完成,正在关闭服务器...")
_httpServers:stopServer(httpServer)
end)
<?php
/** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */
global $threads;
/** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */
global $coroutines;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpServers $httpServers */
global $httpServers;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpClients $httpClients */
global $httpClients;
/** @var m8test_java\com\m8test\script\core\api\console\Console $console */
global $console;
/** @var m8test_java\com\m8test\script\core\api\collections\Iterables $iterables */
global $iterables;
/** @var m8test_java\java\lang\System $System */
use m8test_java\java\lang\System;
// 确保脚本在后台运行
$threads->getMain()->setBackground(true);
$scope = $coroutines->newScope(function ($context) {
$context->setDispatcher(function ($dispatchers) {
return $dispatchers->getScriptMain();
});
});
$port = 8080;
// 启动一个服务器
$httpServer = $httpServers->startServer($port, function ($config) {
$config->routing(function ($route) {
$route->get(javaString("/"), function ($call, $s) {
global $console;
$request = $call->getRequest();
$console->log(javaString("[服务器] 收到来自 ") . $request->getOriginConnectionPoint()->getRemoteHost() . javaString(" 的根路径请求"));
// respondText 现在返回一个 Job,这成为 get 处理器块的返回值
return $call->getResponse()->respondText($s, javaString("你好,世界!来自 M8Test HTTP 服务器。"), function ($it) {
return $it->getTextPlain();
});
});
$route->get(javaString("/json"), function ($call, $s) {
global $console;
$console->log(javaString("[服务器] 收到 /json 路径请求"));
$jsonResponse = javaString('{"status": "ok", "timestamp": ') . System::currentTimeMillis() . '}';
return $call->getResponse()->respondText($s, $jsonResponse, function ($it) {
return $it->getApplicationJson();
});
});
});
});
$console->log(javaString("HTTP 服务器已在 http://127.0.0.1:${port} 启动"));
// 创建客户端进行测试
$httpClient = $httpClients->newClient(null);
// 延迟1秒确保服务器已完全启动
$scope->delay(1000)->then(function ($s, $v) use ($httpClient, $port) {
global $console, $iterables;
$console->log(javaString("[客户端] 开始测试服务器..."));
$req1 = $httpClient->get($s, javaString("http://127.0.0.1:${port}/"), null, null);
$req2 = $httpClient->get($s, javaString("http://127.0.0.1:${port}/json"), null, null);
// 等待所有请求完成 (修正点1: 添加 return, 修正点2: 使用 listOf)
return $s->awaitAll($iterables->listOf($req1, $req2));
})->then(function ($s, $responses) {
global $iterables;
$resp1Text = $responses->get(0)->getTextBody($s);
$resp2Text = $responses->get(1)->getTextBody($s);
// 修正点3: 同样使用 listOf 以保持一致和稳健
return $s->awaitAll($iterables->listOf($resp1Text, $resp2Text));
})->then(function ($s, $bodies) {
global $console;
$console->log(javaString("[客户端] 根路径响应:"), $bodies->get(0));
$console->log(javaString("[客户端] /json 路径响应:"), $bodies->get(1));
return $s->resolve(null);
})->onError(function ($error) {
global $console;
$console->error(javaString("[客户端] 测试失败:"), $error);
})->onComplete(function () use ($httpServer) {
global $console, $httpServers;
$console->log(javaString("测试完成,正在关闭服务器..."));
$httpServers->stopServer($httpServer);
});
# 导入Python标准库
import time
from m8test_java.com.m8test.script.GlobalVariables import _console
from m8test_java.com.m8test.script.GlobalVariables import _coroutines
from m8test_java.com.m8test.script.GlobalVariables import _httpClients
from m8test_java.com.m8test.script.GlobalVariables import _httpServers
# 导入所需的全局变量
from m8test_java.com.m8test.script.GlobalVariables import _threads
# 确保脚本在后台运行
_threads.getMain().setBackground(True)
scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain()))
port = 8080
# 启动一个服务器
httpServer = _httpServers.startServer(port, lambda config:
config.routing(lambda route: (
route.get("/", lambda call, s: (
(request := call.getRequest()),
_console.log(f"[服务器] 收到来自 {request.getOriginConnectionPoint().getRemoteHost()} 的根路径请求"),
# respondText 现在返回一个 Job,这成为 get 处理器块的返回值
call.getResponse().respondText(s, "你好,世界!来自 M8Test HTTP 服务器。", lambda it: it.getTextPlain())
)[-1]),
route.get("/json", lambda call, s: (
_console.log("[服务器] 收到 /json 路径请求"),
# 使用 f-string 和 time.time() 来构造JSON
(jsonResponse := f'{{"status": "ok", "timestamp": {int(time.time() * 1000)}}}'),
call.getResponse().respondText(s, jsonResponse, lambda it: it.getApplicationJson())
)[-1])
))
)
_console.log(f"HTTP 服务器已在 http://127.0.0.1:{port} 启动")
# 创建客户端进行测试
httpClient = _httpClients.newClient(None)
# 延迟1秒确保服务器已完全启动
scope.delay(1000).then(lambda s, v: (
_console.log("[客户端] 开始测试服务器..."),
(req1 := httpClient.get(s, f"http://127.0.0.1:{port}/", None, None)),
(req2 := httpClient.get(s, f"http://127.0.0.1:{port}/json", None, None)),
# 等待所有请求完成
s.awaitAll([req1, req2])
)[-1]).then(lambda s, responses: (
(resp1Text := responses[0].getTextBody(s)),
(resp2Text := responses[1].getTextBody(s)),
s.awaitAll([resp1Text, resp2Text])
)[-1]).then(lambda s, bodies: (
_console.log("[客户端] 根路径响应: " + str(bodies[0])),
_console.log("[客户端] /json 路径响应: " + str(bodies[1])),
s.resolve(None)
)[-1]).onError(lambda error: (
_console.error("[客户端] 测试失败: " + str(error))
)).onComplete(lambda: ( # 使用 lambda _: 以安全地接收可能存在的参数
_console.log("测试完成,正在关闭服务器..."),
_httpServers.stopServer(httpServer)
))
# encoding: utf-8
# 确保脚本在后台运行
$threads.getMain.setBackground(true)
scope = $coroutines.newScope(nil)
port = 8080
# 启动一个服务器
httpServer = $httpServers.startServer(port) do |config|
config.routing do |route|
route.get("/") do |call, s|
request = call.getRequest
$console.log("[服务器] 收到来自 #{request.getOriginConnectionPoint.getRemoteHost} 的根路径请求")
# respondText 现在返回一个 Job,这成为 get 处理器块的返回值
call.getResponse.respondText(s, "你好,世界!来自 M8Test HTTP 服务器.") do |it|
it.getTextPlain
end
end
route.get("/json") do |call, s|
$console.log("[服务器] 收到 /json 路径请求")
# 使用静态方法调用 System.currentTimeMillis
jsonResponse = '{"status": "ok", "timestamp": ' + M8testJava::Java::Lang::System::N__currentTimeMillis().to_s + '}'
call.getResponse.respondText(s, jsonResponse) do |it|
it.getApplicationJson
end
end
end
end
$console.log("HTTP 服务器已在 http://127.0.0.1:#{port} 启动")
# 创建客户端进行测试
httpClient = $httpClients.newClient(nil)
# 延迟1秒确保服务器已完全启动
scope.delay(1000).then do |s, v|
$console.log("[客户端] 开始测试服务器...")
req1 = httpClient.get(s, "http://127.0.0.1:#{port}/", nil, nil)
req2 = httpClient.get(s, "http://127.0.0.1:#{port}/json", nil, nil)
# 等待所有请求完成
s.awaitAll([req1, req2])
end.then do |s, responses|
resp1Text = responses[0].getTextBody(s)
resp2Text = responses[1].getTextBody(s)
s.awaitAll([resp1Text, resp2Text])
end.then do |s, bodies|
$console.log("[客户端] 根路径响应:", bodies[0])
$console.log("[客户端] /json 路径响应:", bodies[1])
s.resolve(nil)
end.onError do |error|
$console.error("[客户端] 测试失败:", error)
end.onComplete do
$console.log("测试完成,正在关闭服务器...")
$httpServers.stopServer(httpServer)
end
高级路由和请求处理
处理路径参数和查询参数
import com.m8test.script.GlobalVariables.*
// 确保脚本在后台运行
_threads.getMain().setBackground(true)
val scope = _coroutines.newScope(null)
val port = 8081
val httpServer = _httpServers.startServer(port) {
routing {
// 同样移除 call 参数,使用 this
get("/users/{name}") { s ->
val request = getRequest()
val name = request.getPathParameters()["name"]?.get(0)
val role = request.getQueryParameters()["role"]?.get(0) ?: "guest"
val responseText = "你好, $name! 你的角色是: $role"
_console.log("[服务器] 正在响应: $responseText")
getResponse().respondText(s, responseText, null)
}
}
}
_console.log("服务器已在 http://127.0.0.1:$port 启动")
// 客户端测试
val httpClient = _httpClients.newClient(null)
scope.delay(1000).then { s, v ->
httpClient.get(s, "http://127.0.0.1:$port/users/M8Test?role=developer", null, null)
}.then { s, response ->
response.getTextBody(s)
}.then { s, body ->
_console.log("[客户端] 收到响应:", body)
s.resolve(null)
}.onError { error ->
_console.error("[客户端] 测试失败:", error)
}.onComplete {
_httpServers.stopServer(httpServer)
}
// 确保脚本在后台运行
$threads.getMain().setBackground(true)
def scope = $coroutines.newScope(null)
def port = 8081
def httpServer = $httpServers.startServer(port, { config ->
config.routing({ route ->
route.get("/users/{name}", { call, s ->
def request = call.getRequest()
def name = request.getPathParameters()["name"]?.get(0)
def role = request.getQueryParameters()["role"]?.get(0) ?: "guest"
def responseText = "你好, ${name}! 你的角色是: ${role}"
$console.log("[服务器] 正在响应: ${responseText}")
// 返回 respondText 返回的 Job
call.getResponse().respondText(s, responseText, null)
})
})
})
$console.log("服务器已在 http://127.0.0.1:${port} 启动")
// 客户端测试
def httpClient = $httpClients.newClient(null)
scope.delay(1000).then({ s, v ->
httpClient.get(s, "http://127.0.0.1:${port}/users/M8Test?role=developer", null, null)
}).then({ s, response ->
response.getTextBody(s)
}).then({ s, body ->
$console.log("[客户端] 收到响应:", body)
s.resolve(null)
}).onError({ error ->
$console.error("[客户端] 测试失败:", error)
}).onComplete({
$httpServers.stopServer(httpServer)
})
// 确保脚本在后台运行
$threads.getMain().setBackground(true);
const scope = $coroutines.newScope(null);
const port = 8081;
const httpServer = $httpServers.startServer(port, config => {
config.routing(route => {
route.get("/users/{name}", (call, s) => {
const request = call.getRequest();
const name = request.getPathParameters().get("name")?.get(0);
const role = request.getQueryParameters().get("role")?.get(0) ?? "guest";
const responseText = "你好, " + name + "! 你的角色是: " + role;
$console.log("[服务器] 正在响应: " + responseText);
// respondText 返回 Job,必须返回
return call.getResponse().respondText(s, responseText, null);
});
});
});
$console.log("服务器已在 http://127.0.0.1:" + port + " 启动");
// 客户端测试
const httpClient = $httpClients.newClient(null);
scope.delay(1000).then((s, v) => {
return httpClient.get(s, "http://127.0.0.1:" + port + "/users/M8Test?role=developer", null, null);
}).then((s, response) => {
return response.getTextBody(s);
}).then((s, body) => {
$console.log("[客户端] 收到响应:", body);
return s.resolve(null);
}).onError(error => {
$console.error("[客户端] 测试失败:", error);
}).onComplete(() => {
$httpServers.stopServer(httpServer);
});
-- 确保脚本在后台运行
_threads:getMain():setBackground(true)
local scope = _coroutines:newScope(nil)
local port = 8081
local httpServer = _httpServers:startServer(port, function(config)
config:routing(function(route)
route:get("/users/{name}", function(call, s)
local request = call:getRequest()
-- ?. 安全调用转换为 'and' 逻辑
local nameList = request:getPathParameters():get("name")
local name = nameList and nameList:get(1) -- Lua 列表/数组索引从 1 开始
-- ?. 和 ?: (Elvis) 运算符的转换
local roleList = request:getQueryParameters():get("role")
local role = (roleList and roleList:get(1)) or "guest"
local responseText = "你好, " .. tostring(name) .. "! 你的角色是: " .. tostring(role)
_console:log("[服务器] 正在响应: " .. responseText)
-- 返回 respondText 返回的 Job
return call:getResponse():respondText(s, responseText, nil)
end)
end)
end)
_console:log("服务器已在 http://127.0.0.1:" .. tostring(port) .. " 启动")
-- 客户端测试
local httpClient = _httpClients:newClient(nil)
scope:delay(1000):_then(function(s, v)
return httpClient:get(s, "http://127.0.0.1:" .. tostring(port) .. "/users/M8Test?role=developer", nil, nil)
end):_then(function(s, response)
return response:getTextBody(s)
end):_then(function(s, body)
_console:log("[客户端] 收到响应:", body)
return s:resolve(nil)
end):onError(function(error)
if error ~= nil then
_console:error("[客户端] 测试失败:", error:stackTraceToString())
else
_console:error("[客户端] 测试失败,但未提供错误详情。")
end
end):onComplete(function()
_httpServers:stopServer(httpServer)
end)
<?php
/** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */
global $threads;
/** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */
global $coroutines;
/** @var m8test_java\com\m8test\script\core\api\http\HttpServers $httpServers */
global $httpServers;
/** @var m8test_java\com\m8test\script\core\api\console\Console $console */
global $console;
/** @var m8test_java\com\m8test\script\core\api\http\HttpClients $httpClients */
global $httpClients;
// 确保脚本在后台运行
$threads->getMain()->setBackground(true);
$scope = $coroutines->newScope(function ($context) {
$context->setDispatcher(function ($dispatchers) {
return $dispatchers->getScriptMain();
});
});
$port = 8081;
$httpServer = $httpServers->startServer($port, function ($config) {
$config->routing(function ($route) {
$route->get(javaString("/users/{name}"), function ($call, $s) {
global $console;
$request = $call->getRequest();
$name = $request->getPathParameters()[javaString("name")]->get(0);
// --- 修正点: 使用 isset 和三元运算符替代 '??' ---
$queryParams = $request->getQueryParameters();
$roleParam = isset($queryParams[javaString("role")]) ? $queryParams[javaString("role")]->get(0) : null;
$role = ($roleParam !== null) ? $roleParam : javaString("guest");
// --- 修正结束 ---
$responseText = javaString("你好, {$name}! 你的角色是: {$role}");
$console->log(javaString("[服务器] 正在响应: {$responseText}"));
// 返回 respondText 返回的 Job
return $call->getResponse()->respondText($s, $responseText, null);
});
});
});
$console->log(javaString("服务器已在 http://127.0.0.1:{$port} 启动"));
// 客户端测试
$httpClient = $httpClients->newClient(null);
$scope->delay(1000)->then(function ($s, $v) use ($httpClient, $port) {
return $httpClient->get($s, javaString("http://127.0.0.1:{$port}/users/M8Test?role=developer"), null, null);
})->then(function ($s, $response) {
return $response->getTextBody($s);
})->then(function ($s, $body) {
global $console;
$console->log(javaString("[客户端] 收到响应:"), $body);
return $s->resolve(null);
})->onError(function ($error) {
global $console;
$console->error(javaString("[客户端] 测试失败:"), $error);
})->onComplete(function () use ($httpServers, $httpServer) {
$httpServers->stopServer($httpServer);
});
# 导入所需的全局变量
from m8test_java.com.m8test.script.GlobalVariables import _console
from m8test_java.com.m8test.script.GlobalVariables import _coroutines
from m8test_java.com.m8test.script.GlobalVariables import _httpClients
from m8test_java.com.m8test.script.GlobalVariables import _httpServers
from m8test_java.com.m8test.script.GlobalVariables import _threads
# 确保脚本在后台运行
_threads.getMain().setBackground(True)
scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain()))
port = 8081
httpServer = _httpServers.startServer(port, lambda config:
config.routing(lambda route:
route.get("/users/{name}", lambda call, s: (
(request := call.getRequest()),
# 安全地获取路径和查询参数
(path_params := request.getPathParameters()),
(name_list := path_params.get("name")),
(name := name_list[0] if name_list else None),
(query_params := request.getQueryParameters()),
(role_list := query_params.get("role")),
(role_from_param := role_list[0] if role_list else None),
(role := role_from_param if role_from_param is not None else "guest"),
# 使用 f-string 进行字符串格式化
(responseText := f"你好, {name}! 你的角色是: {role}"),
_console.log(f"[服务器] 正在响应: {responseText}"),
# 返回 respondText 返回的 Job
call.getResponse().respondText(s, responseText, None)
)[-1])
)
)
_console.log(f"服务器已在 http://127.0.0.1:{port} 启动")
# 客户端测试
httpClient = _httpClients.newClient(None)
(scope.delay(1000).then(
lambda s, v: httpClient.get(s, f"http://127.0.0.1:{port}/users/M8Test?role=developer", None, None))
.then(lambda s, response: response.getTextBody(s))
.then(lambda s, body: (
_console.log("[客户端] 收到响应:", body),
s.resolve(None)
)[-1])
.onError(lambda error: _console.error("[客户端] 测试失败:", error))
.onComplete(lambda: _httpServers.stopServer(httpServer)))
# encoding: utf-8
# 确保脚本在后台运行
$threads.getMain.setBackground(true)
scope = $coroutines.newScope(nil)
port = 8081
httpServer = $httpServers.startServer(port) do |config|
config.routing do |route|
route.get("/users/{name}") do |call, s|
request = call.getRequest
# 修复: 替换 &. 操作符
path_params_name = request.getPathParameters["name"]
name = path_params_name ? path_params_name.get(0) : nil
query_params_role = request.getQueryParameters["role"]
role_val = query_params_role ? query_params_role.get(0) : nil
role = role_val || "guest"
responseText = "你好, #{name}! 你的角色是: #{role}"
$console.log("[服务器] 正在响应: #{responseText}")
# 返回 respondText 返回的 Job
call.getResponse.respondText(s, responseText, nil)
end
end
end
$console.log("服务器已在 http://127.0.0.1:#{port} 启动")
# 客户端测试
httpClient = $httpClients.newClient(nil)
scope.delay(1000).then do |s, v|
httpClient.get(s, "http://127.0.0.1:#{port}/users/M8Test?role=developer", nil, nil)
end.then do |s, response|
response.getTextBody(s)
end.then do |s, body|
$console.log("[客户端] 收到响应:", body)
s.resolve(nil)
end.onError do |error|
$console.error("[客户端] 测试失败:", error)
end.onComplete do
$httpServers.stopServer(httpServer)
end
处理 POST 请求体
import com.m8test.script.GlobalVariables.*
// 确保脚本在后台运行
_threads.getMain().setBackground(true)
val scope = _coroutines.newScope(null)
val port = 8082
val httpServer = _httpServers.startServer(port) {
routing {
// post 处理器: HttpServerCall.(CoroutineScope) -> Job
post("/submit") { s ->
// getRequest() 是 HttpServerCall (this) 的方法
// getJsonBody 返回 Deferred<T>
getRequest().getJsonBody(scope).then { s2, body ->
_console.log("[服务器] 收到的 JSON Body:", body)
val responseJson = """{"message": "数据已收到", "received": $body}"""
// respondText 返回 Job, 而 then 的 lambda 需要返回 Deferred
// 使用 toDeferred() 将 Job 转换为 Deferred<Unit>
getResponse().respondText(s2, responseJson) { it.getApplicationJson() }.toDeferred()
}.onError { error ->
// 移除显式类型注解,让编译器自动推断为 com.m8test.script.core.api.exception.Throwable
_console.error("[服务器] 处理请求体失败:", error)
// onError 的 lambda 返回 Unit,但在异步链中我们通常只是执行副作用
// 这里直接响应错误信息
getResponse().respondText(s, "错误的请求体", null)
}
// 整个链式调用的结果是 Deferred (实现了 Job),符合 post 处理器的返回值要求
}
}
}
_console.log("服务器已在 http://127.0.0.1:$port 启动")
// 客户端测试
val httpClient = _httpClients.newClient(null)
val postData = """{"user": "test", "id": 123}"""
scope.delay(1000).then { s, v ->
httpClient.postJson(s, "http://127.0.0.1:$port/submit", postData, null)
}.then { s, response ->
_console.log("[客户端] 响应状态码:", response.getStatusCode().getValue())
response.getTextBody(s)
}.then { s, body ->
_console.log("[客户端] 收到响应:", body)
s.resolve(null)
}.onError { error ->
_console.error("[客户端] 测试失败:", error)
}.onComplete {
_httpServers.stopServer(httpServer)
}
// 确保脚本在后台运行
$threads.getMain().setBackground(true)
def scope = $coroutines.newScope(null)
def port = 8082
def httpServer = $httpServers.startServer(port, { config ->
config.routing({ route ->
route.post("/submit", { call, s1 ->
// post 处理器需要返回一个 Job。
// 整个 Deferred 链就是一个 Job,所以我们返回它。
call.getRequest().getJsonBody(scope).then({ s, body ->
$console.log("[服务器] 收到的 JSON Body:", body)
def responseJson = '{"message": "数据已收到", "received": ' + body.toString() + '}'
call.getResponse().respondText(s, responseJson, { it.getApplicationJson() })
}).onError({ error ->
$console.error("[服务器] 处理请求体失败:", error)
call.getResponse().respondText(s1, "错误的请求体", null)
})
})
})
})
$console.log("服务器已在 http://127.0.0.1:${port} 启动")
// 客户端测试
def httpClient = $httpClients.newClient(null)
def postData = '{"user": "test", "id": 123}'
scope.delay(1000).then({ s, v ->
httpClient.postJson(s, "http://127.0.0.1:${port}/submit", postData, null)
}).then({ s, response ->
$console.log("[客户端] 响应状态码:", response.getStatusCode().value)
response.getTextBody(s)
}).then({ s, body ->
$console.log("[客户端] 收到响应:", body)
s.resolve(null)
}).onError({ error ->
$console.error("[客户端] 测试失败:", error)
}).onComplete({
$httpServers.stopServer(httpServer)
})
// 确保脚本在后台运行
$threads.getMain().setBackground(true);
const scope = $coroutines.newScope(null);
const port = 8082;
const httpServer = $httpServers.startServer(port, config => {
config.routing(route => {
route.post("/submit", (call, s1) => {
// post 处理器需要返回一个 Job。
// 整个 Deferred 链就是一个 Job,所以我们直接返回它。
return call.getRequest().getJsonBody(scope).then((s, body) => {
$console.log("[服务器] 收到的 JSON Body:", body);
const responseJson = '{"message": "数据已收到", "received": ' + body.toString() + '}';
return call.getResponse().respondText(s, responseJson, it => it.getApplicationJson());
}).onError(error => {
$console.error("[服务器] 处理请求体失败:", error);
return call.getResponse().respondText(s1, "错误的请求体", null);
});
});
});
});
$console.log("服务器已在 http://127.0.0.1:" + port + " 启动");
// 客户端测试
const httpClient = $httpClients.newClient(null);
const postData = '{"user": "test", "id": 123}';
scope.delay(1000).then((s, v) => {
return httpClient.postJson(s, "http://127.0.0.1:" + port + "/submit", postData, null);
}).then((s, response) => {
$console.log("[客户端] 响应状态码:", response.getStatusCode().getValue());
return response.getTextBody(s);
}).then((s, body) => {
$console.log("[客户端] 收到响应:", body);
return s.resolve(null);
}).onError(error => {
$console.error("[客户端] 测试失败:", error);
}).onComplete(() => {
$httpServers.stopServer(httpServer);
});
-- 确保脚本在后台运行
_threads:getMain():setBackground(true)
local scope = _coroutines:newScope(nil)
local port = 8082
local httpServer = _httpServers:startServer(port, function(config)
config:routing(function(route)
route:post("/submit", function(call, s1)
-- post 处理器需要返回一个 Job。
-- 整个 Deferred 链就是一个 Job,所以我们返回它。
return call:getRequest():getJsonBody(scope):_then(function(s, body)
_console:log("[服务器] 收到的 JSON Body:", body)
local responseJson = '{"message": "数据已收到", "received": ' .. tostring(body) .. '}'
return call:getResponse():respondText(s, responseJson, function(it) return it:getApplicationJson() end)
end):onError(function(error)
if error ~= nil then
_console:error("[服务器] 处理请求体失败:", error:stackTraceToString())
else
_console:error("[服务器] 处理请求体失败,但未提供错误详情。")
end
return call:getResponse():respondText(s1, "错误的请求体", nil)
end)
end)
end)
end)
_console:log("服务器已在 http://127.0.0.1:" .. tostring(port) .. " 启动")
-- 客户端测试
local httpClient = _httpClients:newClient(nil)
local postData = '{"user": "test", "id": 123}'
scope:delay(1000):_then(function(s, v)
return httpClient:postJson(s, "http://127.0.0.1:" .. tostring(port) .. "/submit", postData, nil)
end):_then(function(s, response)
_console:log("[客户端] 响应状态码:", response:getStatusCode().value)
return response:getTextBody(s)
end):_then(function(s, body)
_console:log("[客户端] 收到响应:", body)
return s:resolve(nil)
end):onError(function(error)
if error ~= nil then
_console:error("[客户端] 测试失败:", error:stackTraceToString())
else
_console:error("[客户端] 测试失败,但未提供错误详情。")
end
end):onComplete(function()
_httpServers:stopServer(httpServer)
end)
<?php
/** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */
global $threads;
/** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */
global $coroutines;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpServers $httpServers */
global $httpServers;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpClients $httpClients */
global $httpClients;
/** @var m8test_java\com\m8test\script\core\api\console\Console $console */
global $console;
// 确保脚本在后台运行
$threads->getMain()->setBackground(true);
$scope = $coroutines->newScope(function ($context) {
$context->setDispatcher(function ($dispatchers) {
return $dispatchers->getScriptMain();
});
});
$port = 8082;
$httpServer = $httpServers->startServer($port, function ($config) use ($scope) {
$config->routing(function ($route) use ($scope) {
$route->post(javaString("/submit"), function ($call, $s1) use ($scope) {
// post 处理器需要返回一个 Job。
// 整个 Deferred 链就是一个 Job,所以我们返回它。
return $call->getRequest()->getJsonBody($scope)->then(function ($s, $body) use ($call) {
global $console;
$console->log(javaString("[服务器] 收到的 JSON Body:"), $body);
$responseJson = javaString('{"message": "数据已收到", "received": ') . $body . '}';
return $call->getResponse()->respondText($s, $responseJson, function ($it) {
return $it->getApplicationJson();
});
})->onError(function ($error) use ($call, $s1) {
global $console;
$console->error(javaString("[服务器] 处理请求体失败:"), $error);
return $call->getResponse()->respondText($s1, javaString("错误的请求体"), null);
});
});
});
});
// 修正点: 修复字符串拼接
$console->log(javaString("服务器已在 http://127.0.0.1:" . $port . " 启动"));
// 客户端测试
$httpClient = $httpClients->newClient(null);
$postData = javaString('{"user": "test", "id": 123}');
$scope->delay(1000)->then(function ($s, $v) use ($httpClient, $port, $postData) {
return $httpClient->postJson($s, javaString("http://127.0.0.1:" . $port . "/submit"), $postData, null);
})->then(function ($s, $response) {
global $console;
$console->log(javaString("[客户端] 响应状态码:"), $response->getStatusCode()->value);
return $response->getTextBody($s);
})->then(function ($s, $body) {
global $console;
$console->log(javaString("[客户端] 收到响应:"), $body);
return $s->resolve(null);
})->onError(function ($error) {
global $console;
$console->error(javaString("[客户端] 测试失败:"), $error);
})->onComplete(function () use ($httpServer) {
global $httpServers;
$httpServers->stopServer($httpServer);
});
# 导入所需的全局变量
from m8test_java.com.m8test.script.GlobalVariables import _console
from m8test_java.com.m8test.script.GlobalVariables import _coroutines
from m8test_java.com.m8test.script.GlobalVariables import _httpClients
from m8test_java.com.m8test.script.GlobalVariables import _httpServers
from m8test_java.com.m8test.script.GlobalVariables import _threads
# 确保脚本在后台运行
_threads.getMain().setBackground(True)
scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain()))
port = 8082
httpServer = _httpServers.startServer(port, lambda config:
config.routing(lambda route:
# post 处理器需要返回一个 Job。
# 整个 Deferred 链就是一个 Job,所以我们返回它。
route.post("/submit", lambda call, s1:
call.getRequest().getJsonBody(scope).then(lambda s, body: (
_console.log("[服务器] 收到的 JSON Body:", body),
(responseJson := f'{{"message": "数据已收到", "received": {str(body)}}}'),
call.getResponse().respondText(s, responseJson, lambda it: it.getApplicationJson())
)[-1]).onError(lambda error: (
_console.error("[服务器] 处理请求体失败:", error),
call.getResponse().respondText(s1, "错误的请求体", None)
)[-1])
)
)
)
_console.log(f"服务器已在 http://127.0.0.1:{port} 启动")
# 客户端测试
httpClient = _httpClients.newClient(None)
postData = '{"user": "test", "id": 123}'
(scope.delay(1000).then(lambda s, v: httpClient.postJson(s, f"http://127.0.0.1:{port}/submit", postData, None))
.then(lambda s, response: (
_console.log("[客户端] 响应状态码:", response.getStatusCode().getValue()),
response.getTextBody(s)
)[-1])
.then(lambda s, body: (
_console.log("[客户端] 收到响应:", body),
s.resolve(None)
)[-1])
.onError(lambda error: _console.error("[客户端] 测试失败:", error))
.onComplete(lambda: _httpServers.stopServer(httpServer)))
# encoding: utf-8
# 确保脚本在后台运行
$threads.getMain.setBackground(true)
scope = $coroutines.newScope(nil)
port = 8082
httpServer = $httpServers.startServer(port) do |config|
config.routing do |route|
route.post("/submit") do |call, s1|
# post 处理器需要返回一个 Job。
# 整个 Deferred 链就是一个 Job,所以我们返回它。
call.getRequest.getJsonBody(scope).then do |s, body|
$console.log("[服务器] 收到的 JSON Body:", body)
responseJson = '{"message": "数据已收到", "received": ' + body.to_s + '}'
call.getResponse.respondText(s, responseJson) do |it|
it.getApplicationJson
end
end.onError do |error|
$console.error("[服务器] 处理请求体失败:", error)
call.getResponse.respondText(s1, "错误的请求体", nil)
end
end
end
end
$console.log("服务器已在 http://127.0.0.1:#{port} 启动")
# 客户端测试
httpClient = $httpClients.newClient(nil)
postData = '{"user": "test", "id": 123}'
scope.delay(1000).then do |s, v|
httpClient.postJson(s, "http://127.0.0.1:#{port}/submit", postData, nil)
end.then do |s, response|
$console.log("[客户端] 响应状态码:", response.getStatusCode.value)
response.getTextBody(s)
end.then do |s, body|
$console.log("[客户端] 收到响应:", body)
s.resolve(nil)
end.onError do |error|
$console.error("[客户端] 测试失败:", error)
end.onComplete do
$httpServers.stopServer(httpServer)
end
托管静态文件
您可以轻松地将一个文件夹的内容作为静态网站托管。
import com.m8test.script.GlobalVariables.*
// 确保脚本在后台运行
_threads.getMain().setBackground(true)
val scope = _coroutines.newScope(null)
// 1. 创建一个用于托管的文件夹和文件
val staticDir = _files.buildFile { setPath(_files.getFilesDir(), "www") }
staticDir.mkdirs()
val indexFile = _files.buildFile { setPath(staticDir.getAbsolutePath(), "index.html") }
indexFile.writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8")
val aboutFile = _files.buildFile { setPath(staticDir.getAbsolutePath(), "about.html") }
aboutFile.writeText("<h1>关于我们</h1>", "UTF-8")
_console.log("静态文件已创建于:", staticDir.getAbsolutePath())
val port = 8083
val httpServer = _httpServers.startServer(port) {
routing {
staticFiles("/", staticDir, "index.html", null)
}
}
_console.log("静态文件服务器已在 http://127.0.0.1:$port 启动")
// 客户端测试
val httpClient = _httpClients.newClient(null)
scope.delay(1000).then { s, v ->
val req1 = httpClient.get(s, "http://127.0.0.1:$port/", null, null)
val req2 = httpClient.get(s, "http://127.0.0.1:$port/about.html", null, null)
s.awaitAll(listOf(req1, req2))
}.then { s, responses ->
val body1 = responses[0].getTextBody(s)
val body2 = responses[1].getTextBody(s)
s.awaitAll(listOf(body1, body2))
}.then { s, bodies ->
_console.log("[客户端] / 响应:", bodies[0])
_console.log("[客户端] /about.html 响应:", bodies[1])
s.resolve(null)
}.onError { error ->
_console.error("[客户端] 测试失败:", error)
}.onComplete {
_httpServers.stopServer(httpServer)
staticDir.deleteRecursively()
_console.log("服务器已关闭,临时文件已清理。")
}
// 确保脚本在后台运行
$threads.getMain().setBackground(true)
def scope = $coroutines.newScope(null)
// 1. 创建一个用于托管的文件夹和文件
def staticDir = $files.buildFile({ it.setPath($files.getFilesDir(), "www") })
staticDir.mkdirs()
def indexFile = $files.buildFile({ it.setPath(staticDir.getAbsolutePath(), "index.html") })
indexFile.writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8")
def aboutFile = $files.buildFile({ it.setPath(staticDir.getAbsolutePath(), "about.html") })
aboutFile.writeText("<h1>关于我们</h1>", "UTF-8")
$console.log("静态文件已创建于:", staticDir.getAbsolutePath())
def port = 8083
def httpServer = $httpServers.startServer(port, { config ->
config.routing({ route ->
route.staticFiles("/", staticDir, "index.html", null)
})
})
$console.log("静态文件服务器已在 http://127.0.0.1:${port} 启动")
// 客户端测试
def httpClient = $httpClients.newClient(null)
scope.delay(1000).then({ s, v ->
def req1 = httpClient.get(s, "http://127.0.0.1:${port}/", null, null)
def req2 = httpClient.get(s, "http://127.0.0.1:${port}/about.html", null, null)
s.awaitAll([req1, req2])
}).then({ s, responses ->
def body1 = responses[0].getTextBody(s)
def body2 = responses[1].getTextBody(s)
s.awaitAll([body1, body2])
}).then({ s, bodies ->
$console.log("[客户端] / 响应:", bodies[0])
$console.log("[客户端] /about.html 响应:", bodies[1])
s.resolve(null)
}).onError({ error ->
$console.error("[客户端] 测试失败:", error)
}).onComplete({
$httpServers.stopServer(httpServer)
staticDir.deleteRecursively()
$console.log("服务器已关闭,临时文件已清理。")
})
// 确保脚本在后台运行
$threads.getMain().setBackground(true);
const scope = $coroutines.newScope(null);
// 1. 创建一个用于托管的文件夹和文件
const staticDir = $files.buildFile(it => { it.setPath($files.getFilesDir(), "www"); });
staticDir.mkdirs();
const indexFile = $files.buildFile(it => { it.setPath(staticDir.getAbsolutePath(), "index.html"); });
indexFile.writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8");
const aboutFile = $files.buildFile(it => { it.setPath(staticDir.getAbsolutePath(), "about.html"); });
aboutFile.writeText("<h1>关于我们</h1>", "UTF-8");
$console.log("静态文件已创建于:", staticDir.getAbsolutePath());
const port = 8083;
const httpServer = $httpServers.startServer(port, config => {
config.routing(route => {
route.staticFiles("/", staticDir, "index.html", null);
});
});
$console.log("静态文件服务器已在 http://127.0.0.1:" + port + " 启动");
// 客户端测试
const httpClient = $httpClients.newClient(null);
scope.delay(1000).then((s, v) => {
const req1 = httpClient.get(s, "http://127.0.0.1:" + port + "/", null, null);
const req2 = httpClient.get(s, "http://127.0.0.1:" + port + "/about.html", null, null);
return s.awaitAll([req1, req2]);
}).then((s, responses) => {
const body1 = responses[0].getTextBody(s);
const body2 = responses[1].getTextBody(s);
return s.awaitAll([body1, body2]);
}).then((s, bodies) => {
$console.log("[客户端] / 响应:", bodies[0]);
$console.log("[客户端] /about.html 响应:", bodies[1]);
return s.resolve(null);
}).onError(error => {
$console.error("[客户端] 测试失败:", error);
}).onComplete(() => {
$httpServers.stopServer(httpServer);
staticDir.deleteRecursively();
$console.log("服务器已关闭,临时文件已清理。");
});
-- 确保脚本在后台运行
_threads:getMain():setBackground(true)
local scope = _coroutines:newScope(nil)
-- 1. 创建一个用于托管的文件夹和文件
local staticDir = _files:buildFile(function(it) it:setPath(_files:getFilesDir(), "www") end)
staticDir:mkdirs()
local indexFile = _files:buildFile(function(it) it:setPath(staticDir:getAbsolutePath(), "index.html") end)
indexFile:writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8")
local aboutFile = _files:buildFile(function(it) it:setPath(staticDir:getAbsolutePath(), "about.html") end)
aboutFile:writeText("<h1>关于我们</h1>", "UTF-8")
_console:log("静态文件已创建于:", staticDir:getAbsolutePath())
local port = 8083
local httpServer = _httpServers:startServer(port, function(config)
config:routing(function(route)
route:staticFiles("/", staticDir, "index.html", nil)
end)
end)
_console:log("静态文件服务器已在 http://127.0.0.1:" .. tostring(port) .. " 启动")
-- 客户端测试
local httpClient = _httpClients:newClient(nil)
scope:delay(1000):_then(function(s, v)
local req1 = httpClient:get(s, "http://127.0.0.1:" .. tostring(port) .. "/", nil, nil)
local req2 = httpClient:get(s, "http://127.0.0.1:" .. tostring(port) .. "/about.html", nil, nil)
-- 修正1:awaitAll 需要一个 Java List, 而不是 Lua table。
return s:awaitAll(_iterables:listOf(req1, req2))
end):_then(function(s, responses)
-- 修正2:Java List 是 0-based 索引。
local body1 = responses:get(0):getTextBody(s)
local body2 = responses:get(1):getTextBody(s)
-- 修正1:同样,这里也需要一个 Java List
return s:awaitAll(_iterables:listOf(body1, body2))
end):_then(function(s, bodies)
-- 修正2:Java List 是 0-based 索引。
_console:log("[客户端] / 响应:", bodies:get(0))
_console:log("[客户端] /about.html 响应:", bodies:get(1))
return s:resolve(nil)
end):onError(function(error)
if error ~= nil then
_console:error("[客户端] 测试失败:", error:stackTraceToString())
else
_console:error("[客户端] 测试失败,但未提供错误详情。")
end
end):onComplete(function()
_httpServers:stopServer(httpServer)
staticDir:deleteRecursively()
_console:log("服务器已关闭,临时文件已清理。")
end)
<?php
/** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */
global $threads;
/** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */
global $coroutines;
/** @var m8test_java\com\m8test\script\core\api\file\Files $files */
global $files;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpServers $httpServers */
global $httpServers;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpClients $httpClients */
global $httpClients;
/** @var m8test_java\com\m8test\script\core\api\console\Console $console */
global $console;
/** @var m8test_java\com\m8test\script\core\api\collections\Iterables $iterables */
global $iterables;
// 确保脚本在后台运行
$threads->getMain()->setBackground(true);
$scope = $coroutines->newScope(function ($context) {
$context->setDispatcher(function ($dispatchers) {
return $dispatchers->getScriptMain();
});
});
// 1. 创建一个用于托管的文件夹和文件
$staticDir = $files->buildFile(function ($it) use ($files) {
$it->setPath($files->getFilesDir(), javaString("www"));
});
$staticDir->mkdirs();
$indexFile = $files->buildFile(function ($it) use ($staticDir) {
$it->setPath($staticDir->getAbsolutePath(), javaString("index.html"));
});
$indexFile->writeText(javaString("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>"), javaString("UTF-8"));
$aboutFile = $files->buildFile(function ($it) use ($staticDir) {
$it->setPath($staticDir->getAbsolutePath(), javaString("about.html"));
});
$aboutFile->writeText(javaString("<h1>关于我们</h1>"), javaString("UTF-8"));
$console->log(javaString("静态文件已创建于:"), $staticDir->getAbsolutePath());
$port = 8083;
$httpServer = $httpServers->startServer($port, function ($config) use ($staticDir) {
$config->routing(function ($route) use ($staticDir) {
$route->staticFiles(javaString("/"), $staticDir, javaString("index.html"), null);
});
});
// 修正点: 修复字符串拼接
$console->log(javaString("静态文件服务器已在 http://127.0.0.1:" . $port . " 启动"));
// 客户端测试
$httpClient = $httpClients->newClient(null);
$scope->delay(1000)->then(function ($s, $v) use ($httpClient, $port) {
global $iterables;
$req1 = $httpClient->get($s, javaString("http://127.0.0.1:" . $port . "/"), null, null);
$req2 = $httpClient->get($s, javaString("http://127.0.0.1:" . $port . "/about.html"), null, null);
return $s->awaitAll($iterables->listOf($req1, $req2));
})->then(function ($s, $responses) {
global $iterables;
$body1 = $responses->get(0)->getTextBody($s);
$body2 = $responses->get(1)->getTextBody($s);
return $s->awaitAll($iterables->listOf($body1, $body2));
})->then(function ($s, $bodies) {
global $console;
$console->log(javaString("[客户端] / 响应:"), $bodies->get(0));
$console->log(javaString("[客户端] /about.html 响应:"), $bodies->get(1));
return $s->resolve(null);
})->onError(function ($error) {
global $console;
$console->error(javaString("[客户端] 测试失败:"), $error);
})->onComplete(function () use ($httpServer, $staticDir) {
global $console, $httpServers;
$httpServers->stopServer($httpServer);
$staticDir->deleteRecursively();
$console->log(javaString("服务器已关闭,临时文件已清理。"));
});
# 导入所需的全局变量
from m8test_java.com.m8test.script.GlobalVariables import _console
from m8test_java.com.m8test.script.GlobalVariables import _coroutines
from m8test_java.com.m8test.script.GlobalVariables import _files
from m8test_java.com.m8test.script.GlobalVariables import _httpClients
from m8test_java.com.m8test.script.GlobalVariables import _httpServers
from m8test_java.com.m8test.script.GlobalVariables import _threads
# 确保脚本在后台运行
_threads.getMain().setBackground(True)
scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain()))
# 1. 创建一个用于托管的文件夹和文件
staticDir = _files.buildFile(lambda it: it.setPath(_files.getFilesDir(), "www"))
staticDir.mkdirs()
indexFile = _files.buildFile(lambda it: it.setPath(staticDir.getAbsolutePath(), "index.html"))
indexFile.writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8")
aboutFile = _files.buildFile(lambda it: it.setPath(staticDir.getAbsolutePath(), "about.html"))
aboutFile.writeText("<h1>关于我们</h1>", "UTF-8")
_console.log("静态文件已创建于:", staticDir.getAbsolutePath())
port = 8083
httpServer = _httpServers.startServer(port, lambda config:
config.routing(lambda route: route.staticFiles("/", staticDir, "index.html", None))
)
_console.log(f"静态文件服务器已在 http://127.0.0.1:{port} 启动")
# 客户端测试
httpClient = _httpClients.newClient(None)
scope.delay(1000).then(lambda s, v: (
(req1 := httpClient.get(s, f"http://127.0.0.1:{port}/", None, None)),
(req2 := httpClient.get(s, f"http://127.0.0.1:{port}/about.html", None, None)),
s.awaitAll([req1, req2])
)[-1]).then(lambda s, responses: (
(body1 := responses[0].getTextBody(s)),
(body2 := responses[1].getTextBody(s)),
s.awaitAll([body1, body2])
)[-1]).then(lambda s, bodies: (
_console.log("[客户端] / 响应:", bodies[0]),
_console.log("[客户端] /about.html 响应:", bodies[1]),
s.resolve(None)
)[-1]).onError(lambda error:
_console.error("[客户端] 测试失败:", error)
).onComplete(lambda: (
_httpServers.stopServer(httpServer),
staticDir.deleteRecursively(),
_console.log("服务器已关闭,临时文件已清理。")
))
# encoding: utf-8
# 确保脚本在后台运行
$threads.getMain.setBackground(true)
scope = $coroutines.newScope(nil)
# 1. 创建一个用于托管的文件夹和文件
staticDir = $files.buildFile do |it|
it.setPath($files.getFilesDir, "www")
end
staticDir.mkdirs
indexFile = $files.buildFile do |it|
it.setPath(staticDir.getAbsolutePath, "index.html")
end
indexFile.writeText("<h1>欢迎来到我的静态网站</h1><p>这是一个由 M8Test 脚本托管的页面。</p>", "UTF-8")
aboutFile = $files.buildFile do |it|
it.setPath(staticDir.getAbsolutePath, "about.html")
end
aboutFile.writeText("<h1>关于我们</h1>", "UTF-8")
$console.log("静态文件已创建于:", staticDir.getAbsolutePath)
port = 8083
httpServer = $httpServers.startServer(port) do |config|
config.routing do |route|
route.staticFiles("/", staticDir, "index.html", nil)
end
end
$console.log("静态文件服务器已在 http://127.0.0.1:#{port} 启动")
# 客户端测试
httpClient = $httpClients.newClient(nil)
scope.delay(1000).then do |s, v|
req1 = httpClient.get(s, "http://127.0.0.1:#{port}/", nil, nil)
req2 = httpClient.get(s, "http://127.0.0.1:#{port}/about.html", nil, nil)
s.awaitAll([req1, req2])
end.then do |s, responses|
body1 = responses[0].getTextBody(s)
body2 = responses[1].getTextBody(s)
s.awaitAll([body1, body2])
end.then do |s, bodies|
$console.log("[客户端] / 响应:", bodies[0])
$console.log("[客户端] /about.html 响应:", bodies[1])
s.resolve(nil)
end.onError do |error|
$console.error("[客户端] 测试失败:", error)
end.onComplete do
$httpServers.stopServer(httpServer)
staticDir.deleteRecursively
$console.log("服务器已关闭,临时文件已清理。")
end
搭建 WebSocket 服务器
创建一个 WebSocket 端点来处理实时双向通信。
import com.m8test.script.GlobalVariables.*
// 确保脚本在后台运行
_threads.getMain().setBackground(true)
val scope = _coroutines.newScope(null)
val port = 8084
val httpServer = _httpServers.startServer(port) {
routing {
// webSocket 处理器: WebSocketSession.(CoroutineScope) -> Job
webSocket("/echo") { s1 ->
_console.log("[服务器] 一个新的 WebSocket 客户端已连接!")
// this 是 WebSocketSession
setOnText { s, text ->
_console.log("[服务器] 收到消息:", text)
val reply = "服务器回显: $text"
// sendText 返回 Job,满足 setOnText 要求
sendText(s, reply)
}
setOnClose { s, reason ->
_console.warn("[服务器] 一个客户端已断开连接:", reason?.getMessage())
// resolve 返回 Deferred (也是 Job),满足 setOnClose 要求
s.resolve(null)
}
// 处理器本身返回一个 Job
s1.resolve(null)
}
}
}
_console.log("WebSocket 服务器已在 ws://127.0.0.1:$port/echo 启动")
// 客户端测试
val httpClient = _httpClients.newClient(null)
scope.delay(1000).then { s, v ->
// 这里的 then 期望返回 Deferred
// httpClient.webSocket 返回 Job,需要转换为 Deferred
httpClient.webSocket(s, "ws://127.0.0.1:$port/echo", null) {
// this 是 WebSocketSession
setOnOpen { ss ->
_console.log("[客户端] WebSocket 已连接,发送消息...")
sendText(ss, "Hello Echo Server!")
}
setOnText { ss, text ->
_console.log("[客户端] 收到回显:", text)
// 收到回显后关闭连接
// setOnText 需要返回 Job
scope.delay(1000).then { sss, _ ->
// close 返回 Job,但 then 需要 Deferred,所以要转换
close(sss, 1000, "测试完成").toDeferred()
}
}
setOnClose { ss, reason ->
_console.log("[客户端] 连接已关闭。")
ss.resolve(null)
}
}.toDeferred() // 将 webSocket 返回的 Job 转为 Deferred
}.then { s, v ->
_console.log("客户端 WebSocket 会话结束。")
s.resolve(null)
}.onError { error ->
_console.error("[客户端] WebSocket 测试失败:", error)
}.onComplete {
_console.log("测试完成,关闭服务器。")
_httpServers.stopServer(httpServer)
}
// 确保脚本在后台运行
$threads.getMain().setBackground(true)
def scope = $coroutines.newScope(null)
def port = 8084
def httpServer = $httpServers.startServer(port, { config ->
config.routing({ route ->
// webSocket 处理器需要返回一个 Job
route.webSocket("/echo", { session, s1 ->
$console.log("[服务器] 一个新的 WebSocket 客户端已连接!")
session.setOnText({ s, text ->
$console.log("[服务器] 收到消息:", text)
def reply = "服务器回显: ${text}"
// sendText 返回 Job,满足监听器要求
session.sendText(s, reply)
})
session.setOnClose({ s, reason ->
$console.warn("[服务器] 一个客户端已断开连接:", reason?.getMessage())
s.resolve(null) // 返回一个完成的 Job
})
// 处理器本身返回一个完成的 Job,表示设置已完成
s1.resolve(null)
})
})
})
$console.log("WebSocket 服务器已在 ws://127.0.0.1:${port}/echo 启动")
// 客户端测试
def httpClient = $httpClients.newClient(null)
scope.delay(1000).then({ s, v ->
httpClient.webSocket(s, "ws://127.0.0.1:${port}/echo", null, { session ->
session.setOnOpen({ ss ->
$console.log("[客户端] WebSocket 已连接,发送消息...")
session.sendText(ss, "Hello Echo Server!")
})
session.setOnText({ ss, text ->
$console.log("[客户端] 收到回显:", text)
// 收到回显后关闭连接
session.close(ss, 1000, "测试完成")
})
session.setOnClose({ ss, reason ->
$console.log("[客户端] 连接已关闭。")
ss.resolve(null)
})
})
}).then({ s, v ->
$console.log("客户端 WebSocket 会话结束。")
s.resolve(null)
}).onError({ error ->
$console.error("[客户端] WebSocket 测试失败:", error)
}).onComplete({
$console.log("测试完成,关闭服务器。")
$httpServers.stopServer(httpServer)
})
// 确保脚本在后台运行
$threads.getMain().setBackground(true);
const scope = $coroutines.newScope(null);
const port = 8084;
const httpServer = $httpServers.startServer(port, config => {
config.routing(route => {
// webSocket 处理器需要返回一个 Job
route.webSocket("/echo", session => {
$console.log("[服务器] 一个新的 WebSocket 客户端已连接!");
session.setOnText((s, text) => {
$console.log("[服务器] 收到消息:", text);
const reply = "服务器回显: " + text;
// sendText 返回 Job,满足监听器要求,必须返回
return session.sendText(s, reply);
});
session.setOnClose((s, reason) => {
$console.warn("[服务器] 一个客户端已断开连接:", reason?.getMessage());
// 返回一个完成的 Job
return s.resolve(null);
});
// 处理器本身返回一个完成的 Job,表示设置已完成
return scope.resolve(null);
});
});
});
$console.log("WebSocket 服务器已在 ws://127.0.0.1:" + port + "/echo 启动");
// 客户端测试
const httpClient = $httpClients.newClient(null);
scope.delay(1000).then((s, v) => {
// httpClient.webSocket 返回一个 Job
httpClient.webSocket(s, "ws://127.0.0.1:" + port + "/echo", null, (session, s1) => {
session.setOnOpen(ss => {
$console.log("[客户端] WebSocket 已连接,发送消息...");
return session.sendText(ss, "Hello Echo Server!");
});
session.setOnText((ss, text) => {
$console.log("[客户端] 收到回显:", text);
// 收到回显后关闭连接,close 返回 Job
return session.close(ss, 1000, "测试完成");
});
session.setOnClose((ss, reason) => {
$console.log("[客户端] 连接已关闭。");
return ss.resolve(null);
});
});
return s.resolve(null);
}).then((s, v) => {
$console.log("客户端 WebSocket 会话结束。");
return s.resolve(null);
}).onError(error => {
$console.error("[客户端] WebSocket 测试失败:", error);
}).onComplete(() => {
$console.log("测试完成,关闭服务器。");
$httpServers.stopServer(httpServer);
});
-- 确保脚本在后台运行
_threads:getMain():setBackground(true)
local scope = _coroutines:newScope(nil)
local port = 8084
local httpServer = _httpServers:startServer(port, function(config)
config:routing(function(route)
-- webSocket 处理器需要返回一个 Job
route:webSocket("/echo", function(session, s1)
_console:log("[服务器] 一个新的 WebSocket 客户端已连接!")
session:setOnText(function(s, text)
_console:log("[服务器] 收到消息:", text)
local reply = "服务器回显: " .. text
-- sendText 返回 Job,满足监听器要求
return session:sendText(s, reply)
end)
session:setOnClose(function(s, reason)
_console:warn("[服务器] 一个客户端已断开连接:", reason and reason:getMessage())
return s:resolve(nil) -- 返回一个完成的 Job
end)
-- 处理器本身返回一个完成的 Job,表示设置已完成
return s1:resolve(nil)
end)
end)
end)
_console:log("WebSocket 服务器已在 ws://127.0.0.1:" .. tostring(port) .. "/echo 启动")
-- 客户端测试
local httpClient = _httpClients:newClient(nil)
scope:delay(1000):_then(function(s, v)
return httpClient:webSocket(s, "ws://127.0.0.1:" .. tostring(port) .. "/echo", nil, function(session)
session:setOnOpen(function(ss)
_console:log("[客户端] WebSocket 已连接,发送消息...")
return session:sendText(ss, "Hello Echo Server!")
end)
session:setOnText(function(ss, text)
_console:log("[客户端] 收到回显:", text)
-- 收到回显后关闭连接
return session:close(ss, 1000, "测试完成")
end)
session:setOnClose(function(ss, reason)
_console:log("[客户端] 连接已关闭。")
return ss:resolve(nil)
end)
end)
end):_then(function(s, v)
_console:log("客户端 WebSocket 会话结束。")
return s:resolve(nil)
end):onError(function(error)
if error ~= nil then
_console:error("[客户端] WebSocket 测试失败:", error:stackTraceToString())
else
_console:error("[客户端] WebSocket 测试失败,但未提供错误详情。")
end
end):onComplete(function()
_console:log("测试完成,关闭服务器。")
_httpServers:stopServer(httpServer)
end)
<?php
/** @var m8test_java\com\m8test\script\core\api\thread\Threads $threads */
global $threads;
/** @var m8test_java\com\m8test\script\core\api\coroutines\Coroutines $coroutines */
global $coroutines;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpServers $httpServers */
global $httpServers;
/** @var m8test_java\com\m8test\script\core\api\net\http\HttpClients $httpClients */
global $httpClients;
/** @var m8test_java\com\m8test\script\core\api\console\Console $console */
global $console;
// 确保脚本在后台运行
$threads->getMain()->setBackground(true);
$scope = $coroutines->newScope(function ($context) {
$context->setDispatcher(function ($dispatchers) {
return $dispatchers->getScriptMain();
});
});
$port = 8084;
$httpServer = $httpServers->startServer($port, function ($config) {
$config->routing(function ($route) {
// webSocket 处理器需要返回一个 Job
$route->webSocket(javaString("/echo"), function ($session, $s1) {
global $console;
$console->log(javaString("[服务器] 一个新的 WebSocket 客户端已连接!"));
$session->setOnText(function ($s, $text) use ($session) {
global $console;
$console->log(javaString("[服务器] 收到消息:"), $text);
$reply = javaString("服务器回显: ${text}");
// sendText 返回 Job,满足监听器要求
// [修正] 必须返回 Job 对象
return $session->sendText($s, $reply);
});
$session->setOnClose(function ($s, $reason) {
global $console;
$console->warn(javaString("[服务器] 一个客户端已断开连接:"), $reason ? $reason->getMessage() : null);
// [修正] 必须返回 Job 对象
return $s->resolve(null);
});
// 处理器本身返回一个完成的 Job,表示设置已完成
return $s1->resolve(null);
});
});
});
$console->log(javaString("WebSocket 服务器已在 ws://127.0.0.1:${port}/echo 启动"));
// 客户端测试
$httpClient = $httpClients->newClient(null);
$scope->delay(1000)->then(function ($s, $v) use ($httpClient, $port) {
return $httpClient->webSocket($s, javaString("ws://127.0.0.1:${port}/echo"), null, function ($session) {
$session->setOnOpen(function ($ss) use ($session) {
global $console;
$console->log(javaString("[客户端] WebSocket 已连接,发送消息..."));
// [修正] 必须返回 Job 对象
return $session->sendText($ss, javaString("Hello Echo Server!"));
});
$session->setOnText(function ($ss, $text) use ($session) {
global $console;
$console->log(javaString("[客户端] 收到回显:"), $text);
// 收到回显后关闭连接
// [修正] 必须返回 Job 对象
return $session->close($ss, 1000, javaString("测试完成"));
});
$session->setOnClose(function ($ss, $reason) {
global $console;
$console->log(javaString("[客户端] 连接已关闭。"));
// [修正] 必须返回 Job 对象
return $ss->resolve(null);
});
});
})->then(function ($s, $v) {
global $console;
$console->log(javaString("客户端 WebSocket 会话结束。"));
return $s->resolve(null);
})->onError(function ($error) {
global $console;
$console->error(javaString("[客户端] WebSocket 测试失败:"), $error);
})->onComplete(function () use ($httpServer) {
global $console, $httpServers;
$console->log(javaString("测试完成,关闭服务器。"));
$httpServers->stopServer($httpServer);
});
# 导入所需的全局变量
from m8test_java.com.m8test.script.GlobalVariables import _console
from m8test_java.com.m8test.script.GlobalVariables import _coroutines
from m8test_java.com.m8test.script.GlobalVariables import _httpClients
from m8test_java.com.m8test.script.GlobalVariables import _httpServers
from m8test_java.com.m8test.script.GlobalVariables import _threads
# 确保脚本在后台运行
_threads.getMain().setBackground(True)
scope = _coroutines.newScope(lambda it: it.setDispatcher(lambda d: d.getScriptMain()))
port = 8084
httpServer = _httpServers.startServer(port, lambda config:
config.routing(lambda route:
# webSocket 处理器需要返回一个 Job
route.webSocket("/echo", lambda session, s1: (
_console.log("[服务器] 一个新的 WebSocket 客户端已连接!"),
session.setOnText(lambda s, text: (
_console.log("[服务器] 收到消息:", text),
(reply := f"服务器回显: {text}"),
# sendText 返回 Job,满足监听器要求
session.sendText(s, reply)
)[-1]),
session.setOnClose(lambda s, reason: (
# reason 可能为 null,所以进行检查
_console.warn("[服务器] 一个客户端已断开连接:",
reason.getMessage() if reason else "No reason given"),
s.resolve(None) # 返回一个完成的 Job
)[-1]),
# 处理器本身返回一个完成的 Job,表示设置已完成
s1.resolve(None)
)[-1])
)
)
_console.log(f"WebSocket 服务器已在 ws://127.0.0.1:{port}/echo 启动")
# 客户端测试
httpClient = _httpClients.newClient(None)
(scope.delay(1000)
.then(lambda s, v: httpClient.webSocket(s, f"ws://127.0.0.1:{port}/echo", None, lambda session: (
session.setOnOpen(lambda ss: (
_console.log("[客户端] WebSocket 已连接,发送消息..."),
session.sendText(ss, "Hello Echo Server!")
)[-1]),
session.setOnText(lambda ss, text: (
_console.log("[客户端] 收到回显:", text),
# 收到回显后关闭连接
session.close(ss, 1000, "测试完成")
)[-1]),
session.setOnClose(lambda ss, reason: (
_console.log("[客户端] 连接已关闭。"),
ss.resolve(None)
)[-1])
)))
.then(lambda s, v: (
_console.log("客户端 WebSocket 会话结束。"),
s.resolve(None)
)[-1])
.onError(lambda error: _console.error("[客户端] WebSocket 测试失败:", error))
.onComplete(lambda: (
_console.log("测试完成,关闭服务器。"),
_httpServers.stopServer(httpServer)
)))
# encoding: utf-8
# 确保脚本在后台运行
$threads.getMain.setBackground(true)
scope = $coroutines.newScope(nil)
port = 8084
httpServer = $httpServers.startServer(port) do |config|
config.routing do |route|
# webSocket 处理器需要返回一个 Job
route.webSocket("/echo") do |session, s1|
$console.log("[服务器] 一个新的 WebSocket 客户端已连接!")
session.setOnText do |s, text|
$console.log("[服务器] 收到消息:", text)
reply = "服务器回显: #{text}"
# sendText 返回 Job,满足监听器要求
session.sendText(s, reply)
end
session.setOnClose do |s, reason|
# 修复: 替换 &. 操作符
msg = reason ? reason.getMessage : nil
$console.warn("[服务器] 一个客户端已断开连接:", msg)
s.resolve(nil) # 返回一个完成的 Job
end
# 处理器本身返回一个完成的 Job,表示设置已完成
s1.resolve(nil)
end
end
end
$console.log("WebSocket 服务器已在 ws://127.0.0.1:#{port}/echo 启动")
# 客户端测试
httpClient = $httpClients.newClient(nil)
scope.delay(1000).then do |s, v|
httpClient.webSocket(s, "ws://127.0.0.1:#{port}/echo", nil) do |session|
session.setOnOpen do |ss|
$console.log("[客户端] WebSocket 已连接,发送消息...")
session.sendText(ss, "Hello Echo Server!")
end
session.setOnText do |ss, text|
$console.log("[客户端] 收到回显:", text)
# 收到回显后关闭连接
session.close(ss, 1000, "测试完成")
end
session.setOnClose do |ss, reason|
$console.log("[客户端] 连接已关闭。")
ss.resolve(nil)
end
end
end.then do |s, v|
$console.log("客户端 WebSocket 会话结束。")
s.resolve(nil)
end.onError do |error|
$console.error("[客户端] WebSocket 测试失败:", error)
end.onComplete do
$console.log("测试完成,关闭服务器。")
$httpServers.stopServer(httpServer)
end
09 December 2025