-
-
Notifications
You must be signed in to change notification settings - Fork 343
/
route.go
127 lines (111 loc) · 3.95 KB
/
route.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
package route
import (
"net/http"
"time"
"github.com/RichardKnop/machinery/v1"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
"github.com/go-redis/redis/v8"
"github.com/jmoiron/sqlx"
log "github.com/sirupsen/logrus"
"os"
"path/filepath"
"github.com/jordanknott/taskcafe/internal/config"
"github.com/jordanknott/taskcafe/internal/db"
"github.com/jordanknott/taskcafe/internal/frontend"
"github.com/jordanknott/taskcafe/internal/graph"
"github.com/jordanknott/taskcafe/internal/jobs"
"github.com/jordanknott/taskcafe/internal/logger"
)
// FrontendHandler serves an embed React client through chi
type FrontendHandler struct {
staticPath string
indexPath string
}
// IsDir checks if the given file is a directory
func IsDir(f http.File) bool {
fi, err := f.Stat()
if err != nil {
return false
}
return fi.IsDir()
}
// ServeHTTP attempts to serve a requested file for the embedded React client
func (h FrontendHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path, err := filepath.Abs(r.URL.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
f, err := frontend.Frontend.Open(path)
if os.IsNotExist(err) || IsDir(f) {
index, err := frontend.Frontend.Open("index.html")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.ServeContent(w, r, "index.html", time.Now(), index)
return
} else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.ServeContent(w, r, path, time.Now(), f)
}
// TaskcafeHandler contains all the route handlers
type TaskcafeHandler struct {
repo db.Repository
AppConfig config.AppConfig
}
// NewRouter creates a new router for chi
func NewRouter(dbConnection *sqlx.DB, redisClient *redis.Client, jobServer *machinery.Server, appConfig config.AppConfig) (chi.Router, error) {
formatter := new(log.TextFormatter)
formatter.TimestampFormat = "02-01-2006 15:04:05"
formatter.FullTimestamp = true
routerLogger := log.New()
routerLogger.SetLevel(log.InfoLevel)
routerLogger.Formatter = formatter
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.RealIP)
r.Use(logger.NewStructuredLogger(routerLogger))
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
r.Use(cors.Handler(cors.Options{
// AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts
AllowedOrigins: []string{"https://*", "http://*"},
// AllowOriginFunc: func(r *http.Request, origin string) bool { return true },
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Authorization", "Cookie", "Content-Type", "X-CSRF-Token"},
ExposedHeaders: []string{"Link"},
AllowCredentials: true,
MaxAge: 300, // Maximum value not ignored by any of major browsers
}))
repository := db.NewRepository(dbConnection)
taskcafeHandler := TaskcafeHandler{*repository, appConfig}
var imgServer = http.FileServer(http.Dir("./uploads/"))
r.Group(func(mux chi.Router) {
mux.Mount("/auth", authResource{}.Routes(taskcafeHandler))
mux.Handle("/__graphql", graph.NewPlaygroundHandler("/graphql"))
mux.Mount("/uploads/", http.StripPrefix("/uploads/", imgServer))
mux.Post("/auth/confirm", taskcafeHandler.ConfirmUser)
mux.Post("/auth/register", taskcafeHandler.RegisterUser)
mux.Get("/settings", taskcafeHandler.PublicSettings)
mux.Post("/logger", taskcafeHandler.HandleClientLog)
})
auth := AuthenticationMiddleware{*repository}
jobQueue := jobs.JobQueue{
Repository: *repository,
AppConfig: appConfig,
Server: jobServer,
}
r.Group(func(mux chi.Router) {
mux.Use(auth.Middleware)
mux.Post("/users/me/avatar", taskcafeHandler.ProfileImageUpload)
mux.Mount("/graphql", graph.NewHandler(*repository, appConfig, jobQueue, redisClient))
})
frontend := FrontendHandler{staticPath: "build", indexPath: "index.html"}
r.Handle("/*", frontend)
return r, nil
}