| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- using Astralis;
- using Invercargill;
- using Invercargill.DataStructures;
- /**
- * HeadersAndCookies Example
- *
- * Demonstrates how to access and manipulate HTTP headers and cookies.
- * Uses Invercargill Dictionary and Enumerable for header/cookie processing.
- */
- // Display all request headers
- class HeadersEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var parts = new Series<string>();
- parts.add("Request Headers:\n");
- parts.add("================\n\n");
-
- http_context.request.headers.to_immutable_buffer()
- .iterate((grouping) => {
- grouping.iterate((value) => {
- parts.add(@"$(grouping.key): $value\n");
- });
- });
-
- var result = parts.to_immutable_buffer()
- .aggregate<string>("", (acc, s) => acc + s);
-
- return new HttpStringResult(result);
- }
- }
- // Check for user-agent header
- class UserAgentEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var user_agent = http_context.request.user_agent ?? "Unknown";
-
- return new HttpStringResult(@"Your User-Agent is: $user_agent");
- }
- }
- // Check content type and content length
- class ContentInfoEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var parts = new Series<string>();
- parts.add("Content Information:\n");
- parts.add("===================\n\n");
- parts.add(@"Content-Type: $(http_context.request.content_type)\n");
- parts.add(@"Content-Length: $(http_context.request.content_length)\n");
- parts.add(@"Content-Encoding: $(http_context.request.content_encoding ?? "none")\n");
-
- var result = parts.to_immutable_buffer()
- .aggregate<string>("", (acc, s) => acc + s);
-
- return new HttpStringResult(result);
- }
- }
- // Check if header exists
- class CheckHeaderEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var header_name = http_context.request.get_query_or_default("name", "Accept");
- var exists = http_context.request.has_header(header_name);
- var value = http_context.request.get_header(header_name);
-
- return new HttpStringResult(@"Header '$header_name': $(exists ? "EXISTS" : "NOT FOUND")\nValue: $(value ?? "N/A")");
- }
- }
- // Set custom response headers
- class CustomHeadersEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult("Response with custom headers!")
- .set_header("X-Custom-Header", "Custom-Value")
- .set_header("X-Request-Id", generate_request_id())
- .set_header("X-Powered-By", "Astralis")
- .set_header("X-Server-Time", new DateTime.now_local().format_iso8601());
- }
- }
- // Display all cookies
- class CookiesEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var parts = new Series<string>();
- parts.add("Request Cookies:\n");
- parts.add("================\n\n");
-
- if (http_context.request.cookies.to_immutable_buffer().count() == 0) {
- parts.add("(No cookies sent)\n");
- parts.add("\nTry setting a cookie first: /set-cookie?name=test&value=123\n");
- } else {
- http_context.request.cookies.to_immutable_buffer()
- .iterate((grouping) => {
- grouping.iterate((value) => {
- parts.add(@"$(grouping.key): $value\n");
- });
- });
- }
-
- var result = parts.to_immutable_buffer()
- .aggregate<string>("", (acc, s) => acc + s);
-
- return new HttpStringResult(result);
- }
- }
- // Get specific cookie
- class GetCookieEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var name = http_context.request.get_query_or_default("name", "session");
- var value = http_context.request.get_cookie(name);
-
- if (value == null) {
- return new HttpStringResult(@"Cookie '$name' not found");
- }
-
- return new HttpStringResult(@"Cookie '$name' = '$value'");
- }
- }
- // Set a cookie (via Set-Cookie header)
- class SetCookieEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var name = http_context.request.get_query_or_default("name", "test");
- var value = http_context.request.get_query_or_default("value", "123");
- var max_age = http_context.request.get_query_or_default("max_age", "3600");
-
- return new HttpStringResult(@"Cookie '$name' set to '$value'")
- .set_header("Set-Cookie", @"$name=$value; Max-Age=$max_age; Path=/");
- }
- }
- // Set multiple cookies
- class SetCookiesEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- // Note: Setting multiple cookies with the same header name requires
- // special handling - this example shows the approach
- return new HttpStringResult("Multiple cookies set!")
- .set_header("Set-Cookie", "user=john; Max-Age=3600; Path=/");
- // Additional cookies would need to be set via multiple Set-Cookie headers
- // which requires extending the HttpResult API or using a different approach
- }
- }
- // Delete a cookie
- class DeleteCookieEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var name = http_context.request.get_query_or_default("name", "test");
-
- return new HttpStringResult(@"Cookie '$name' deleted")
- .set_header("Set-Cookie", @"$name=; Max-Age=0; Path=/");
- }
- }
- // Check if cookie exists
- class HasCookieEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var name = http_context.request.get_query_or_default("name", "session");
- var exists = http_context.request.has_cookie(name);
-
- return new HttpStringResult(@"Cookie '$name': $(exists ? "EXISTS" : "NOT FOUND")");
- }
- }
- // Cookie-based session simulation
- class SessionEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var session_id = http_context.request.get_cookie("session_id");
-
- if (session_id == null) {
- // Create new session
- var new_session_id = generate_session_id();
-
- return new HttpStringResult(@"New session created!
- Session ID: $new_session_id
- Your session will expire in 1 hour.")
- .set_header("Set-Cookie", @"session_id=$new_session_id; Max-Age=3600; Path=/; HttpOnly");
- }
-
- // Existing session
- return new HttpStringResult(@"Welcome back!
- Session ID: $session_id
- Your session is active.");
- }
- }
- // CORS headers example
- class CorsEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var origin = http_context.request.get_header("Origin") ?? "*";
-
- return new HttpStringResult(@"CORS enabled for origin: $origin")
- .set_header("Access-Control-Allow-Origin", origin)
- .set_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
- .set_header("Access-Control-Allow-Headers", "Content-Type, Authorization")
- .set_header("Access-Control-Max-Age", "86400");
- }
- }
- // Cache control headers
- class CacheEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var cache_type = http_context.request.get_query_or_default("type", "public");
-
- return new HttpStringResult(@"This response is cached ($cache_type cache, 1 hour)")
- .set_header("Cache-Control", @"$cache_type, max-age=3600")
- .set_header("Expires", get_expires_header(3600))
- .set_header("ETag", generate_etag());
- }
- }
- // Content negotiation
- class NegotiateEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- var accept = http_context.request.get_header("Accept") ?? "*/*";
-
- if (accept.contains("application/json")) {
- return new HttpStringResult(@"{ \"message\": \"JSON response\", \"format\": \"json\" }")
- .set_header("Content-Type", "application/json");
- } else if (accept.contains("text/xml")) {
- return new HttpStringResult(@"<?xml version=\"1.0\"?><response><message>XML response</message><format>xml</format></response>")
- .set_header("Content-Type", "text/xml");
- } else {
- return new HttpStringResult("Plain text response")
- .set_header("Content-Type", "text/plain");
- }
- }
- }
- // Security headers
- class SecureEndpoint : Object, Endpoint {
- public async HttpResult handle_request(HttpContext http_context, RouteContext route) throws Error {
- return new HttpStringResult("Response with security headers!")
- .set_header("X-Content-Type-Options", "nosniff")
- .set_header("X-Frame-Options", "DENY")
- .set_header("X-XSS-Protection", "1; mode=block")
- .set_header("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
- .set_header("Content-Security-Policy", "default-src 'self'")
- .set_header("Referrer-Policy", "strict-origin-when-cross-origin");
- }
- }
- void main() {
- var application = new WebApplication(8083);
-
- application.container.register_scoped<Endpoint>(() => new HeadersEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/headers"));
-
- application.container.register_scoped<Endpoint>(() => new UserAgentEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/user-agent"));
-
- application.container.register_scoped<Endpoint>(() => new ContentInfoEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/content-info"));
-
- application.container.register_scoped<Endpoint>(() => new CheckHeaderEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/check-header"));
-
- application.container.register_scoped<Endpoint>(() => new CustomHeadersEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/custom-headers"));
-
- application.container.register_scoped<Endpoint>(() => new CookiesEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/cookies"));
-
- application.container.register_scoped<Endpoint>(() => new GetCookieEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/get-cookie"));
-
- application.container.register_scoped<Endpoint>(() => new SetCookieEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/set-cookie"));
-
- application.container.register_scoped<Endpoint>(() => new SetCookiesEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/set-cookies"));
-
- application.container.register_scoped<Endpoint>(() => new DeleteCookieEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/delete-cookie"));
-
- application.container.register_scoped<Endpoint>(() => new HasCookieEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/has-cookie"));
-
- application.container.register_scoped<Endpoint>(() => new SessionEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/session"));
-
- application.container.register_scoped<Endpoint>(() => new CorsEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/cors"));
-
- application.container.register_scoped<Endpoint>(() => new CacheEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/cache"));
-
- application.container.register_scoped<Endpoint>(() => new NegotiateEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/negotiate"));
-
- application.container.register_scoped<Endpoint>(() => new SecureEndpoint())
- .with_metadata<EndpointRoute>(new EndpointRoute("/secure"));
-
- print("Headers and Cookies Example Server running on port 8083\n");
- print("Try these endpoints:\n");
- print(" - http://localhost:8083/headers\n");
- print(" - http://localhost:8083/user-agent\n");
- print(" - http://localhost:8083/cookies\n");
- print(" - http://localhost:8083/set-cookie?name=test&value=hello\n");
- print(" - http://localhost:8083/set-cookies\n");
- print(" - http://localhost:8083/session\n");
- print(" - http://localhost:8083/cors\n");
- print(" - http://localhost:8083/cache\n");
- print(" - http://localhost:8083/negotiate\n");
- print(" - http://localhost:8083/secure\n");
-
- application.run();
- }
- // Helper functions
- string generate_request_id() {
- var timestamp = new DateTime.now_local().to_unix();
- var random = Random.next_int();
- return @"req-$timestamp-$random";
- }
- string generate_session_id() {
- var timestamp = new DateTime.now_local().to_unix();
- var random = Random.next_int();
- return @"sess-$timestamp-$random";
- }
- string generate_etag() {
- var timestamp = new DateTime.now_local().to_unix();
- return @"\"$timestamp\"";
- }
- string get_expires_header(int seconds) {
- var now = new DateTime.now_local();
- var expires = now.add_seconds(seconds);
- return expires.format("%a, %d %b %Y %H:%M:%S GMT");
- }
|