From ffc705ec8ba99c9986becff9b2cd9690207a31e3 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sat, 29 Feb 2020 16:53:08 -0700 Subject: [PATCH] check in other important files --- cmd/mothd/httpd.go | 99 ++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 8 ++++ go.sum | 6 +++ jsend/jsend.go | 39 ++++++++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 cmd/mothd/httpd.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 jsend/jsend.go diff --git a/cmd/mothd/httpd.go b/cmd/mothd/httpd.go new file mode 100644 index 0000000..b2315db --- /dev/null +++ b/cmd/mothd/httpd.go @@ -0,0 +1,99 @@ +package main + +import ( + "net/http" + "log" + "strings" + "github.com/dirtbags/moth/jsend" +) + +type HTTPServer struct { + PuzzleProvider + ThemeProvider + StateProvider + *http.ServeMux +} + +func NewHTTPServer(base string, theme ThemeProvider, state StateProvider, puzzles PuzzleProvider) (*HTTPServer) { + h := &HTTPServer{ + ThemeProvider: theme, + StateProvider: state, + PuzzleProvider: puzzles, + ServeMux: http.NewServeMux(), + } + h.HandleFunc(base+"/", h.ThemeHandler) + h.HandleFunc(base+"/state", h.StateHandler) + h.HandleFunc(base+"/register", h.RegisterHandler) + h.HandleFunc(base+"/answer", h.AnswerHandler) + h.HandleFunc(base+"/content/", h.ContentHandler) + return h +} + + +func (h *HTTPServer) Run(bindStr string) { + log.Printf("Listening on %s", bindStr) + log.Fatal(http.ListenAndServe(bindStr, h)) +} + +type MothResponseWriter struct { + statusCode *int + http.ResponseWriter +} + +func (w MothResponseWriter) WriteHeader(statusCode int) { + *w.statusCode = statusCode + w.ResponseWriter.WriteHeader(statusCode) +} + +// This gives Instances the signature of http.Handler +func (h *HTTPServer) ServeHTTP(wOrig http.ResponseWriter, r *http.Request) { + w := MothResponseWriter{ + statusCode: new(int), + ResponseWriter: wOrig, + } + h.ServeMux.ServeHTTP(w, r) + log.Printf( + "%s %s %s %d\n", + r.RemoteAddr, + r.Method, + r.URL, + *w.statusCode, + ) +} + +func (h *HTTPServer) ThemeHandler(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path + if strings.Contains(path, "..") { + http.Error(w, "Invalid URL path", http.StatusBadRequest) + return + } + if path == "/" { + path = "/index.html" + } + + f, err := h.ThemeProvider.Open(path) + if err != nil { + http.NotFound(w, req) + return + } + defer f.Close() + mtime, _ := h.ThemeProvider.ModTime(path) + http.ServeContent(w, req, path, mtime, f) +} + + +func (h *HTTPServer) StateHandler(w http.ResponseWriter, req *http.Request) { + jsend.Write(w, jsend.Fail, "unimplemented", "I haven't written this yet") +} + +func (h *HTTPServer) RegisterHandler(w http.ResponseWriter, req *http.Request) { + jsend.Write(w, jsend.Fail, "unimplemented", "I haven't written this yet") +} + +func (h *HTTPServer) AnswerHandler(w http.ResponseWriter, req *http.Request) { + jsend.Write(w, jsend.Fail, "unimplemented", "I haven't written this yet") +} + +func (h *HTTPServer) ContentHandler(w http.ResponseWriter, req *http.Request) { + jsend.Write(w, jsend.Fail, "unimplemented", "I haven't written this yet") +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fe6b061 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/dirtbags/moth + +go 1.13 + +require ( + github.com/namsral/flag v1.7.4-pre + github.com/spf13/afero v1.2.2 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..f0f321c --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +github.com/namsral/flag v1.7.4-pre h1:b2ScHhoCUkbsq0d2C15Mv+VU8bl8hAXV8arnWiOHNZs= +github.com/namsral/flag v1.7.4-pre/go.mod h1:OXldTctbM6SWH1K899kPZcf65KxJiD7MsceFUpB5yDo= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/jsend/jsend.go b/jsend/jsend.go new file mode 100644 index 0000000..6027d7f --- /dev/null +++ b/jsend/jsend.go @@ -0,0 +1,39 @@ +package jsend + +import ( + "encoding/json" + "fmt" + "net/http" +) + +// This provides a JSend function for MOTH +// https://github.com/omniti-labs/jsend + +const ( + Success = "success" + Fail = "fail" + Error = "error" +) + +func Write(w http.ResponseWriter, status, short string, format string, a ...interface{}) { + resp := struct{ + Status string `json:"status"` + Data struct { + Short string `json:"short"` + Description string `json:"description"` + } `json:"data"` + }{} + resp.Status = status + resp.Data.Short = short + resp.Data.Description = fmt.Sprintf(format, a...) + + respBytes, err := json.Marshal(resp) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) // RFC2616 makes it pretty clear that 4xx codes are for the user-agent + w.Write(respBytes) +}