///|
/// Error type for invalid native server configuration values.
pub suberror NativeServeError {
InvalidMaxConnections(Int)
InvalidMaxRequestBodyBytes(Int)
InvalidRequestBodyReadTimeoutMs(Int)
InvalidHandlerTimeoutMs(Int)
InvalidShutdownTimeoutMs(Int)
InvalidWebSocketMaxMessageBytes(Int)
InvalidWebSocketOutgoingQueueCapacity(Int)
InvalidWebSocketReadTimeoutMs(Int)
} derive(Debug, ToJson)
///|
/// Configuration options for the native async HTTP server runtime.
/// The constructor validates all values eagerly and raises on invalid input.
pub struct NativeServeOptions {
/// Maximum concurrent TCP connections; `None` means unlimited.
max_connections : Int?
/// Maximum request body size in bytes; exceeding yields `413 Request Entity Too Large`.
max_request_body_bytes : Int?
/// Timeout for reading the request body in milliseconds; exceeding yields `408 Request Timeout`.
request_body_read_timeout_ms : Int?
/// Timeout for the handler + middleware pipeline in milliseconds; exceeding yields `504 Gateway Timeout`.
handler_timeout_ms : Int?
/// Graceful shutdown drain period in milliseconds; `None` means immediate cancellation.
shutdown_timeout_ms : Int?
/// Maximum buffered outbound WebSocket messages per connection (default: 256).
websocket_outgoing_queue_capacity : Int?
/// Policy when the outbound WebSocket queue is full (`DropOldest` or `DropLatest`).
websocket_overflow_policy : @ws.NativeWebSocketOverflowPolicy?
/// Timeout for the next inbound WebSocket message in milliseconds; exceeding closes the connection.
websocket_read_timeout_ms : Int?
/// Maximum inbound WebSocket message size in bytes; exceeding closes with `1009 Message Too Big`.
websocket_max_message_bytes : Int?
}
///|
/// Validate and construct `NativeServeOptions` from optional tuning
/// parameters. Each parameter defaults to `None` (moon fmt infers that
/// from the `?` markers) and is individually range-checked; raises if
/// any value is out of range.
pub fn NativeServeOptions::NativeServeOptions(
max_connections? : Int,
max_request_body_bytes? : Int,
request_body_read_timeout_ms? : Int,
handler_timeout_ms? : Int,
shutdown_timeout_ms? : Int,
websocket_outgoing_queue_capacity? : Int,
websocket_overflow_policy? : @ws.NativeWebSocketOverflowPolicy,
websocket_read_timeout_ms? : Int,
websocket_max_message_bytes? : Int,
) -> NativeServeOptions raise {
if max_connections is Some(v) {
guard v > 0 else { raise NativeServeError::InvalidMaxConnections(v) }
}
if max_request_body_bytes is Some(v) {
guard v >= 0 else { raise NativeServeError::InvalidMaxRequestBodyBytes(v) }
}
if request_body_read_timeout_ms is Some(v) {
guard v > 0 else {
raise NativeServeError::InvalidRequestBodyReadTimeoutMs(v)
}
}
if handler_timeout_ms is Some(v) {
guard v > 0 else { raise NativeServeError::InvalidHandlerTimeoutMs(v) }
}
if shutdown_timeout_ms is Some(v) {
guard v > 0 else { raise NativeServeError::InvalidShutdownTimeoutMs(v) }
}
if websocket_max_message_bytes is Some(v) {
guard v >= 0 else {
raise NativeServeError::InvalidWebSocketMaxMessageBytes(v)
}
}
if websocket_outgoing_queue_capacity is Some(v) {
guard v > 0 else {
raise NativeServeError::InvalidWebSocketOutgoingQueueCapacity(v)
}
}
if websocket_read_timeout_ms is Some(v) {
guard v > 0 else {
raise NativeServeError::InvalidWebSocketReadTimeoutMs(v)
}
}
{
max_connections,
max_request_body_bytes,
request_body_read_timeout_ms,
handler_timeout_ms,
shutdown_timeout_ms,
websocket_outgoing_queue_capacity,
websocket_overflow_policy,
websocket_read_timeout_ms,
websocket_max_message_bytes,
}
}
///|
test "NativeServeOptions accepts all defaults" {
let opts = NativeServeOptions()
debug_inspect(opts.max_connections, content="None")
}
///|
test "NativeServeOptions accepts valid values" {
let opts = NativeServeOptions(
max_connections=5,
max_request_body_bytes=1024,
request_body_read_timeout_ms=100,
handler_timeout_ms=5000,
shutdown_timeout_ms=5000,
websocket_outgoing_queue_capacity=10,
websocket_overflow_policy=DropLatest,
websocket_read_timeout_ms=100,
websocket_max_message_bytes=1024,
)
debug_inspect(opts.max_connections, content="Some(5)")
debug_inspect(opts.max_request_body_bytes, content="Some(1024)")
}
///|
test "NativeServeOptions accepts zero max_request_body_bytes" {
let opts = NativeServeOptions(max_request_body_bytes=0)
debug_inspect(opts.max_request_body_bytes, content="Some(0)")
}
///|
test "NativeServeOptions accepts zero websocket_max_message_bytes" {
let opts = NativeServeOptions(websocket_max_message_bytes=0)
debug_inspect(opts.websocket_max_message_bytes, content="Some(0)")
}
///|
test "NativeServeOptions rejects zero max_connections" {
@test.assert_raise(() => NativeServeOptions(max_connections=0))
}
///|
test "NativeServeOptions rejects negative max_connections" {
@test.assert_raise(() => NativeServeOptions(max_connections=-1))
}
///|
test "NativeServeOptions rejects negative max_request_body_bytes" {
@test.assert_raise(() => NativeServeOptions(max_request_body_bytes=-1))
}
///|
test "NativeServeOptions rejects zero request_body_read_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(request_body_read_timeout_ms=0))
}
///|
test "NativeServeOptions rejects negative request_body_read_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(request_body_read_timeout_ms=-1))
}
///|
test "NativeServeOptions rejects zero handler_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(handler_timeout_ms=0))
}
///|
test "NativeServeOptions rejects negative handler_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(handler_timeout_ms=-1))
}
///|
test "NativeServeOptions rejects zero shutdown_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(shutdown_timeout_ms=0))
}
///|
test "NativeServeOptions rejects negative shutdown_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(shutdown_timeout_ms=-1))
}
///|
test "NativeServeOptions rejects negative websocket_max_message_bytes" {
@test.assert_raise(() => NativeServeOptions(websocket_max_message_bytes=-1))
}
///|
test "NativeServeOptions rejects zero websocket_outgoing_queue_capacity" {
@test.assert_raise(() => {
NativeServeOptions(websocket_outgoing_queue_capacity=0)
})
}
///|
test "NativeServeOptions rejects negative websocket_outgoing_queue_capacity" {
@test.assert_raise(() => {
NativeServeOptions(websocket_outgoing_queue_capacity=-1)
})
}
///|
test "NativeServeOptions rejects zero websocket_read_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(websocket_read_timeout_ms=0))
}
///|
test "NativeServeOptions rejects negative websocket_read_timeout_ms" {
@test.assert_raise(() => NativeServeOptions(websocket_read_timeout_ms=-1))
}