using Astralis; using Invercargill; using Invercargill.DataStructures; /** * QueryParameters Example * * Demonstrates how to handle query parameters in Astralis. * Uses Invercargill Dictionary for parameter storage and * Enumerable for processing parameters. */ // Greet handler - simple query parameter access class GreetEndpoint : Object, Endpoint { public string route { get { return "/greet"; } } public Method[] methods { owned get { return { Method.GET }; } } public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error { var name = http_context.request.get_query_or_default("name", "World"); var greeting = http_context.request.get_query_or_default("greeting", "Hello"); return new HttpStringResult(@"$greeting, $name!"); } } // Search handler - multiple query parameters with validation class SearchEndpoint : Object, Endpoint { public string route { get { return "/search"; } } public Method[] methods { owned get { return { Method.GET }; } } public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error { var query = http_context.request.get_query("q"); var limit = int.parse(http_context.request.get_query_or_default("limit", "10")); var offset = int.parse(http_context.request.get_query_or_default("offset", "0")); if (query == null || query == "") { return new HttpStringResult(@"{ \"error\": \"Query parameter 'q' is required\" }") .set_header("Content-Type", "application/json"); } // Build response using Enumerable operations var results = Wrap.array({"Result 1", "Result 2", "Result 3", "Result 4", "Result 5"}) .skip(offset) .take(limit); var json_parts = new Series(); json_parts.add(@"{ \"query\": \"$query\", \"results\": ["); bool first = true; results.iterate((result) => { if (!first) json_parts.add(", "); json_parts.add(@"\"$result\""); first = false; }); json_parts.add("] }"); var json_string = json_parts.to_immutable_buffer() .aggregate("", (acc, s) => acc + s); return new HttpStringResult(json_string) .set_header("Content-Type", "application/json"); } } // Debug handler - boolean flag query parameters class DebugEndpoint : Object, Endpoint { public string route { get { return "/debug"; } } public Method[] methods { owned get { return { Method.GET }; } } public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error { var verbose = http_context.request.has_query("verbose"); var level = http_context.request.get_query_or_default("level", "info"); var parts = new Series(); parts.add("Debug Information:\n"); parts.add(@" Verbose mode: $(verbose ? "enabled" : "disabled")\n"); parts.add(@" Log level: $level\n"); // Add query parameters listing using Enumerable parts.add("\nAll query parameters:\n"); http_context.request.query_params.to_immutable_buffer() .iterate((grouping) => { grouping.iterate((value) => { parts.add(@" - $(grouping.key): $value\n"); }); }); var result = parts.to_immutable_buffer() .aggregate("", (acc, s) => acc + s); return new HttpStringResult(result); } } // Filter handler - query parameter with multiple values (comma-separated) class FilterEndpoint : Object, Endpoint { public string route { get { return "/filter"; } } public Method[] methods { owned get { return { Method.GET }; } } public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error { var tags_param = http_context.request.get_query("tags"); if (tags_param == null) { return new HttpStringResult(@"{ \"message\": \"No tags provided\" }") .set_header("Content-Type", "application/json"); } // Parse comma-separated tags using Enumerable operations var tags = Wrap.array(tags_param.split(",")) .select(tag => tag.strip()) .where(tag => tag != "") .to_vector(); var json_parts = new Series(); json_parts.add(@"{ \"tags\": ["); bool first = true; tags.to_immutable_buffer().iterate((tag) => { if (!first) json_parts.add(", "); json_parts.add(@"\"$tag\""); first = false; }); json_parts.add("] }"); var json_string = json_parts.to_immutable_buffer() .aggregate("", (acc, s) => acc + s); return new HttpStringResult(json_string) .set_header("Content-Type", "application/json"); } } // Range handler - numeric query parameters with range validation class RangeEndpoint : Object, Endpoint { public string route { get { return "/range"; } } public Method[] methods { owned get { return { Method.GET }; } } public async HttpResult handle_request(HttpContext http_context, RouteInformation route) throws Error { var min = int.parse(http_context.request.get_query_or_default("min", "0")); var max = int.parse(http_context.request.get_query_or_default("max", "100")); var step = int.parse(http_context.request.get_query_or_default("step", "1")); if (min >= max) { return new HttpStringResult(@"{ \"error\": \"min must be less than max\" }") .set_header("Content-Type", "application/json"); } // Generate range using Iterate.range and Enumerable operations var numbers = Iterate.range(min, max) .where(n => (n - min) % step == 0); var json_parts = new Series(); json_parts.add(@"{ \"min\": $min, \"max\": $max, \"step\": $step, \"numbers\": ["); bool first = true; numbers.iterate((n) => { if (!first) json_parts.add(", "); json_parts.add(n.to_string()); first = false; }); json_parts.add("] }"); var json_string = json_parts.to_immutable_buffer() .aggregate("", (acc, s) => acc + s); return new HttpStringResult(json_string) .set_header("Content-Type", "application/json"); } } void main() { var router = new EndpointRouter() .add_endpoint(new GreetEndpoint()) .add_endpoint(new SearchEndpoint()) .add_endpoint(new DebugEndpoint()) .add_endpoint(new FilterEndpoint()) .add_endpoint(new RangeEndpoint()); var pipeline = new Pipeline() .add_component(router); var server = new Server(8081, pipeline); print("Query Parameters Example Server running on port 8081\n"); print("Try these endpoints:\n"); print(" - http://localhost:8081/greet?name=Alice\n"); print(" - http://localhost:8081/search?q=test&limit=3\n"); print(" - http://localhost:8081/debug?verbose&level=debug\n"); print(" - http://localhost:8081/filter?tags=foo,bar,baz\n"); print(" - http://localhost:8081/range?min=1&max=20&step=2\n"); server.run(); }