77 lines
1.5 KiB
Go
77 lines
1.5 KiB
Go
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())
|
|
}
|