initial page
This commit is contained in:
114
main.go
Normal file
114
main.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/moh682/portfolio/components"
|
||||
"github.com/moh682/portfolio/domain"
|
||||
"github.com/moh682/portfolio/middlewares"
|
||||
)
|
||||
|
||||
func templHandlerWithOptions(component templ.Component) http.Handler {
|
||||
t := templ.Handler(component, templ.WithStatus(200), templ.WithContentType("text/html"))
|
||||
|
||||
log.Println("templHandlerWithOptions: ", t.Status)
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func rootHandler(handler http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
handler.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// SafeFileServer wraps http.FileServer to only serve specific file types from specific directories
|
||||
func SafeFileServer(root http.FileSystem) http.Handler {
|
||||
fileServer := http.FileServer(root)
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Set security headers
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.Header().Set("X-Frame-Options", "DENY")
|
||||
w.Header().Set("X-XSS-Protection", "1; mode=block")
|
||||
|
||||
log.Println("path", r.URL.Path)
|
||||
|
||||
// Only allow specific file extensions
|
||||
if allowed := func(path string) bool {
|
||||
allowedExts := map[string]bool{
|
||||
".js": true,
|
||||
".css": true,
|
||||
".png": true,
|
||||
".jpg": true,
|
||||
".jpeg": true,
|
||||
".svg": true,
|
||||
".ico": true,
|
||||
}
|
||||
for ext := range allowedExts {
|
||||
if strings.HasSuffix(path, ext) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}(r.URL.Path); !allowed {
|
||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
//go:embed assets/json/experiences.json
|
||||
var embeddedExperiences []byte
|
||||
|
||||
//go:embed assets/json/projects.json
|
||||
var embeddedProjects []byte
|
||||
|
||||
func main() {
|
||||
server := http.NewServeMux()
|
||||
|
||||
// Serve static files with restrictions
|
||||
staticFS := http.Dir("static")
|
||||
server.Handle("GET /assets/", http.StripPrefix("/assets/", SafeFileServer(staticFS)))
|
||||
|
||||
server.Handle("GET /about", templHandlerWithOptions(components.AboutPage()))
|
||||
|
||||
var exps []domain.Experience
|
||||
err := json.Unmarshal(embeddedExperiences, &exps)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
server.Handle("GET /experiences", templHandlerWithOptions(components.ExperiencesPage(exps)))
|
||||
|
||||
var projects []domain.Project
|
||||
err = json.Unmarshal(embeddedProjects, &projects)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
server.Handle("GET /projects", templHandlerWithOptions(components.ProjectsPage(projects)))
|
||||
|
||||
server.Handle("GET /contact", templHandlerWithOptions(components.ContactPage()))
|
||||
server.Handle("GET /{$}", templHandlerWithOptions(components.LandingPage()))
|
||||
|
||||
// 404 fallback page
|
||||
server.Handle("GET /", templHandlerWithOptions(components.NotFound()))
|
||||
|
||||
// TODO: add Blogs to my portfolio website
|
||||
// server.Handle("GET /blogs", templHandlerWithOptions(components.AboutPage()))
|
||||
|
||||
fmt.Println("Listening on :8080")
|
||||
log.Panic(
|
||||
http.ListenAndServe(":8080",
|
||||
middlewares.Combine(
|
||||
middlewares.Logger(server),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user