@@ -62,22 +62,24 @@ extern "js" fn HttpResponseInternal::write_head(
6262) -> Unit = "(s, statusCode, headers) => s.writeHead(statusCode, headers)"
6363
6464///|
65- pub extern "js" fn create_server (
65+ type NodeServerInternal
66+
67+ ///|
68+ #module ("node:http" )
69+ extern "js" fn create_server (
6670 handler : (HttpRequestInternal , HttpResponseInternal , () -> Unit ) -> Unit ,
71+ ) -> NodeServerInternal = "createServer"
72+
73+ ///|
74+ pub extern "js" fn start_server (
75+ server : NodeServerInternal ,
6776 port : Int ,
77+ accept_key : (String ) -> String ,
6878) -> Unit =
69- #| (handler, port) => {
70- #| const server = require('node:http').createServer(handler);
79+ #| (server, port, acceptKey) => {
7180 #| function start(server, port) {
72- #| const http = require('node:http');
73- #| const crypto = require('node:crypto');
74- #| const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
7581 #| const clientsById = new Map();
7682 #|
77- #| function acceptKey(key) {
78- #| return crypto.createHash('sha1').update(String(key) + GUID).digest('base64');
79- #| }
80- #|
8183 #| // 供 FFI 调用的发送函数
8284 #| function sendText(socket, str) {
8385 #| const payload = Buffer.from(String(str), 'utf8');
@@ -254,77 +256,75 @@ pub extern "js" fn create_server(
254256
255257///|
256258pub fn serve_ffi (mocket : Mocket , port ~ : Int ) -> Unit {
257- create_server (
258- fn (req , res , _ ) {
259- // 优化:简化 headers 转换逻辑
260- let string_headers : Map [StringView , StringView ] = {}
261- guard (try ? req .headers ().to_value ().to_json ()) is Ok (Object (headers )) else {
262- res .write_head (400 , @js .Object ::new ().to_value ())
263- res .end (@js .Value ::cast_from ("Invalid headers" ))
264- return
265- }
259+ let server = create_server (fn (req , res , _ ) {
260+ // 优化:简化 headers 转换逻辑
261+ let string_headers : Map [StringView , StringView ] = {}
262+ guard (try ? req .headers ().to_value ().to_json ()) is Ok (Object (headers )) else {
263+ res .write_head (400 , @js .Object ::new ().to_value ())
264+ res .end (@js .Value ::cast_from ("Invalid headers" ))
265+ return
266+ }
266267
267- // 批量转换 headers,减少单个处理的开销
268- headers .each (fn (key , value ) {
269- if value is String (v ) {
270- string_headers .set (key , v .to_string_view ())
271- }
272- })
273- let (params , handler ) = match
274- mocket .find_route (req .req_method (), req .url ()) {
275- Some ((h , p )) => (p , h )
276- _ => ({}, handle_not_found )
268+ // 批量转换 headers,减少单个处理的开销
269+ headers .each (fn (key , value ) {
270+ if value is String (v ) {
271+ string_headers .set (key , v .to_string_view ())
277272 }
278- let event = {
279- req : {
280- http_method : req .req_method (),
281- url : req .url (),
282- headers : string_headers ,
283- raw_body : "" ,
284- },
285- res : HttpResponse ::new (OK ),
286- params ,
273+ })
274+ let (params , handler ) = match
275+ mocket .find_route (req .req_method (), req .url ()) {
276+ Some ((h , p )) => (p , h )
277+ _ => ({}, handle_not_found )
278+ }
279+ let event = {
280+ req : {
281+ http_method : req .req_method (),
282+ url : req .url (),
283+ headers : string_headers ,
284+ raw_body : "" ,
285+ },
286+ res : HttpResponse ::new (OK ),
287+ params ,
288+ }
289+ async_run (() => {
290+ // 如果是 post,先等待 data 事件
291+ if event .req.http_method == "POST" {
292+ let buffer = @buffer .new ()
293+ (try ? suspend (fn (res , _ ) {
294+ req .on ("data" , data => buffer .write_string (data .to_string ()))
295+ req .on ("end" , _ => res (buffer .to_string ()))
296+ }))
297+ |> ignore
298+ event .req.raw_body = buffer .to_bytes ()
287299 }
288- async_run (() => {
289- // 如果是 post,先等待 data 事件
290- if event .req.http_method == "POST" {
291- let buffer = @buffer .new ()
292- (try ? suspend (fn (res , _ ) {
293- req .on ("data" , data => buffer .write_string (data .to_string ()))
294- req .on ("end" , _ => res (buffer .to_string ()))
295- }))
296- |> ignore
297- event .req.raw_body = buffer .to_bytes ()
298- }
299-
300- // 执行中间件链和处理器
301- let responder = execute_middlewares (mocket .middlewares, event , handler )
302- // let boundary = "----------------moonbit-" + port.to_string()
303- responder .options (event .res)
304- res .write_head (
305- event .res.status_code.to_int (),
306- {
307- let headers_obj = (try ? @js .Value ::from_json (
308- event .res.headers.to_json (),
309- )).or (@js .Object ::new ().to_value ())
310- if not (event .res.cookies.is_empty ()) {
311- let cookies = event .res.cookies
312- .values ()
313- .map (fn (c ) { c .to_string () })
314- .to_array ()
315- set_js_property (headers_obj , "Set-Cookie" , array_to_js (cookies ))
316- }
317- headers_obj
318- },
319- )
320- let buf = @buffer .new ()
321- responder .output (buf )
322- event .res.raw_body = buf .to_bytes ()
323- res .end (@js .Value ::cast_from (event .res.raw_body))
324- })
325- },
326- port ,
327- )
300+
301+ // 执行中间件链和处理器
302+ let responder = execute_middlewares (mocket .middlewares, event , handler )
303+ // let boundary = "----------------moonbit-" + port.to_string()
304+ responder .options (event .res)
305+ res .write_head (
306+ event .res.status_code.to_int (),
307+ {
308+ let headers_obj = (try ? @js .Value ::from_json (
309+ event .res.headers.to_json (),
310+ )).or (@js .Object ::new ().to_value ())
311+ if not (event .res.cookies.is_empty ()) {
312+ let cookies = event .res.cookies
313+ .values ()
314+ .map (fn (c ) { c .to_string () })
315+ .to_array ()
316+ set_js_property (headers_obj , "Set-Cookie" , array_to_js (cookies ))
317+ }
318+ headers_obj
319+ },
320+ )
321+ let buf = @buffer .new ()
322+ responder .output (buf )
323+ event .res.raw_body = buf .to_bytes ()
324+ res .end (@js .Value ::cast_from (event .res.raw_body))
325+ })
326+ })
327+ start_server (server , port , websocket_accept_key )
328328 register_ws_handler (mocket , port )
329329 __ws_emit_js_export (__ws_emit_js_port )
330330 __ws_state_js_export (
@@ -333,6 +333,16 @@ pub fn serve_ffi(mocket : Mocket, port~ : Int) -> Unit {
333333 __get_port_by_connection_js_export (__get_port_by_connection_js )
334334}
335335
336+ ///|
337+ fn websocket_accept_key (key : String ) -> String {
338+ let guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
339+ (key + guid )
340+ |> @encoding/utf8 .encode
341+ |> @crypto .sha1
342+ |> Bytes ::from_array
343+ |> @base64 .encode
344+ }
345+
336346///|
337347/// 全局 handler 映射:port -> WebSocketHandler
338348let ws_handler_map : Map [Int , WebSocketHandler ] = Map ::new ()
0 commit comments