package server import ( "net/http" "net/url" "somehole.com/common/log" ) type Request interface { Parse(*url.Values) error } type EmptyRequest interface { Request() Request } type Response interface { HttpStatus() int Response() []byte } type ErrorResponse interface { Ok() bool HttpStatus() int ErrorResponse() []byte String() string } type server struct { emptyReq EmptyRequest allowed []string logger log.Logger do func(req Request) (res Response, errRes ErrorResponse) } func NewServer(req EmptyRequest, allowed []string, logger log.Logger, do func(req Request) (res Response, errRes ErrorResponse)) *server { return &server{ emptyReq: req, allowed: allowed, logger: logger, do: do, } } type defaultError struct { Error string `json:"error"` } func (srv *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { req := srv.emptyReq request := req.Request() var allowed bool for _, method := range srv.allowed { if method == r.Method { allowed = true break } } if !allowed { w.WriteHeader(http.StatusMethodNotAllowed) w.Write(mustMarshalJson(&defaultError{Error: "method_not_allowed"})) srv.logger.Logf(log.LevelError, "requested method (%s) not one of %v", r.Method, srv.allowed) return } r.ParseForm() request.Parse(&r.Form) res, errRes := srv.do(request) if !errRes.Ok() { w.WriteHeader(errRes.HttpStatus()) w.Write(errRes.ErrorResponse()) srv.logger.Logf(log.LevelError, "request failed: %s", errRes.String()) } w.WriteHeader(res.HttpStatus()) w.Write(res.Response()) }