-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.go
More file actions
139 lines (116 loc) · 4.22 KB
/
Copy pathserver.go
File metadata and controls
139 lines (116 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"html/template"
"log"
"net/http"
"os"
"time"
"strings"
"github.com/gorilla/mux"
)
func main() {
StartServer()
}
func StartServer() {
router := buildRouter()
port := getenv("PORT", "9999")
server := &http.Server{
Addr: ":" + port,
Handler: router,
ReadTimeout: 40 * time.Second,
WriteTimeout: 300 * time.Second,
}
log.Printf("Splitifly web server listening at port %v", server.Addr)
err := server.ListenAndServe()
if err != nil {
log.Println("Unexpected error initiliazing Splitifly web server: ", err)
}
}
func getenv(key, fallback string) string {
value := os.Getenv(key)
if len(value) == 0 {
return fallback
}
return value
}
func buildRouter() *mux.Router {
router := mux.NewRouter()
router.NotFoundHandler = http.HandlerFunc(NoMatchingHandler)
// tratamiento especial para el service worker pues tiene que tener header Service-Worker-Allowed
router.HandleFunc("/assets/js/service-worker.js", ServeServiceWorker).Methods("GET")
fileServer := http.FileServer(http.Dir("./assets"))
//router.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", fileServer))
router.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Serving static file:", r.URL.Path)
// workaround for : https://github.com/microsoft/TypeScript/issues/27287#issuecomment-2679347081
if len(r.URL.Path) > 3 && r.URL.Path[:3] == "js/" && !strings.HasSuffix(r.URL.Path, ".js") {
r.URL.Path += ".js"
log.Println("Adjusted path to:", r.URL.Path)
}
fileServer.ServeHTTP(w, r)
})))
// Rutas públicas con CORS
router.HandleFunc("/healthcheck", addCORS(Healthcheck)).Methods("GET", "OPTIONS")
router.HandleFunc("/version", addCORS(Version)).Methods("GET", "OPTIONS")
// Ruta raíz para el index.html
router.HandleFunc("/", serveRoot).Methods("GET")
// Ruta standalone para el about (crawleable por bots de búsqueda y AdSense).
// En la app se sigue cargando como modal vía fetch desde el index.
router.HandleFunc("/about", serveAbout).Methods("GET")
// El service worker pre-cachea "/assets/html/index.html" (la ruta real del archivo),
// pero la app sirve el index desde "/" via serveRoot. Sin esta ruta, cuando el SW
// pide /assets/html/index.html al server para cachearla, el file server la devuelve
// como archivo estático sin el tratamiento de serveRoot. Mapeando ambas rutas al
// mismo handler garantizamos que el contenido cacheado por el SW sea idéntico al
// que se sirve en "/".
router.HandleFunc("/assets/html/index.html", serveRoot).Methods("GET")
return router
}
func ServeServiceWorker(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Service-Worker-Allowed", "/")
http.ServeFile(w, r, "./assets/js/service-worker.js")
}
// Helper function para añadir headers CORS
func addCORS(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
next(w, r)
}
}
func NoMatchingHandler(response http.ResponseWriter, request *http.Request) {
if request.URL.Path != "/favicon.ico" { // don't log this
log.Println("No maching route for " + request.URL.Path)
}
response.WriteHeader(http.StatusNotFound)
}
func serveRoot(response http.ResponseWriter, request *http.Request) {
t, err := template.ParseFiles("./assets/html/index.html")
if err != nil {
log.Printf("Error while parsing template : %v", err)
response.WriteHeader(http.StatusInternalServerError)
return
}
t.Execute(response, nil)
}
func serveAbout(response http.ResponseWriter, request *http.Request) {
t, err := template.ParseFiles("./assets/html/about.html")
if err != nil {
log.Printf("Error while parsing template : %v", err)
response.WriteHeader(http.StatusInternalServerError)
return
}
t.Execute(response, nil)
}
func Healthcheck(response http.ResponseWriter, request *http.Request) {
response.WriteHeader(http.StatusOK)
}
const ServerVersion = "0.0.1"
func Version(response http.ResponseWriter, request *http.Request) {
response.WriteHeader(http.StatusOK)
response.Write([]byte(ServerVersion))
}