Clean up http handling

This commit is contained in:
Ian Kent 2014-04-20 19:49:05 +01:00
parent 2a0e49fda9
commit 9a6426f359
3 changed files with 121 additions and 39 deletions

58
mailhog/http/api/v1.go Normal file
View file

@ -0,0 +1,58 @@
package api
import (
"log"
"encoding/json"
"net/http"
"regexp"
"github.com/ian-kent/MailHog/mailhog"
"github.com/ian-kent/MailHog/mailhog/storage"
"github.com/ian-kent/MailHog/mailhog/http/handler"
)
type APIv1 struct {
config *mailhog.Config
exitChannel chan int
server *http.Server
}
func CreateAPIv1(exitCh chan int, conf *mailhog.Config, server *http.Server) *APIv1 {
log.Println("Creating API v1")
apiv1 := &APIv1{
config: conf,
exitChannel: exitCh,
server: server,
}
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/api/v1/messages$"), apiv1.messages)
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/api/v1/messages/delete$"), apiv1.delete_all)
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/api/v1/messages/([0-9a-f]+)/delete$"), apiv1.delete_one)
return apiv1
}
func (apiv1 *APIv1) messages(w http.ResponseWriter, r *http.Request, route *handler.Route) {
log.Println("[APIv1] GET /api/v1/messages")
// TODO start, limit
messages, _ := storage.List(apiv1.config, 0, 1000)
bytes, _ := json.Marshal(messages)
w.Header().Set("Content-Type", "text/json")
w.Write(bytes)
}
func (apiv1 *APIv1) delete_all(w http.ResponseWriter, r *http.Request, route *handler.Route) {
log.Println("[APIv1] POST /api/v1/messages/delete")
w.Header().Set("Content-Type", "text/json")
storage.DeleteAll(apiv1.config)
}
func (apiv1 *APIv1) delete_one(w http.ResponseWriter, r *http.Request, route *handler.Route) {
match := route.Pattern.FindStringSubmatch(r.URL.Path)
id := match[1]
log.Printf("[APIv1] POST /api/v1/messages/%s/delete\n", id)
w.Header().Set("Content-Type", "text/json")
storage.DeleteOne(apiv1.config, id)
}

View file

@ -0,0 +1,43 @@
package handler;
import (
"regexp"
"net/http"
)
// http://stackoverflow.com/questions/6564558/wildcards-in-the-pattern-for-http-handlefunc
type Route struct {
Pattern *regexp.Regexp
Handler HandlerFunc
}
type HandlerFunc func(http.ResponseWriter, *http.Request, *Route)
//type Handler http.Handler
func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request, route *Route) {
f(w, r, route)
}
type RegexpHandler struct {
routes []*Route
}
func (h *RegexpHandler) Handler(pattern *regexp.Regexp, handler HandlerFunc) {
h.routes = append(h.routes, &Route{pattern, handler})
}
func (h *RegexpHandler) HandleFunc(pattern *regexp.Regexp, handler func(http.ResponseWriter, *http.Request, *Route)) {
h.routes = append(h.routes, &Route{pattern, HandlerFunc(handler)})
}
func (h *RegexpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for _, route := range h.routes {
if route.Pattern.MatchString(r.URL.Path) {
route.Handler.ServeHTTP(w, r, route)
return
}
}
// no pattern matched; send 404 response
http.NotFound(w, r)
}

View file

@ -1,36 +1,36 @@
package http
import (
"encoding/json"
"net/http"
"regexp"
"net/http"
"github.com/ian-kent/MailHog/mailhog"
"github.com/ian-kent/MailHog/mailhog/templates"
"github.com/ian-kent/MailHog/mailhog/storage"
"github.com/ian-kent/MailHog/mailhog/templates/images"
"github.com/ian-kent/MailHog/mailhog/templates/js"
"github.com/ian-kent/MailHog/mailhog/http/api"
"github.com/ian-kent/MailHog/mailhog/http/handler"
)
var exitChannel chan int
var config *mailhog.Config
func web_exit(w http.ResponseWriter, r *http.Request) {
func web_exit(w http.ResponseWriter, r *http.Request, route *handler.Route) {
web_headers(w)
w.Write([]byte("Exiting MailHog!"))
exitChannel <- 1
}
func web_index(w http.ResponseWriter, r *http.Request) {
func web_index(w http.ResponseWriter, r *http.Request, route *handler.Route) {
web_headers(w)
w.Write([]byte(web_render(templates.Index())))
}
func web_jscontroller(w http.ResponseWriter, r *http.Request) {
func web_jscontroller(w http.ResponseWriter, r *http.Request, route *handler.Route) {
w.Header().Set("Content-Type", "text/javascript")
w.Write([]byte(js.Controllers()))
}
func web_imgcontroller(w http.ResponseWriter, r *http.Request) {
func web_imgcontroller(w http.ResponseWriter, r *http.Request, route *handler.Route) {
w.Header().Set("Content-Type", "image/png")
w.Write(images.Hog())
}
@ -43,40 +43,21 @@ func web_headers(w http.ResponseWriter) {
w.Header().Set("Content-Type", "text/html")
}
func api_messages(w http.ResponseWriter, r *http.Request) {
re, _ := regexp.Compile("/api/v1/messages/([0-9a-f]+)/delete")
match := re.FindStringSubmatch(r.URL.Path)
if len(match) > 0 {
api_delete_one(w, r, match[1])
return
}
// TODO start, limit
messages, _ := storage.List(config, 0, 1000)
bytes, _ := json.Marshal(messages)
w.Header().Set("Content-Type", "text/json")
w.Write(bytes)
}
func api_delete_all(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/json")
storage.DeleteAll(config)
}
func api_delete_one(w http.ResponseWriter, r *http.Request, id string) {
w.Header().Set("Content-Type", "text/json")
storage.DeleteOne(config, id)
}
func Start(exitCh chan int, conf *mailhog.Config) {
exitChannel = exitCh
config = conf
http.HandleFunc("/exit", web_exit)
http.HandleFunc("/js/controllers.js", web_jscontroller)
http.HandleFunc("/images/hog.png", web_imgcontroller)
http.HandleFunc("/", web_index)
http.HandleFunc("/api/v1/messages/", api_messages)
http.HandleFunc("/api/v1/messages/delete", api_delete_all)
http.ListenAndServe(conf.HTTPBindAddr, nil)
server := &http.Server{
Addr: conf.HTTPBindAddr,
Handler: &handler.RegexpHandler{},
}
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/exit$"), web_exit)
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/js/controllers.js$"), web_jscontroller)
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/images/hog.png$"), web_imgcontroller)
server.Handler.(*handler.RegexpHandler).HandleFunc(regexp.MustCompile("^/$"), web_index)
api.CreateAPIv1(exitCh, conf, server)
server.ListenAndServe()
}