diff --git a/Docs/examples/web-servers/01-basic-hello-server.wfl b/Docs/examples/web-servers/01-basic-hello-server.wfl new file mode 100644 index 00000000..ab486350 --- /dev/null +++ b/Docs/examples/web-servers/01-basic-hello-server.wfl @@ -0,0 +1,31 @@ +// Basic Hello World Web Server +// +// This is the simplest possible web server in WFL. +// It demonstrates the core web server syntax: listen, wait, and respond. +// +// To run this example: +// 1. Save as hello-server.wfl +// 2. Run: wfl hello-server.wfl +// 3. Visit http://127.0.0.1:8080 in your browser +// +// Expected output: "Hello from WFL Web Server!" + +display "=== Basic Hello World Web Server ===" +display "Starting web server on port 8080..." + +// Start the web server - this creates an HTTP server listening on port 8080 +listen on port 8080 as web_server + +display "✓ Server started successfully!" +display "Visit http://127.0.0.1:8080 in your browser" + +// Wait for an incoming HTTP request +wait for request comes in on web_server as req + +display "Received request: " with method with " " with path + +// Send a simple text response +respond to req with "Hello from WFL Web Server!" + +display "Server responded to request" +display "Example complete!" \ No newline at end of file diff --git a/Docs/examples/web-servers/02-file-server-basic.wfl b/Docs/examples/web-servers/02-file-server-basic.wfl new file mode 100644 index 00000000..4da8ec30 --- /dev/null +++ b/Docs/examples/web-servers/02-file-server-basic.wfl @@ -0,0 +1,65 @@ +// Basic File Server - Reads and Serves File Contents +// +// This example demonstrates reading a file from disk and serving its contents +// as an HTTP response. This is exactly what was requested in GitHub issue #213. +// +// To run this example: +// 1. Create a file called "content.txt" with some text +// 2. Save this as file-server.wfl +// 3. Run: wfl file-server.wfl +// 4. Visit http://127.0.0.1:8080 in your browser +// +// Key concepts: +// - Reading files with open/read/close +// - Serving file contents as HTTP responses +// - Basic error handling with try/catch +// - Setting content types + +display "=== Basic File Server Example ===" +display "This server reads files and serves their contents as HTTP responses" + +// Create a sample file for demonstration +try: + create file at "content.txt" with "Hello from WFL File Server! +This content was read from a file on disk. +WFL makes file serving simple and natural." + display "✓ Created sample content.txt file" +catch: + display "Note: Using existing content.txt file" +end try + +display "Starting web server on port 8080..." +listen on port 8080 as file_server + +display "✓ Server started successfully!" +display "Visit http://127.0.0.1:8080 to see file contents" + +// Wait for a request +wait for request comes in on file_server as req + +display "Request received: " with method with " " with path + +// Read file and serve its contents +try: + // Open the file for reading + open file at "content.txt" for reading as text_file + + // Read the entire file content into a variable + store file_content as read content from text_file + + // Close the file (good practice) + close file text_file + + // Send the file content as the HTTP response + respond to req with file_content and content_type "text/plain" + + display "✓ Successfully served file content" + display "File content length: " with length of file_content with " characters" + +catch: + // Handle file errors (file not found, permission denied, etc.) + respond to req with "Error: Could not read content.txt file" and status 404 + display "❌ Error reading file: " with error message +end try + +display "=== File Server Example Complete ===" \ No newline at end of file diff --git a/Docs/examples/web-servers/03-multi-route-server.wfl b/Docs/examples/web-servers/03-multi-route-server.wfl new file mode 100644 index 00000000..ff6fe23e --- /dev/null +++ b/Docs/examples/web-servers/03-multi-route-server.wfl @@ -0,0 +1,145 @@ +// Multi-Route File Server - Handle Different URLs +// +// This example shows how to handle different URL paths and serve different files +// based on the requested path. It demonstrates basic routing concepts. +// +// To run this example: +// 1. Create files: index.html, about.txt, data.json +// 2. Save this as multi-route-server.wfl +// 3. Run: wfl multi-route-server.wfl +// 4. Visit different URLs: +// - http://127.0.0.1:8080/ (serves index.html) +// - http://127.0.0.1:8080/about (serves about.txt) +// - http://127.0.0.1:8080/data (serves data.json) +// - http://127.0.0.1:8080/anything-else (shows 404) +// +// Key concepts: +// - URL path routing with check/otherwise +// - Different content types for different file types +// - HTTP status codes (200 OK, 404 Not Found) +// - Conditional file serving + +display "=== Multi-Route File Server Example ===" + +// Create sample files for demonstration +try: + create file at "index.html" with " + +WFL File Server + +

Welcome to WFL File Server!

+

This HTML file was served by WFL.

