-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
156 lines (128 loc) · 5.27 KB
/
main.go
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package main
import (
"encoding/json"
"html/template"
"log"
"net/http"
"os"
"path"
"strings"
"sync"
"github.com/gorilla/csrf"
)
// Global CSRF protection key
var csrfKey = []byte("AXEFQ3J45TOP6912WMHHFKDV63DPIN7S") // 32 bytes
// Template rendering function
var tmpl *template.Template
var (
AvailableTemplates []string
mu sync.Mutex
)
func init() {
// Parse your resume.html template once and reuse it.
tmpl = template.Must(template.ParseFiles("./static/resume.html"))
}
func main() {
// Set up the CSRF protection middleware with the secret key
CSRF := csrf.Protect(csrfKey,
csrf.Secure(false), // Set to true in production (for HTTPS)
csrf.HttpOnly(true), // Makes CSRF token cookie HTTP-only
csrf.Path("/"), // Cookie path
csrf.MaxAge(3600), // Set CSRF cookie expiry to 1 hour
csrf.ErrorHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Forbidden - CSRF token invalid or missing", http.StatusForbidden)
})),
)
// Define API routes first
http.HandleFunc("/resume", renderResumeForm)
// Serve static files last
http.HandleFunc("/", serveFile)
http.HandleFunc("/submitResume", handleFormSubmission)
http.HandleFunc("/availableTemplates", fetchAvailableTemplates)
log.Println("Server started on :8080")
errs := http.ListenAndServe(":8080", CSRF(http.DefaultServeMux))
if errs != nil {
log.Fatal("Listen-And-Serve: ", errs)
}
log.Println("For Application, go to http://localhost:8080/resume")
}
// Render the resume form with the CSRF token embedded
func renderResumeForm(w http.ResponseWriter, r *http.Request) {
// Pass CSRF token to template
data := map[string]interface{}{
"csrfField": csrf.TemplateField(r),
}
err := tmpl.Execute(w, data)
if err != nil {
http.Error(w, "Error rendering template", http.StatusInternalServerError)
}
}
// Custom file server to handle requests
func serveFile(w http.ResponseWriter, r *http.Request) {
log.Printf("Request Path: %s", r.URL.Path) // Log the request path
// Check if the request is for an HTML file
if strings.HasSuffix(r.URL.Path, ".html") {
// Remove the .html extension and redirect
openQuery := r.URL.Query().Get("open") // Get the 'open' query parameter
if openQuery == "true" && r.Header.Get("X-Requested-With") == "XMLHttpRequest"{
if strings.HasPrefix(r.URL.Path, "/layout/"){
filePath := path.Join("./static", r.URL.Path)
log.Printf("Checking file path: %s", filePath) // Log the resolved file path
// Check if the requested layout file exists
if _, err := os.Stat(filePath); os.IsNotExist(err) {
log.Printf("File not found: %s", filePath)
http.ServeFile(w, r, "./static/404.html")
return
}
// Serve the file if it exists
http.ServeFile(w, r, filePath)
return
}
}
newPath := strings.TrimSuffix(r.URL.Path, ".html")
http.Redirect(w, r, newPath, http.StatusMovedPermanently)
return
}
// Prevent directory listing
if r.URL.Path == "/" {
http.ServeFile(w, r, "./static/NotAllowed.html")
return
}
// Serve files without revealing the directory structure
filePath := path.Join("./static", r.URL.Path)
// Use os.Stat to check if the requested file exists
if _, err := os.Stat(filePath); os.IsNotExist(err) {
log.Printf("File not found: %s", filePath) // Log if file is not found
http.ServeFile(w, r, "./static/404.html") // Ensure the path matches where your 404.html is located
return
}
http.ServeFile(w, r, filePath)
}
// Fetch available templates from a text file
func fetchAvailableTemplates(w http.ResponseWriter, r *http.Request) {
// Check if the request is likely coming from a browser
if strings.Contains(r.Header.Get("Accept"), "text/html") {
http.ServeFile(w, r, "./static/404.html") // Serve your custom 404 page
return
}
w.Header().Set("Content-Type", "application/json")
// Locking to avoid race conditions during concurrent access
mu.Lock()
defer mu.Unlock()
// Debug: Log incoming request
log.Printf("Received request for available templates")
if len(AvailableTemplates) == 0 {
var err error
AvailableTemplates, err = LoadAvailableTemplates("./static/templates")
if err != nil {
log.Printf("Error loading templates: %v", err)
http.Error(w, "Failed to load templates", http.StatusInternalServerError)
return
}
}
// Send the templates as JSON response
if err := json.NewEncoder(w).Encode(AvailableTemplates); err != nil {
log.Printf("Error encoding templates: %v", err)
http.Error(w, "Failed to encode templates", http.StatusInternalServerError)
}
}