From 790f62dd2a54fb954a64304392d74a087cb45698 Mon Sep 17 00:00:00 2001 From: Thomas Grothe Date: Mon, 22 Dec 2025 23:39:04 -0500 Subject: go webserver written by claude --- go_server_readme.md | 172 ++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 81 +++++++++++++++++++++++++ server_readme.md | 124 +++++++++++++++++++++++++++++++++++++ 3 files changed, 377 insertions(+) create mode 100644 go_server_readme.md create mode 100644 main.go create mode 100644 server_readme.md diff --git a/go_server_readme.md b/go_server_readme.md new file mode 100644 index 0000000..1caa361 --- /dev/null +++ b/go_server_readme.md @@ -0,0 +1,172 @@ +# Go Web Server for Simple Website + +This is a simple, expandable Go web server designed to serve a static website with HTML, CSS, and JavaScript files. The server is designed to be easily expanded with new routes and functionality. + +## Setup Instructions + +### Prerequisites +- Go 1.15 or higher + +### Installation + +No additional installation is required beyond having Go installed. + +### Running the Server + +1. Start the Go server: + ``` + go run main.go + ``` + + Options: + - `--port=8080` - Change the port (default: 5000) + - `--debug=false` - Disable debug mode + +2. Access the website at [http://localhost:5000](http://localhost:5000) + +## Project Structure + +- `main.go` - The main Go web server +- `index.html` - Main HTML file +- `css/` - CSS stylesheets +- `js/` - JavaScript files + +## How to Expand the Server + +### Adding New Routes + +To add a new route, add a handler function in the `main.go` file: + +```go +http.HandleFunc("/new-route", func(w http.ResponseWriter, r *http.Request) { + // Your handler code here + fmt.Fprintf(w, "This is a new route") +}) +``` + +### Adding API Endpoints + +For JSON APIs, add a route that returns a JSON response: + +```go +http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) { + data := map[string]interface{}{ + "key": "value", + "items": []int{1, 2, 3}, + } + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(data) +}) +``` + +### Adding Database Support + +To add a database, you can use one of Go's database packages: + +1. Add the necessary imports: + ```go + import ( + "database/sql" + _ "github.com/mattn/go-sqlite3" // For SQLite + ) + ``` + +2. Create a database connection: + ```go + db, err := sql.Open("sqlite3", "./database.db") + if err != nil { + log.Fatal(err) + } + defer db.Close() + ``` + +3. Use the database in your handlers: + ```go + http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) { + rows, err := db.Query("SELECT id, name FROM users") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer rows.Close() + + var users []map[string]interface{} + for rows.Next() { + var id int + var name string + rows.Scan(&id, &name) + users = append(users, map[string]interface{}{ + "id": id, + "name": name, + }) + } + + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(users) + }) + ``` + +### Adding User Authentication + +For user authentication, you can use middleware: + +1. Create an authentication middleware: + ```go + func authMiddleware(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("Authorization") + // Validate token + if token == "" { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + // Call the next handler + next(w, r) + } + } + ``` + +2. Use the middleware with your handlers: + ```go + http.HandleFunc("/api/protected", authMiddleware(func(w http.ResponseWriter, r *http.Request) { + // Protected route logic + })) + ``` + +### Environment Variables + +The server passes environment variables to the frontend. To add new environment variables: + +1. Update the `EnvVars` struct in `main.go`: + ```go + type EnvVars struct { + Thing int `json:"thing"` + ApiUrl string `json:"apiUrl"` + NewVar string `json:"newVariable"` + } + ``` + +2. Update the `getEnvVars` function: + ```go + func getEnvVars() EnvVars { + return EnvVars{ + Thing: 1, + ApiUrl: "http://api.example.com", + NewVar: "value", + } + } + ``` + +## Production Deployment + +For production deployment, consider: + +1. Building a binary: + ``` + go build -o server main.go + ./server --port=8080 --debug=false + ``` + +2. Setting up a proper web server like Nginx as a reverse proxy +3. Using environment variables for configuration +4. Implementing proper logging and monitoring diff --git a/main.go b/main.go new file mode 100644 index 0000000..80a3583 --- /dev/null +++ b/main.go @@ -0,0 +1,81 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "log" + "net/http" + "os" +) + +// Configuration for the server +type Config struct { + Debug bool + Port int +} + +// Environment variables to pass to frontend +type EnvVars struct { + Thing int `json:"thing"` + // Add more environment variables as needed +} + +// Get environment variables to pass to frontend +func getEnvVars() EnvVars { + return EnvVars{ + Thing: 1, + // Add more variables as needed + } +} + +func main() { + // Parse command line flags + config := Config{} + flag.IntVar(&config.Port, "port", 5000, "Port to run the server on") + flag.BoolVar(&config.Debug, "debug", true, "Enable debug mode") + flag.Parse() + + // Override port from environment variable if set + if portStr := os.Getenv("PORT"); portStr != "" { + var err error + config.Port, err = fmt.Sscanf(portStr, "%d", &config.Port) + if err != nil { + log.Printf("Warning: Invalid PORT environment variable: %s. Using default port %d", portStr, config.Port) + } + } + + // Create a file server for static files + fs := http.FileServer(http.Dir(".")) + + // Set up routes + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + // If the request is for the root path, serve index.html + if r.URL.Path == "/" { + http.ServeFile(w, r, "index.html") + return + } + // Otherwise, use the file server to serve static files + fs.ServeHTTP(w, r) + }) + + // API routes + http.HandleFunc("/api/env", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(getEnvVars()) + }) + + http.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + json.NewEncoder(w).Encode(map[string]string{"status": "ok"}) + }) + + // Error handlers are handled by default Go error handling + + // Start the server + addr := fmt.Sprintf(":%d", config.Port) + log.Printf("Starting server at http://localhost%s", addr) + if err := http.ListenAndServe(addr, nil); err != nil { + log.Fatalf("Server error: %v", err) + } +} diff --git a/server_readme.md b/server_readme.md new file mode 100644 index 0000000..69cfe53 --- /dev/null +++ b/server_readme.md @@ -0,0 +1,124 @@ +# Flask Web Server for Simple Website + +This is a simple, expandable Flask web server designed to serve a static website with HTML, CSS, and JavaScript files. The server is designed to be easily expanded with new routes and functionality. + +## Setup Instructions + +### Prerequisites +- Python 3.6 or higher +- pip (Python package manager) + +### Installation + +1. Install required packages: + ``` + pip install -r requirements.txt + ``` + +### Running the Server + +1. Start the Flask development server: + ``` + python app.py + ``` + +2. Access the website at [http://localhost:5000](http://localhost:5000) + +## Project Structure + +- `app.py` - The main Flask application +- `requirements.txt` - Python dependencies +- `index.html` - Main HTML file +- `css/` - CSS stylesheets +- `js/` - JavaScript files + +## How to Expand the Server + +### Adding New Routes + +To add a new page or API endpoint, add a route to `app.py`: + +```python +@app.route('/new-page') +def new_page(): + return send_from_directory('.', 'new-page.html') +``` + +### Adding API Endpoints + +For JSON APIs, add a route that returns a JSON response: + +```python +@app.route('/api/data') +def api_data(): + data = { + 'key': 'value', + 'items': [1, 2, 3] + } + return jsonify(data) +``` + +### Adding Database Support + +To add a database, you can use Flask-SQLAlchemy: + +1. Install Flask-SQLAlchemy: + ``` + pip install Flask-SQLAlchemy + ``` + +2. Update your `app.py` to include database configuration: + ```python + from flask_sqlalchemy import SQLAlchemy + + app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' + db = SQLAlchemy(app) + + class User(db.Model): + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(80), unique=True, nullable=False) + ``` + +### Adding User Authentication + +For user authentication, you can use Flask-Login: + +1. Install Flask-Login: + ``` + pip install Flask-Login + ``` + +2. Configure it in your application: + ```python + from flask_login import LoginManager, UserMixin + + login_manager = LoginManager(app) + login_manager.login_view = 'login' + ``` + +### Environment Variables + +The server passes environment variables to the frontend. To add new environment variables: + +1. Update the `get_env_vars()` function in `app.py`: + ```python + def get_env_vars(): + return { + 'thing': 1, + 'apiUrl': 'http://api.example.com', + 'newVariable': 'value' + } + ``` + +## Production Deployment + +For production deployment, consider: + +1. Using a WSGI server like Gunicorn: + ``` + pip install gunicorn + gunicorn -w 4 -b 0.0.0.0:5000 app:app + ``` + +2. Setting up a proper web server like Nginx as a reverse proxy +3. Setting environment variables for production configuration -- cgit v1.2.3