| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- using Astralis;
- using Invercargill;
- using Invercargill.DataStructures;
- /**
- * ErrorHandling Example
- *
- * Demonstrates error handling and status codes in Astralis.
- * Uses Invercargill data structures for error logging and management.
- */
- // Root handler
- class RootEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult("""Error Handling Demo
- This example demonstrates various error handling patterns in Astralis:
- Endpoints:
- GET /ok - 200 OK response
- GET /not-found - 404 Not Found
- GET /bad-request - 400 Bad Request
- GET /internal-error - 500 Internal Server Error
- GET /validation - Input validation example
- GET /resource/{id} - Resource lookup with error handling
- GET /api/{endpoint} - API endpoint simulation
- GET /custom-error - Custom error response
- GET /timeout - Simulated timeout
- GET /unauthorized - 401 Unauthorized
- GET /forbidden - 403 Forbidden
- GET /method-not-allowed - 405 Method Not Allowed
- """);
- }
- }
- // 200 OK response
- class OkEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"status\": \"success\", \"message\": \"Request completed successfully\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 404 Not Found
- class NotFoundEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"error\": \"Not Found\", \"message\": \"The requested resource was not found\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 400 Bad Request
- class BadRequestEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"error\": \"Bad Request\", \"message\": \"The request could not be understood\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 500 Internal Server Error
- class InternalErrorEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"error\": \"Internal Server Error\", \"message\": \"An unexpected error occurred\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // Input validation example
- class ValidationEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var email = http_context.request.get_query("email");
- var age_str = http_context.request.get_query("age");
-
- var error_list = new List<string>();
-
- if (email == null || !is_valid_email(email)) {
- error_list.append("Invalid email address");
- }
-
- if (age_str == null) {
- error_list.append("Age parameter is required");
- } else {
- var age = int.parse(age_str);
- if (age < 0 || age > 150) {
- error_list.append("Age must be between 0 and 150");
- }
- }
-
- if (error_list.length() > 0) {
- var json_parts = new StringBuilder();
- json_parts.append("{ \"error\": \"Validation Failed\", \"errors\": [");
-
- bool first = true;
- error_list.foreach((err) => {
- if (!first) {
- json_parts.append(", ");
- }
- json_parts.append("\"");
- json_parts.append(err);
- json_parts.append("\"");
- first = false;
- });
-
- json_parts.append("] }");
-
- var json_string = json_parts.str;
-
- return new HttpStringResult(json_string)
- .set_header("Content-Type", "application/json");
- }
-
- return new HttpStringResult(@"{ \"status\": \"success\", \"email\": \"$email\", \"age\": $age_str }")
- .set_header("Content-Type", "application/json");
- }
- }
- // Resource lookup with error handling
- class ResourceEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route_info) throws Error {
- string? id_str = null;
- route_info.mapped_parameters.try_get("id", out id_str);
- int id;
-
- if (!int.try_parse(id_str, out id)) {
- return error_response(@"Invalid resource ID: $id_str", StatusCode.BAD_REQUEST);
- }
-
- // Simulate resource lookup using array
- var resource_array = new Resource[3];
- resource_array[0] = new Resource(1, "Resource One", "Description of resource one");
- resource_array[1] = new Resource(2, "Resource Two", "Description of resource two");
- resource_array[2] = new Resource(3, "Resource Three", "Description of resource three");
-
- Resource? resource = null;
- foreach (var r in resource_array) {
- if (r.id == id) {
- resource = r;
- break;
- }
- }
-
- if (resource == null) {
- return error_response(@"Resource with ID $id not found", StatusCode.NOT_FOUND);
- }
-
- return new HttpStringResult(resource.to_json())
- .set_header("Content-Type", "application/json");
- }
- }
- // API endpoint simulation
- class ApiEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route_info) throws Error {
- string? endpoint = null;
- route_info.mapped_parameters.try_get("endpoint", out endpoint);
-
- // Simulate different API responses
- switch (endpoint) {
- case "users":
- return new HttpStringResult(@"{ \"users\": [{\"id\": 1, \"name\": \"Alice\"}, {\"id\": 2, \"name\": \"Bob\"}] }")
- .set_header("Content-Type", "application/json");
-
- case "posts":
- return new HttpStringResult(@"{ \"posts\": [{\"id\": 1, \"title\": \"First Post\"}, {\"id\": 2, \"title\": \"Second Post\"}] }")
- .set_header("Content-Type", "application/json");
-
- case "invalid":
- return error_response("Invalid API endpoint", StatusCode.NOT_FOUND);
-
- default:
- return error_response(@"Unknown endpoint: $endpoint", StatusCode.NOT_FOUND);
- }
- }
- }
- // Custom error response
- class CustomErrorEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var error_code = http_context.request.get_query_or_default("code", "CUSTOM_ERROR");
- var message = http_context.request.get_query_or_default("message", "A custom error occurred");
-
- var timestamp = new DateTime.now_local().format_iso8601();
- var request_id = generate_request_id();
- var json = @"{
- \"error\": \"$error_code\",
- \"message\": \"$message\",
- \"timestamp\": \"$timestamp\",
- \"request_id\": \"$request_id\"
- }";
-
- return new HttpStringResult(json)
- .set_header("Content-Type", "application/json");
- }
- }
- // Simulated timeout (actually returns 408)
- class TimeoutEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"error\": \"Request Timeout\", \"message\": \"The request took too long to complete\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 401 Unauthorized
- class UnauthorizedEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var auth_header = http_context.request.get_header("Authorization");
-
- if (auth_header == null) {
- return new HttpStringResult(@"{ \"error\": \"Unauthorized\", \"message\": \"Authentication required\" }")
- .set_header("Content-Type", "application/json")
- .set_header("WWW-Authenticate", "Bearer realm=\"api\"");
- }
-
- // Check auth token (simplified)
- if (!auth_header.contains("valid-token")) {
- return new HttpStringResult(@"{ \"error\": \"Unauthorized\", \"message\": \"Invalid authentication token\" }")
- .set_header("Content-Type", "application/json")
- .set_header("WWW-Authenticate", "Bearer error=\"invalid_token\"");
- }
-
- return new HttpStringResult(@"{ \"status\": \"success\", \"message\": \"Authenticated\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 403 Forbidden
- class ForbiddenEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var user_role = http_context.request.get_cookie("role") ?? "guest";
-
- if (user_role != "admin") {
- return new HttpStringResult(@"{ \"error\": \"Forbidden\", \"message\": \"You don't have permission to access this resource\" }")
- .set_header("Content-Type", "application/json");
- }
-
- return new HttpStringResult(@"{ \"status\": \"success\", \"message\": \"Admin access granted\" }")
- .set_header("Content-Type", "application/json");
- }
- }
- // 405 Method Not Allowed
- class MethodNotAllowedEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult(@"{ \"error\": \"Method Not Allowed\", \"message\": \"GET method is not allowed for this endpoint\" }")
- .set_header("Content-Type", "application/json")
- .set_header("Allow", "POST, PUT, DELETE");
- }
- }
- void main() {
- var application = new WebApplication(8088);
-
- application.container.register_scoped<Endpoint>(() => new RootEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/"));
-
- application.container.register_scoped<Endpoint>(() => new OkEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/ok"));
-
- application.container.register_scoped<Endpoint>(() => new NotFoundEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/not-found"));
-
- application.container.register_scoped<Endpoint>(() => new BadRequestEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/bad-request"));
-
- application.container.register_scoped<Endpoint>(() => new InternalErrorEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/internal-error"));
-
- application.container.register_scoped<Endpoint>(() => new ValidationEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/validation"));
-
- application.container.register_scoped<Endpoint>(() => new ResourceEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/resource/{id}"));
-
- application.container.register_scoped<Endpoint>(() => new ApiEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/api/{endpoint}"));
-
- application.container.register_scoped<Endpoint>(() => new CustomErrorEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/custom-error"));
-
- application.container.register_scoped<Endpoint>(() => new TimeoutEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/timeout"));
-
- application.container.register_scoped<Endpoint>(() => new UnauthorizedEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/unauthorized"));
-
- application.container.register_scoped<Endpoint>(() => new ForbiddenEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/forbidden"));
-
- application.container.register_scoped<Endpoint>(() => new MethodNotAllowedEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/method-not-allowed"));
-
- print("Error Handling Demo Server running on port 8088\n");
- print("Try these endpoints:\n");
- print(" - http://localhost:8088/\n");
- print(" - http://localhost:8088/ok\n");
- print(" - http://localhost:8088/not-found\n");
- print(" - http://localhost:8088/bad-request\n");
- print(" - http://localhost:8088/internal-error\n");
- print(" - http://localhost:8088/validation?email=test&age=25\n");
- print(" - http://localhost:8088/resource/1\n");
- print(" - http://localhost:8088/resource/999\n");
- print(" - http://localhost:8088/api/users\n");
- print(" - http://localhost:8088/custom-error?code=TEST&message=Test+error\n");
- print(" - http://localhost:8088/timeout\n");
- print(" - http://localhost:8088/unauthorized\n");
- print(" - http://localhost:8088/forbidden\n");
- print(" - http://localhost:8088/method-not-allowed\n");
-
- application.run();
- }
- // Helper functions
- HttpResult error_response(string message, StatusCode status) {
- var json = @"{ \"error\": \"Error\", \"message\": \"$message\" }";
- return new HttpStringResult(json)
- .set_header("Content-Type", "application/json");
- }
- string generate_request_id() {
- var timestamp = new DateTime.now_local().to_unix();
- var random = Random.next_int();
- return @"req-$timestamp-$random";
- }
- bool is_valid_email(string email) {
- // Simple email validation
- return email.contains("@") && email.contains(".") && email.length > 5;
- }
- // Helper classes
- class Resource {
- public int id { get; private set; }
- public string name { get; private set; }
- public string description { get; private set; }
-
- public Resource(int id, string name, string description) {
- this.id = id;
- this.name = name;
- this.description = description;
- }
-
- public string to_json() {
- return @"{ \"id\": $id, \"name\": \"$name\", \"description\": \"$description\" }";
- }
- }
|