Last active
June 18, 2025 11:05
-
-
Save vadviktor/6273e4afd1753b6bf48974e55aee9836 to your computer and use it in GitHub Desktop.
Go stdlib http server with api and embedded SPA (e.g. React)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"embed" | |
"encoding/json" | |
"fmt" | |
"io" | |
"io/fs" | |
"log" | |
"net/http" | |
) | |
//go:embed static | |
var staticFiles embed.FS | |
type CreateRequest struct { | |
Name string `json:"name"` | |
} | |
type APIResponse struct { | |
Message string `json:"message"` | |
} | |
type CreateResponse struct { | |
Created string `json:"created"` | |
} | |
func main() { | |
mux := http.NewServeMux() | |
// Serve static files from embedded FS at root | |
// Since we embedded "static", we need to serve from the "static" subdirectory | |
staticFS, err := http.FS(staticFiles).Open("static") | |
if err != nil { | |
log.Fatal("Failed to open static directory:", err) | |
} | |
staticFS.Close() | |
// Create a sub filesystem that serves from the static directory | |
subFS, err := fs.Sub(staticFiles, "static") | |
if err != nil { | |
log.Fatal("Failed to create sub filesystem:", err) | |
} | |
staticHandler := http.FileServer(http.FS(subFS)) | |
mux.Handle("/", staticHandler) | |
// API endpoint that returns JSON | |
mux.HandleFunc("GET /api", func(w http.ResponseWriter, r *http.Request) { | |
w.Header().Set("Content-Type", "application/json") | |
response := APIResponse{Message: "hello from api"} | |
json.NewEncoder(w).Encode(response) | |
}) | |
// POST endpoint for creating | |
mux.HandleFunc("POST /api/create", func(w http.ResponseWriter, r *http.Request) { | |
w.Header().Set("Content-Type", "application/json") | |
body, err := io.ReadAll(r.Body) | |
if err != nil { | |
http.Error(w, "Failed to read request body", http.StatusBadRequest) | |
return | |
} | |
defer r.Body.Close() | |
var req CreateRequest | |
if err := json.Unmarshal(body, &req); err != nil { | |
http.Error(w, "Invalid JSON", http.StatusBadRequest) | |
return | |
} | |
// Log the received name for debugging | |
log.Printf("Received create request for: %s", req.Name) | |
response := CreateResponse{Created: "ok"} | |
json.NewEncoder(w).Encode(response) | |
}) | |
fmt.Println("Server starting on port 16000...") | |
fmt.Println("Static files served from: /") | |
fmt.Println("API endpoint: GET /api") | |
fmt.Println("Create endpoint: POST /api/create") | |
log.Fatal(http.ListenAndServe(":16000", mux)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment