import core::http; import settings.aspl as app; share fn handle(req: http::IncomingRequest, ctx: http::Context) -> http::ServerResponse { let before = http::read_state(ctx); http::replace_state(ctx, app::State { count: before::count + 1 }); if req::path matches "/hello" { return http::text_response(200, "مرحبا من ASPL", "text/plain; charset=utf-8")::value; } if req::path matches "/submit" { let text = http::decode_utf8(req::body); if not text::ok { return http::text_response(400, text::error::code, "text/plain")::value; } // This echoes explicit JSON text. It does not parse or validate JSON. return http::text_response(200, text::value, "application/json; charset=utf-8")::value; } if req::path matches "/bytes" { return http::response(200, req::body)::value; } if req::path matches "/download" { return http::response(200, [0, 255, 65])::value; } if req::path matches "/count" { return http::text_response(200, format_i64(before::count), "text/plain")::value; } if req::path matches "/upstream" { let config = http::read_config(ctx); var options = http::client_options(); options::use_private_ca = true; options::ca_file = config::ca; let outbound = http::client_request("GET", config::upstream)::value; let reply = http::request(outbound, options); if not reply::ok { return http::text_response(502, reply::error::code, "text/plain")::value; } // Forward only the bytes. Compressed length/encoding metadata may be stale. return http::response(reply::value::status, reply::value::body)::value; } if req::path matches "/stop" { http::stop(ctx); } return http::response(200, [])::value; } share fn routes() -> http::Router { return http::router([ http::route("GET", "/hello", handle)::value, http::route("POST", "/submit", handle)::value, http::route("POST", "/bytes", handle)::value, http::route("GET", "/download", handle)::value, http::route("GET", "/count", handle)::value, http::route("GET", "/upstream", handle)::value, http::route("POST", "/stop", handle)::value ])::value; }