+ + +" + display "✓ Created index.html" +catch: + display "Using existing index.html" +end try + +try: + create file at "about.txt" with "About WFL File Server + +This is a simple file server built with WFL (WebFirst Language). +WFL uses natural language syntax to make web development intuitive. + +Key features: +- Natural English-like syntax +- Built-in web server capabilities +- Simple file serving +- Easy error handling" + display "✓ Created about.txt" +catch: + display "Using existing about.txt" +end try + +try: + create file at "data.json" with "{ + \"message\": \"Hello from WFL!\", + \"server\": \"WFL File Server\", + \"features\": [ + \"Natural language syntax\", + \"Built-in web server\", + \"File serving\", + \"JSON support\" + ], + \"version\": \"1.0\" +}" + display "✓ Created data.json" +catch: + display "Using existing data.json" +end try + +display "Starting multi-route server on port 8080..." +listen on port 8080 as multi_server + +display "✓ Server started successfully!" +display "Available routes:" +display " http://127.0.0.1:8080/ - HTML home page" +display " http://127.0.0.1:8080/about - Text about page" +display " http://127.0.0.1:8080/data - JSON data" + +// Wait for a request +wait for request comes in on multi_server as req + +display "Request: " with method with " " with path + +// Route handling based on URL path +check if path is equal to "/": + // Serve the home page (HTML file) + try: + open file at "index.html" for reading as html_file + store html_content as read content from html_file + close file html_file + respond to req with html_content and content_type "text/html" + display "✓ Served HTML home page" + catch: + respond to req with "Error loading home page" and status 500 + display "❌ Error serving home page" + end try + +check if path is equal to "/about": + // Serve the about page (text file) + try: + open file at "about.txt" for reading as about_file + store about_content as read content from about_file + close file about_file + respond to req with about_content and content_type "text/plain" + display "✓ Served about page" + catch: + respond to req with "About page not found" and status 404 + display "❌ Error serving about page" + end try + +check if path is equal to "/data": + // Serve JSON data + try: + open file at "data.json" for reading as json_file + store json_content as read content from json_file + close file json_file + respond to req with json_content and content_type "application/json" + display "✓ Served JSON data" + catch: + respond to req with "Data not found" and status 404 + display "❌ Error serving JSON data" + end try + +otherwise: + // Handle 404 - Page not found + store not_found_html as " + +404 Not Found + +

404 - Page Not Found

+

The requested page " with path with " was not found.

+

← Return to home page

+ +" + respond to req with not_found_html and status 404 and content_type "text/html" + display "❌ 404 Not Found: " with path +end check + +display "=== Multi-Route Server Example Complete ===" \ No newline at end of file diff --git a/Docs/examples/web-servers/04-advanced-comprehensive.wfl b/Docs/examples/web-servers/04-advanced-comprehensive.wfl new file mode 100644 index 00000000..2babc521 --- /dev/null +++ b/Docs/examples/web-servers/04-advanced-comprehensive.wfl @@ -0,0 +1,149 @@ +// Advanced Comprehensive Web Server +// +// This is a simplified version of the comprehensive web server demo that shows +// advanced features like JSON APIs, different HTTP methods, and request logging. +// Based on TestPrograms/comprehensive_web_server_demo.wfl but with explanatory comments. +// +// To run this example: +// 1. Save as advanced-server.wfl +// 2. Run: wfl advanced-server.wfl +// 3. Visit different endpoints: +// - http://127.0.0.1:8080/ (HTML home page) +// - http://127.0.0.1:8080/api/status (JSON status) +// - http://127.0.0.1:8080/api/time (JSON current time) +// +// Key concepts: +// - JSON API endpoints +// - Dynamic content generation +// - Server statistics and logging +// - Multiple content types +// - Request information access + +display "=== Advanced Comprehensive Web Server ===" +display "This server demonstrates advanced WFL web features" + +// Server configuration +store server_port as 8080 +store request_count as 0 +store server_start_time as current time in milliseconds + +display "Starting advanced web server on port " with server_port with "..." +listen on port server_port as advanced_server + +display "✓ Server started successfully!" +display "Available endpoints:" +display " GET http://127.0.0.1:8080/ - HTML home page" +display " GET http://127.0.0.1:8080/api/status - JSON server status" +display " GET http://127.0.0.1:8080/api/time - JSON current time" +display "" + +// Wait for incoming request +wait for request comes in on advanced_server as req + +// Increment request counter for statistics +store request_count as request_count plus 1 + +// Log the incoming request (middleware-like behavior) +display "Request #" with request_count with ": " with method with " " with path +display " Client IP: " with client_ip +display " User Agent: " with (headers at "user-agent" or "Unknown") + +// Route handling with different response types +check if path is equal to "/": + // Serve a dynamic HTML home page + store current_time as current time + store home_html as " + + + WFL Advanced Web Server + + + +

WFL Advanced Web Server Demo

+

This is an advanced web server built with WebFirst Language!

+ +
+

📊 Server Statistics

+

Requests served: " with request_count with "

+

Server time: " with current_time with "

+

Your IP: " with client_ip with "

+
+ +

🌐 Available API Endpoints

+
+ GET + /api/status - Server status information +
+
+ GET + /api/time - Current server time +
+ +

✨ WFL Features Demonstrated

+ + +" + respond to req with home_html and content_type "text/html" + display "✓ Served dynamic HTML home page" + +check if path is equal to "/api/status": + // Serve JSON status information + store uptime_ms as (current time in milliseconds) minus server_start_time + store uptime_seconds as uptime_ms divided by 1000 + + store status_json as "{ + \"server\": \"WFL Advanced Web Server\", + \"status\": \"running\", + \"version\": \"1.0\", + \"requests_served\": " with request_count with ", + \"uptime_seconds\": " with round of uptime_seconds with ", + \"current_time\": \"" with current time with "\", + \"client_ip\": \"" with client_ip with "\", + \"method\": \"" with method with "\" +}" + respond to req with status_json and content_type "application/json" + display "✓ Served JSON status API" + +check if path is equal to "/api/time": + // Serve current time as JSON + store time_json as "{ + \"current_time\": \"" with current time with "\", + \"timestamp_ms\": " with (current time in milliseconds) with ", + \"timezone\": \"Server Local Time\", + \"request_number\": " with request_count with " +}" + respond to req with time_json and content_type "application/json" + display "✓ Served JSON time API" + +otherwise: + // Handle 404 errors with JSON response + store error_json as "{ + \"error\": \"Not Found\", + \"message\": \"The requested endpoint '" with path with "' was not found.\", + \"status_code\": 404, + \"available_endpoints\": [ + \"/\", + \"/api/status\", + \"/api/time\" + ] +}" + respond to req with error_json and status 404 and content_type "application/json" + display "❌ 404 Not Found: " with path +end check + +display "" +display "Request processing complete!" +display "=== Advanced Web Server Example Complete ===" \ No newline at end of file diff --git a/Docs/examples/web-servers/README.md b/Docs/examples/web-servers/README.md new file mode 100644 index 00000000..2549a087 --- /dev/null +++ b/Docs/examples/web-servers/README.md @@ -0,0 +1,143 @@ +# WFL Web Server Examples + +This directory contains web server examples organized by complexity level. Each example demonstrates specific concepts and builds upon the previous ones. + +## 📁 Example Organization + +### Basic Level (Start Here!) + +**[01-basic-hello-server.wfl](01-basic-hello-server.wfl)** +- **Concept**: Simplest possible web server +- **Features**: `listen on port`, `wait for request`, `respond to` +- **Time**: 2 minutes +- **Perfect for**: First web server, understanding basic syntax + +**[02-file-server-basic.wfl](02-file-server-basic.wfl)** +- **Concept**: Reading files and serving their contents (exactly what was requested in issue #213) +- **Features**: File I/O with `open file`, `read content`, `close file` +- **Time**: 5 minutes +- **Perfect for**: Understanding file serving, error handling + +### Intermediate Level + +**[03-multi-route-server.wfl](03-multi-route-server.wfl)** +- **Concept**: Handling different URL paths and file types +- **Features**: Multiple routes, different content types, 404 handling +- **Time**: 10 minutes +- **Perfect for**: Learning URL routing, content types + +### Advanced Level + +**[04-advanced-comprehensive.wfl](04-advanced-comprehensive.wfl)** +- **Concept**: Full-featured server with APIs and dynamic content +- **Features**: JSON APIs, request logging, dynamic HTML, statistics +- **Time**: 15 minutes +- **Perfect for**: Production-like servers, API development + +## 🚀 Quick Start + +1. **Start with the basics**: Run `01-basic-hello-server.wfl` + ```bash + wfl 01-basic-hello-server.wfl + ``` + +2. **Try file serving**: Run `02-file-server-basic.wfl` + ```bash + wfl 02-file-server-basic.wfl + ``` + This directly addresses the GitHub issue request! + +3. **Explore routing**: Run `03-multi-route-server.wfl` + ```bash + wfl 03-multi-route-server.wfl + ``` + +4. **Build APIs**: Run `04-advanced-comprehensive.wfl` + ```bash + wfl 04-advanced-comprehensive.wfl + ``` + +## 🎯 Learning Path + +| Level | Focus | Time | Key Concepts | +|-------|-------|------|--------------| +| **Beginner** | Basic server setup | 5 min | `listen`, `wait for request`, `respond to` | +| **Beginner** | File serving | 10 min | File I/O, error handling, content types | +| **Intermediate** | Multiple routes | 15 min | Path routing, different file types | +| **Advanced** | Full features | 30 min | JSON APIs, dynamic content, logging | + +## 💡 Key WFL Web Server Concepts + +### Core Syntax +```wfl +// Start a server +listen on port 8080 as server_name + +// Handle requests +wait for request comes in on server_name as req + +// Send responses +respond to req with "content" and content_type "text/html" +respond to req with "error" and status 404 +``` + +### File Serving Pattern +```wfl +try: + open file at "filename.txt" for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/plain" +catch: + respond to req with "File not found" and status 404 +end try +``` + +### Request Information +```wfl +// Available request properties: +method // GET, POST, PUT, DELETE, etc. +path // /api/users, /, /hello, etc. +client_ip // Client's IP address +body // Request body content +headers // HTTP headers object +``` + +## 📚 Additional Resources + +- **[Quick Start Guide](../../guides/wfl-web-server-quickstart.md)** - 5-minute tutorial +- **[WFL by Example](../../guides/wfl-by-example.md#web-servers-and-http-services)** - Complete language tutorial +- **[Web Server Specification](../../wflspecs/SPEC-web-server.md)** - Complete feature documentation +- **[Test Programs](../../../TestPrograms/)** - More working examples + +## 🔧 Working with Test Programs + +The main WFL repository includes additional web server examples in the `TestPrograms/` directory: + +- **`test_static_files.wfl`** - Complete static file server +- **`comprehensive_web_server_demo.wfl`** - Full-featured server demo +- **`simple_web_server.wfl`** - Basic server example + +These are production test programs that must always work. + +## ⚡ Pro Tips + +1. **Start small**: Always begin with `01-basic-hello-server.wfl` +2. **Read the comments**: Each example has detailed explanations +3. **Modify and experiment**: Change ports, file names, content +4. **Check the test programs**: See `TestPrograms/` for more examples +5. **Use error handling**: Always wrap file operations in `try/catch` + +## 🤝 Contributing Examples + +When adding new examples: + +1. Follow the naming convention: `##-description-name.wfl` +2. Include comprehensive comments explaining each concept +3. Start with `display` statements showing what the example does +4. Use realistic scenarios that users might actually need +5. Update this README with the new example + +--- + +**Happy coding with WFL! 🚀** \ No newline at end of file diff --git a/Docs/guides/wfl-by-example.md b/Docs/guides/wfl-by-example.md index e5606abd..31b98c9a 100644 --- a/Docs/guides/wfl-by-example.md +++ b/Docs/guides/wfl-by-example.md @@ -14,9 +14,10 @@ This comprehensive guide teaches WFL through practical examples, building from s 8. [Functions (Actions)](#functions-actions) 9. [Containers (Objects/Classes)](#containers-objectsclasses) 10. [File Input and Output](#file-input-and-output) -11. [Async Operations and Web Requests](#async-operations-and-web-requests) -12. [Error Handling](#error-handling) -13. [Advanced Features](#advanced-features) +11. [Web Servers and HTTP Services](#web-servers-and-http-services) +12. [Async Operations and Web Requests](#async-operations-and-web-requests) +13. [Error Handling](#error-handling) +14. [Advanced Features](#advanced-features) --- @@ -734,9 +735,132 @@ display "Last modified: " with last modified --- +## Web Servers and HTTP Services + +WFL makes creating web servers natural and readable with its built-in web capabilities. Whether you're serving static files, creating APIs, or building web applications, WFL's syntax reads like English. + +**Simple web server:** + +```wfl +// Start a web server +listen on port 8080 as web_server + +display "Server started on http://127.0.0.1:8080" + +// Handle requests +wait for request comes in on web_server as req +respond to req with "Hello from WFL!" +``` + +**Serving file contents (exactly what you asked for!):** + +```wfl +// Read a file and serve it as HTTP response +listen on port 8080 as file_server + +wait for request comes in on file_server as req + +check if path is equal to "/": + try: + open file at "index.html" for reading as html_file + store content as read content from html_file + close file html_file + respond to req with content and content_type "text/html" + catch: + respond to req with "File not found" and status 404 + end try +otherwise: + respond to req with "Welcome to WFL Web Server" and content_type "text/plain" +end check +``` + +**Handling different HTTP methods and paths:** + +```wfl +listen on port 8080 as api_server + +wait for request comes in on api_server as req + +check if method is equal to "GET" and path is equal to "/api/status": + respond to req with "{\"status\": \"ok\"}" and content_type "application/json" + +check if method is equal to "POST" and path is equal to "/api/data": + // Read POST body and save to file + try: + create file at "uploads/data.txt" with body + respond to req with "Data saved successfully" + catch: + respond to req with "Save failed" and status 500 + end try + +otherwise: + respond to req with "Not found" and status 404 +end check +``` + +**Complete file server with multiple file types:** + +```wfl +listen on port 8080 as static_server + +wait for request comes in on static_server as req + +check if path is equal to "/": + // Serve HTML file + try: + open file at "public/index.html" for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/html" + catch: + respond to req with "Index not found" and status 404 + end try + +check if path is equal to "/style.css": + // Serve CSS file + try: + open file at "public/style.css" for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/css" + catch: + respond to req with "CSS not found" and status 404 + end try + +check if path is equal to "/data.json": + // Serve JSON file + try: + open file at "public/data.json" for reading as file + store content as read content from file + close file + respond to req with content and content_type "application/json" + catch: + respond to req with "Data not found" and status 404 + end try + +otherwise: + respond to req with "404 - Page not found" and status 404 +end check +``` + +**Request properties available:** +- `method` - HTTP method (GET, POST, PUT, DELETE) +- `path` - URL path (e.g., "/api/users") +- `body` - Request body content +- `headers` - HTTP headers +- `client_ip` - Client's IP address + +**For more web server examples, see:** +- [WFL Web Server Quick Start Guide](wfl-web-server-quickstart.md) - Complete tutorial +- `TestPrograms/test_static_files.wfl` - Working file server +- `TestPrograms/comprehensive_web_server_demo.wfl` - Advanced features +- [Web Server Specification](../wflspecs/SPEC-web-server.md) - Complete feature documentation + +--- + ## Async Operations and Web Requests -WFL supports asynchronous operations for web requests and concurrent tasks: +WFL also supports making outbound HTTP requests and asynchronous operations for concurrent tasks: **Simple web request:** diff --git a/Docs/guides/wfl-getting-started.md b/Docs/guides/wfl-getting-started.md index b07d8bb8..ea71b8eb 100644 --- a/Docs/guides/wfl-getting-started.md +++ b/Docs/guides/wfl-getting-started.md @@ -271,14 +271,36 @@ otherwise: end check ``` +### 4. Simple Web Server +```wfl +// Create a web server that serves files +listen on port 8080 as web_server + +display "Web server started at http://127.0.0.1:8080" +display "Visit the URL in your browser!" + +wait for request comes in on web_server as req + +check if path is equal to "/": + respond to req with "Welcome to WFL! This is your first web server." +check if path is equal to "/hello": + respond to req with "Hello from WFL Web Server!" +otherwise: + respond to req with "Page not found" and status 404 +end check + +display "Server responded to a request" +``` + ## Next Steps Now that you've mastered the basics: 1. **Explore More Examples**: Look at the programs in the `TestPrograms/` folder 2. **Read the Language Reference**: Check out the detailed documentation in `Docs/language-reference/` -3. **Try the WFL by Example Guide**: For a more comprehensive learning path -4. **Use the Cookbook**: For solutions to common programming tasks +3. **Try the WFL by Example Guide**: For a more comprehensive learning path, including [web servers](wfl-by-example.md#web-servers-and-http-services) +4. **Learn Web Development**: Check out the [WFL Web Server Quick Start Guide](wfl-web-server-quickstart.md) +5. **Use the Cookbook**: For solutions to common programming tasks ## Getting Help diff --git a/Docs/guides/wfl-web-server-cookbook.md b/Docs/guides/wfl-web-server-cookbook.md new file mode 100644 index 00000000..ff18a439 --- /dev/null +++ b/Docs/guides/wfl-web-server-cookbook.md @@ -0,0 +1,554 @@ +# WFL Web Server Cookbook + +*Common patterns and solutions for building web servers with WFL* + +This cookbook provides ready-to-use patterns for common web server tasks. Each recipe includes working code that you can copy and adapt for your own projects. + +## Table of Contents + +- [Basic Patterns](#basic-patterns) +- [File Serving Patterns](#file-serving-patterns) +- [API Development Patterns](#api-development-patterns) +- [Error Handling Patterns](#error-handling-patterns) +- [Security and Validation](#security-and-validation) +- [Performance Tips](#performance-tips) + +--- + +## Basic Patterns + +### Simple HTTP Server +*Start a basic web server and respond to requests* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req +respond to req with "Hello, World!" +``` + +### Multi-Route Server +*Handle different URL paths* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if path is equal to "/": + respond to req with "Home page" +check if path is equal to "/about": + respond to req with "About page" +check if path is equal to "/contact": + respond to req with "Contact page" +otherwise: + respond to req with "Page not found" and status 404 +end check +``` + +### Method-Based Routing +*Handle different HTTP methods* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if method is equal to "GET" and path is equal to "/users": + respond to req with "List of users" +check if method is equal to "POST" and path is equal to "/users": + respond to req with "Create new user" +check if method is equal to "PUT" and path is equal to "/users": + respond to req with "Update user" +check if method is equal to "DELETE" and path is equal to "/users": + respond to req with "Delete user" +otherwise: + respond to req with "Method not allowed" and status 405 +end check +``` + +--- + +## File Serving Patterns + +### Basic File Server +*Read a file and serve its contents* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +try: + open file at "content.txt" for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/plain" +catch: + respond to req with "File not found" and status 404 +end try +``` + +### Static File Server with MIME Types +*Serve different file types with correct content types* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +// Remove leading slash for file path +store file_path as substring of path from 1 +check if file_path is equal to "": + store file_path as "index.html" +end check + +try: + open file at file_path for reading as file + store content as read content from file + close file + + // Set content type based on file extension + check if file_path ends with ".html": + respond to req with content and content_type "text/html" + check if file_path ends with ".css": + respond to req with content and content_type "text/css" + check if file_path ends with ".js": + respond to req with content and content_type "text/javascript" + check if file_path ends with ".json": + respond to req with content and content_type "application/json" + otherwise: + respond to req with content and content_type "text/plain" + end check + +catch: + respond to req with "File not found" and status 404 +end try +``` + +### Directory-Based File Serving +*Serve files from a specific directory* + +```wfl +listen on port 8080 as server +store public_dir as "public" + +wait for request comes in on server as req + +// Build safe file path +store requested_file as substring of path from 1 +check if requested_file is equal to "": + store requested_file as "index.html" +end check + +store full_path as public_dir with "/" with requested_file + +try: + open file at full_path for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/html" +catch: + respond to req with "File not found" and status 404 +end try +``` + +--- + +## API Development Patterns + +### JSON API Response +*Return structured JSON data* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if path is equal to "/api/status": + store response_json as "{ + \"status\": \"OK\", + \"timestamp\": \"" with current time with "\", + \"server\": \"WFL Web Server\" +}" + respond to req with response_json and content_type "application/json" +end check +``` + +### POST Data Handler +*Process incoming POST data* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if method is equal to "POST" and path is equal to "/api/data": + // Process the POST body + store received_data as body + + // Log the received data (in real app, you might save to file/database) + display "Received POST data: " with received_data + + // Send confirmation response + store response as "{\"message\": \"Data received successfully\"}" + respond to req with response and content_type "application/json" + +otherwise: + respond to req with "{\"error\": \"Not found\"}" and status 404 +end check +``` + +### REST API Pattern +*Complete RESTful API for a resource* + +```wfl +listen on port 8080 as api_server + +wait for request comes in on api_server as req + +// Users API endpoints +check if path starts with "/api/users": + check if method is equal to "GET" and path is equal to "/api/users": + // GET /api/users - List all users + store users_json as "[{\"id\": 1, \"name\": \"Alice\"}, {\"id\": 2, \"name\": \"Bob\"}]" + respond to req with users_json and content_type "application/json" + + check if method is equal to "POST" and path is equal to "/api/users": + // POST /api/users - Create new user + store new_user as "{\"id\": 3, \"name\": \"New User\", \"created\": \"" with current time with "\"}" + respond to req with new_user and content_type "application/json" + + check if method is equal to "GET" and path starts with "/api/users/": + // GET /api/users/:id - Get specific user + store user_id as substring of path from 11 // Extract ID from path + store user_json as "{\"id\": " with user_id with ", \"name\": \"User " with user_id with "\"}" + respond to req with user_json and content_type "application/json" + + otherwise: + respond to req with "{\"error\": \"Method not allowed\"}" and status 405 + end check + +otherwise: + respond to req with "{\"error\": \"API endpoint not found\"}" and status 404 +end check +``` + +--- + +## Error Handling Patterns + +### Graceful Error Handling +*Handle errors without crashing the server* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +try: + // Attempt to serve a file + store file_name as substring of path from 1 + check if file_name is equal to "": + store file_name as "index.html" + end check + + open file at file_name for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/html" + +when file not found: + respond to req with "The requested file was not found" and status 404 +when permission denied: + respond to req with "Access to file is denied" and status 403 +when error: + respond to req with "Internal server error occurred" and status 500 + display "Unexpected error: " with error message +end try +``` + +### Custom Error Pages +*Serve custom HTML error pages* + +```wfl +define action called send error page: + parameter request as Request + parameter status_code as Number + parameter error_title as Text + parameter error_message as Text + + store error_html as " + + + " with error_title with " + + + +

" with status_code with " " with error_title with "

+

" with error_message with "

+

← Return to home page

+ +" + + respond to request with error_html and status status_code and content_type "text/html" +end action + +// Usage: +listen on port 8080 as server + +wait for request comes in on server as req + +check if path is equal to "/missing": + send error page with req and 404 and "Not Found" and "The page you requested does not exist." +otherwise: + respond to req with "Welcome to the home page!" +end check +``` + +--- + +## Security and Validation + +### Input Validation +*Validate request data before processing* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if method is equal to "POST" and path is equal to "/api/validate": + // Validate that body is not empty + check if length of body is equal to 0: + respond to req with "{\"error\": \"Request body is required\"}" and status 400 + return + end check + + // Validate maximum body size (example: 1MB limit) + check if length of body is greater than 1048576: + respond to req with "{\"error\": \"Request body too large\"}" and status 413 + return + end check + + // Process valid request + respond to req with "{\"message\": \"Data is valid\"}" and content_type "application/json" +end check +``` + +### Path Security +*Prevent directory traversal attacks* + +```wfl +define action called is safe path: + parameter requested_path as Text + + // Check for directory traversal attempts + check if requested_path contains "..": + return no + end check + + check if requested_path contains "~": + return no + end check + + // Only allow alphanumeric, hyphens, underscores, and slashes + // (In a real implementation, you'd use pattern matching) + return yes +end action + +listen on port 8080 as server + +wait for request comes in on server as req + +store requested_file as substring of path from 1 +check if requested_file is equal to "": + store requested_file as "index.html" +end check + +check if is safe path with requested_file: + // Safe to serve file + try: + open file at "public/" with requested_file for reading as file + store content as read content from file + close file + respond to req with content + catch: + respond to req with "File not found" and status 404 + end try +else: + respond to req with "Invalid file path" and status 400 +end check +``` + +--- + +## Performance Tips + +### Request Logging +*Log requests for monitoring and debugging* + +```wfl +listen on port 8080 as server +store request_count as 0 + +wait for request comes in on server as req + +// Increment request counter +store request_count as request_count plus 1 + +// Log request details +store log_entry as "[" with current time with "] Request #" with request_count with ": " with method with " " with path with " from " with client_ip +display log_entry + +// You could also write to a log file: +try: + append log_entry with "\n" to file "access.log" +catch: + display "Warning: Could not write to log file" +end try + +// Process request normally +respond to req with "Request processed successfully" +``` + +### Response Caching Headers +*Set appropriate cache headers for static content* + +```wfl +listen on port 8080 as server + +wait for request comes in on server as req + +check if path ends with ".css" or path ends with ".js": + // Static assets - cache for 1 hour + try: + store file_path as substring of path from 1 + open file at file_path for reading as file + store content as read content from file + close file + + respond to req with content and content_type "text/css" and header "Cache-Control" as "public, max-age=3600" + catch: + respond to req with "File not found" and status 404 + end try +else: + // Dynamic content - no cache + respond to req with "Dynamic content" and header "Cache-Control" as "no-cache" +end check +``` + +--- + +## Complete Example: Blog Server + +Here's a complete example that combines many patterns: + +```wfl +// Blog server demonstrating multiple patterns +display "=== WFL Blog Server ===" +display "Starting blog server with multiple features..." + +listen on port 8080 as blog_server +store post_count as 0 + +display "✓ Blog server started on port 8080" +display "Available endpoints:" +display " GET / - Blog home page" +display " GET /api/posts - List all posts (JSON)" +display " POST /api/posts - Create new post" +display " GET /static/* - Static files" + +wait for request comes in on blog_server as req + +// Log request +display "[" with current time with "] " with method with " " with path with " from " with client_ip + +// Route handling +check if path is equal to "/": + // Serve blog home page + store home_html as " + + + WFL Blog + + + +

WFL Blog Server

+

Welcome to the blog server built with WebFirst Language!

+
+

Sample Post

+

This is an example blog post served by WFL.

+

Posted on " with current time with "

+
+

View posts as JSON

+ +" + respond to req with home_html and content_type "text/html" + +check if path is equal to "/api/posts" and method is equal to "GET": + // List posts as JSON + store posts_json as "[ + {\"id\": 1, \"title\": \"Welcome to WFL\", \"content\": \"First post!\"}, + {\"id\": 2, \"title\": \"Web Servers in WFL\", \"content\": \"Easy to create!\"} +]" + respond to req with posts_json and content_type "application/json" + +check if path is equal to "/api/posts" and method is equal to "POST": + // Create new post + store post_count as post_count plus 1 + store new_post as "{ + \"id\": " with post_count with ", + \"title\": \"New Post\", + \"content\": \"" with body with "\", + \"created\": \"" with current time with "\" +}" + respond to req with new_post and content_type "application/json" + +check if path starts with "/static/": + // Serve static files + store file_name as substring of path from 8 // Remove "/static/" + try: + open file at "static/" with file_name for reading as static_file + store file_content as read content from static_file + close file static_file + respond to req with file_content + catch: + respond to req with "Static file not found" and status 404 + end try + +otherwise: + // 404 error with custom page + store error_html as " + +404 - Not Found + +

Page Not Found

+

The page " with path with " was not found.

+

← Return to blog home

+ +" + respond to req with error_html and status 404 and content_type "text/html" +end check + +display "Blog server request processed successfully" +``` + +--- + +## Next Steps + +- **[Web Server Quick Start](wfl-web-server-quickstart.md)** - 5-minute tutorial +- **[Web Server Examples](../examples/web-servers/)** - Organized examples by complexity +- **[WFL by Example](wfl-by-example.md)** - Complete language tutorial +- **[SPEC-web-server.md](../wflspecs/SPEC-web-server.md)** - Complete feature documentation + +Happy web development with WFL! 🌐 \ No newline at end of file diff --git a/Docs/guides/wfl-web-server-quickstart.md b/Docs/guides/wfl-web-server-quickstart.md new file mode 100644 index 00000000..674f6ae7 --- /dev/null +++ b/Docs/guides/wfl-web-server-quickstart.md @@ -0,0 +1,248 @@ +# WFL Web Server Quick Start Guide + +*Get your first WFL web server running in 5 minutes* + +WFL makes creating web servers natural and readable with its built-in web capabilities. This guide shows you how to create a simple web server that reads files and serves them as HTTP responses. + +## Table of Contents + +1. [Your First Web Server](#your-first-web-server) +2. [Serving Static Files](#serving-static-files) +3. [Handling Different HTTP Methods](#handling-different-http-methods) +4. [Error Handling](#error-handling) +5. [Next Steps](#next-steps) + +--- + +## Your First Web Server + +Let's start with the simplest possible web server: + +```wfl +// Start a web server on port 8080 +listen on port 8080 as web_server + +display "Server started on port 8080!" +display "Visit http://127.0.0.1:8080 to test it" + +// Wait for a request and respond +wait for request comes in on web_server as req +respond to req with "Hello from WFL Web Server!" + +display "Server responded to request" +``` + +**What's happening:** +- `listen on port 8080 as web_server` - Creates a web server listening on port 8080 +- `wait for request comes in` - Waits for an HTTP request to arrive +- `respond to req with` - Sends an HTTP response back to the client + +Save this as `hello-server.wfl` and run it with: +```bash +wfl hello-server.wfl +``` + +Visit `http://127.0.0.1:8080` in your browser to see "Hello from WFL Web Server!" + +--- + +## Serving Static Files + +Now let's create a server that reads and serves file contents - exactly what was requested in the GitHub issue: + +```wfl +// Simple file server that reads and displays file contents +display "=== File Server Demo ===" +display "Starting web server on port 8080..." + +// Start the web server +listen on port 8080 as file_server + +display "✓ Server started successfully!" +display "Testing file serving..." + +// Wait for a request +wait for request comes in on file_server as request + +display "Request: " with method with " " with path + +// Check the requested path and serve appropriate files +check if path is equal to "/": + // Serve index.html for the root path + try: + open file at "index.html" for reading as html_file + store html_content as read content from html_file + close file html_file + respond to request with html_content and content_type "text/html" + display "✓ Served index.html" + catch: + respond to request with "File not found: index.html" and status 404 + display "❌ index.html not found" + end try + +check if path is equal to "/data.txt": + // Serve a text file + try: + open file at "data.txt" for reading as text_file + store text_content as read content from text_file + close file text_file + respond to request with text_content and content_type "text/plain" + display "✓ Served data.txt" + catch: + respond to request with "File not found: data.txt" and status 404 + display "❌ data.txt not found" + end try + +otherwise: + // 404 for unknown paths + store not_found_html as " + +404 Not Found + +

404 - File Not Found

+

The requested file " with path with " was not found.

+

← Return to home

+ +" + respond to request with not_found_html and status 404 and content_type "text/html" + display "❌ 404 Not Found: " with path +end check + +display "Server finished handling request" +``` + +**Key concepts:** +- **Reading files:** `open file at "filename" for reading` → `read content from file` → `close file` +- **HTTP responses:** `respond to request with content and content_type "text/html"` +- **Path routing:** `check if path is equal to "/"` to handle different URLs +- **Error handling:** `try/catch` blocks for file operations, HTTP status codes + +**To test this server:** + +1. Create an `index.html` file: + ```html + + + WFL File Server + +

Welcome to WFL File Server!

+

This file was served from disk by WFL.

+

View data.txt

+ + + ``` + +2. Create a `data.txt` file: + ``` + Hello from WFL! + This text file was read from disk and served by the web server. + WFL makes file serving simple and readable. + ``` + +3. Run the server: `wfl file-server.wfl` + +4. Test the URLs: + - `http://127.0.0.1:8080/` - Serves the HTML file + - `http://127.0.0.1:8080/data.txt` - Serves the text file + - `http://127.0.0.1:8080/missing` - Shows 404 error + +--- + +## Handling Different HTTP Methods + +WFL automatically provides access to HTTP request details: + +```wfl +listen on port 8080 as api_server + +wait for request comes in on api_server as req + +display "Received " with method with " request to " with path + +check if method is equal to "GET": + respond to req with "GET request received" and content_type "text/plain" +check if method is equal to "POST": + respond to req with "POST request received" and content_type "text/plain" +otherwise: + respond to req with "Method not supported" and status 405 +end check +``` + +**Request properties available:** +- `method` - HTTP method (GET, POST, PUT, DELETE, etc.) +- `path` - URL path (e.g., "/api/users") +- `headers` - HTTP headers +- `body` - Request body (for POST/PUT requests) +- `client_ip` - Client IP address + +--- + +## Error Handling + +WFL provides natural error handling for web servers: + +```wfl +listen on port 8080 as secure_server + +try: + wait for request comes in on secure_server as req + + // Read configuration file + try: + open file at "config.json" for reading as config_file + store config as read content from config_file + close file config_file + respond to req with config and content_type "application/json" + catch: + respond to req with "Configuration error" and status 500 + end try + +when server error: + display "Server encountered an error" +when port unavailable: + display "Port 8080 is already in use" +otherwise: + display "Unexpected error: " with error message +end try +``` + +**Common error scenarios:** +- File not found → HTTP 404 +- Permission denied → HTTP 403 +- Server errors → HTTP 500 +- Port already in use → Server startup failure + +--- + +## Next Steps + +Congratulations! You now know how to: +- ✅ Start a basic WFL web server +- ✅ Read files and serve their contents as HTTP responses +- ✅ Handle different URL paths +- ✅ Manage HTTP methods and status codes +- ✅ Implement error handling + +### Explore More Advanced Features + +- **Static file serving with MIME detection** - See [`TestPrograms/test_static_files.wfl`](../../TestPrograms/test_static_files.wfl) +- **Comprehensive web server** - See [`TestPrograms/comprehensive_web_server_demo.wfl`](../../TestPrograms/comprehensive_web_server_demo.wfl) +- **JSON APIs and POST handling** - Check out examples in [`TestPrograms/`](../../TestPrograms/) +- **Complete web server specification** - Read [SPEC-web-server.md](../wflspecs/SPEC-web-server.md) for all planned features and implementation status + +### Learn More About WFL + +- **[WFL by Example](wfl-by-example.md)** - Complete language tutorial +- **[WFL Getting Started](wfl-getting-started.md)** - Installation and first steps +- **[File I/O Guide](../wfldocs/WFL-io.md)** - Working with files and I/O +- **[Error Handling](../wfldocs/WFL-errors.md)** - Complete error handling guide + +### Community and Support + +- **Test Programs** - All examples in [`TestPrograms/`](../../TestPrograms/) are guaranteed to work +- **Documentation** - Complete documentation in [`Docs/`](../../Docs/) +- **Issues** - Report problems or request features on GitHub + +--- + +**Pro tip:** WFL web servers are built on the robust Warp framework with Tokio async runtime, giving you production-ready performance with natural language syntax! \ No newline at end of file diff --git a/Docs/wfl-documentation-index.md b/Docs/wfl-documentation-index.md index 115633ba..81aa75e3 100644 --- a/Docs/wfl-documentation-index.md +++ b/Docs/wfl-documentation-index.md @@ -32,7 +32,7 @@ Implemented language features and syntax documentation: - **[Async Programming](wfldocs/WFL-async.md)** - Asynchronous operations and concurrency - **[Container System](wfldocs/WFL-containers.md)** - Object-oriented programming in WFL - **[Error Handling](wfldocs/WFL-errors.md)** - Understanding and handling errors -- **[I/O Operations](wfldocs/WFL-io.md)** - File and network input/output +- **[I/O Operations](wfldocs/WFL-io.md)** - File and network input/output (includes web servers) - **[Main Loop](wfldocs/WFL-main-loop.md)** - Event-driven programming - **[Loop Scoping](wfldocs/WFL-loop-scoping.md)** - Loop variable scoping and iteration behavior @@ -40,7 +40,7 @@ Implemented language features and syntax documentation: Proposed and experimental features under development: -- **[Web Server Implementation](wflspecs/SPEC-web-server.md)** - Planned web server functionality and API design +- **[Web Server Implementation](wflspecs/SPEC-web-server.md)** - Complete web server functionality and API design (many features implemented) ## 📖 Guides and Tutorials @@ -48,7 +48,8 @@ Best practices and learning resources: - **[WFL Foundation](guides/wfl-foundation.md)** - Core principles and design philosophy - **[Getting Started](guides/wfl-getting-started.md)** - Installation and first steps -- **[WFL by Example](guides/wfl-by-example.md)** - Learn through practical examples +- **[WFL by Example](guides/wfl-by-example.md)** - Learn through practical examples (includes web servers) +- **[Web Server Quick Start](guides/wfl-web-server-quickstart.md)** - Create file-serving web servers in 5 minutes - **[WFL Cookbook](guides/wfl-cookbook.md)** - Recipes for common tasks - **[Building WFL](guides/building.md)** - Building from source - **[Deployment Guide](guides/wfl-deployment.md)** - Deploying WFL applications @@ -185,7 +186,7 @@ When adding new documentation: - **Core Language Features (WFLDocs):** 11 comprehensive guides - **Planned Features (WFLSpecs):** 1 specification document -- **User Guides:** 14 tutorials and how-tos +- **User Guides:** 15 tutorials and how-tos - **IDE Integration:** 3 LSP and editor guides - **API Documentation:** 11 module references - **Technical Docs:** 19 internal documents (including moved files) diff --git a/Docs/wfldocs/WFL-io.md b/Docs/wfldocs/WFL-io.md index e0219f10..e3b80112 100644 --- a/Docs/wfldocs/WFL-io.md +++ b/Docs/wfldocs/WFL-io.md @@ -17,6 +17,7 @@ This document describes WFL's unified I/O vision. **Not all features described h | Feature Category | Status | Details | |-----------------|--------|---------| | **File I/O** | ✅ **Implemented** | `open file`, `read from`, `write to`, `close` - All file operations work as specified | +| **Web Servers** | ✅ **Implemented** | `listen on port`, `wait for request`, `respond to` - Full HTTP server functionality | | **Basic HTTP** | ✅ **Implemented** | `wait for open url` for GET/POST requests - Async HTTP operations functional | | **Subprocess Execution** | ✅ **Implemented** | `execute command`, `spawn command`, process control, output streaming - Full subprocess support | | **HTTP Headers & Advanced** | 🔧 **Partial** | Basic requests work; advanced header manipulation may be limited | @@ -48,6 +49,25 @@ wait for open url at "https://api.example.com/data" and read content as response wait for http post request to "https://api.example.com/endpoint" with data as result ``` +**Web Servers (Fully Working):** +```wfl +// Start an HTTP server +listen on port 8080 as web_server + +// Handle incoming requests +wait for request comes in on web_server as req + +// Read files and serve them +try: + open file at "index.html" for reading as html_file + store content as read content from html_file + close file html_file + respond to req with content and content_type "text/html" +catch: + respond to req with "File not found" and status 404 +end try +``` + **Subprocess Execution (Fully Working):** ```wfl // Execute external commands @@ -70,7 +90,9 @@ The following are **architectural specifications** for future development. Code **For up-to-date information on implementation status, see:** - [WFL-spec.md](WFL-spec.md) - Current language features -- [SPEC-web-server.md](../wflspecs/SPEC-web-server.md) - Planned web server features +- [SPEC-web-server.md](../wflspecs/SPEC-web-server.md) - Complete web server feature documentation +- [Web Server Quick Start Guide](../guides/wfl-web-server-quickstart.md) - 5-minute tutorial +- [Web Server Examples](../examples/web-servers/) - Organized examples by complexity - Test programs in `TestPrograms/` - Working code examples --- diff --git a/README.md b/README.md index 4bf0ac6f..9bfcbe68 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ end count - **🚀 Modern Async Support**: Built-in async/await for concurrent operations - **🛡️ Type Safety**: Static type checking with intelligent inference - **🌐 Web-First Design**: Native HTTP and database support +- **🌍 Built-in Web Server**: Create HTTP servers with `listen on port 8080` - no external frameworks needed +- **📂 File Serving Made Simple**: Read files and serve them with natural syntax like `respond to request with content` - **🎨 Developer Experience**: Comprehensive tooling and real-time error checking - **♻️ Backward Compatibility**: Your code will always work with future versions @@ -136,6 +138,42 @@ Run it: wfl hello.wfl ``` +### Your First Web Server + +WFL makes creating web servers incredibly simple. Create `server.wfl`: + +```wfl +// Start a web server on port 8080 +listen on port 8080 as web_server + +display "Server running at http://127.0.0.1:8080" + +// Handle incoming requests +wait for request comes in on web_server as req + +check if path is equal to "/": + respond to req with "Hello from WFL Web Server!" +check if path is equal to "/file": + // Read a file and serve its contents + try: + open file at "welcome.txt" for reading as file + store content as read content from file + close file + respond to req with content and content_type "text/plain" + catch: + respond to req with "File not found" and status 404 + end try +otherwise: + respond to req with "Page not found" and status 404 +end check +``` + +Run it and visit `http://127.0.0.1:8080` in your browser! + +```bash +wfl server.wfl +``` + ## 📚 Language Overview ### Variables and Types