ref 1: clean server.go code + response implements http.Handler + add generic getter on request params Get() (interface{},error)

This commit is contained in:
Adrien Marquès 2019-05-02 07:48:34 +02:00
parent 0e498607ba
commit 6afedf190f
3 changed files with 42 additions and 33 deletions

View File

@ -17,12 +17,21 @@ const ErrReqParamNotType = ConstError("request parameter does not fulfills type"
// RequestParam defines input parameters of an api request
type RequestParam map[string]interface{}
// GetString returns a string and an error if not found or string
func (rp RequestParam) GetString(key string) (string, error) {
// Get returns the raw value (not typed) and an error if not found
func (rp RequestParam) Get(key string) (interface{}, error) {
rawValue, found := rp[key]
if !found {
return "", ErrReqParamNotFound
}
return rawValue, nil
}
// GetString returns a string and an error if not found or string
func (rp RequestParam) GetString(key string) (string, error) {
rawValue, err := rp.Get(key)
if err != nil {
return "", err
}
convertedValue, canConvert := rawValue.(string)
if !canConvert {

View File

@ -72,8 +72,8 @@ func (res *Response) MarshalJSON() ([]byte, error) {
return json.Marshal(fmt)
}
// Write writes to an HTTP response.
func (res *Response) Write(w http.ResponseWriter) error {
// ServeHTTP implements http.Handler and writes the API response.
func (res *Response) ServeHTTP(w http.ResponseWriter, r *http.Request) error {
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
w.WriteHeader(res.Status)

View File

@ -53,36 +53,36 @@ func New(configPath string) (*Server, error) {
}
// ServeHTTP implements http.Handler and has to be called on each request
func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
// 1. build API request from HTTP request
apiRequest, err := api.NewRequest(req)
request, err := api.NewRequest(r)
if err != nil {
log.Fatal(err)
}
// 2. find a matching service for this path in the config
serviceDef, pathIndex := s.services.Browse(apiRequest.URI)
serviceDef, pathIndex := s.services.Browse(request.URI)
if serviceDef == nil {
return
}
servicePath := strings.Join(apiRequest.URI[:pathIndex], "/")
servicePath := strings.Join(request.URI[:pathIndex], "/")
if !strings.HasPrefix(servicePath, "/") {
servicePath = "/" + servicePath
}
// 3. check if matching methodDef exists in config */
var methodDef = serviceDef.Method(req.Method)
var methodDef = serviceDef.Method(r.Method)
if methodDef == nil {
apiResponse := api.NewResponse(api.ErrorUnknownMethod())
apiResponse.Write(res)
logError(apiResponse)
response := api.NewResponse(api.ErrorUnknownMethod())
response.ServeHTTP(w, r)
logError(response)
return
}
// 4. parse every input data from the request
store := reqdata.New(apiRequest.URI[pathIndex:], req)
store := reqdata.New(request.URI[pathIndex:], r)
/* (4) Check parameters
---------------------------------------------------------*/
@ -90,13 +90,13 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
// Fail if argument check failed
if paramError.Code != api.ErrorSuccess().Code {
apiResponse := api.NewResponse(paramError)
apiResponse.Write(res)
logError(apiResponse)
response := api.NewResponse(paramError)
response.ServeHTTP(w, r)
logError(response)
return
}
apiRequest.Param = parameters
request.Param = parameters
/* (5) Search a matching handler
---------------------------------------------------------*/
@ -106,7 +106,7 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
for _, handler := range s.handlers {
if handler.GetPath() == servicePath {
serviceFound = true
if handler.GetMethod() == req.Method {
if handler.GetMethod() == r.Method {
serviceHandler = handler
}
}
@ -115,38 +115,38 @@ func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) {
// fail if found no handler
if serviceHandler == nil {
if serviceFound {
apiResponse := api.NewResponse()
apiResponse.SetError(api.ErrorUncallableMethod(), servicePath, req.Method)
apiResponse.Write(res)
logError(apiResponse)
response := api.NewResponse()
response.SetError(api.ErrorUncallableMethod(), servicePath, r.Method)
response.ServeHTTP(w, r)
logError(response)
return
}
apiResponse := api.NewResponse()
apiResponse.SetError(api.ErrorUncallableService(), servicePath)
apiResponse.Write(res)
logError(apiResponse)
response := api.NewResponse()
response.SetError(api.ErrorUncallableService(), servicePath)
response.ServeHTTP(w, r)
logError(response)
return
}
/* (6) Execute handler and return response
---------------------------------------------------------*/
// 1. feed request with configuration scope
apiRequest.Scope = methodDef.Permission
request.Scope = methodDef.Permission
// 1. execute
apiResponse := api.NewResponse()
serviceHandler.Handle(*apiRequest, apiResponse)
response := api.NewResponse()
serviceHandler.Handle(*request, response)
// 2. apply headers
for key, values := range apiResponse.Headers {
for key, values := range response.Headers {
for _, value := range values {
res.Header().Add(key, value)
w.Header().Add(key, value)
}
}
// 3. write to response
apiResponse.Write(res)
response.ServeHTTP(w, r)
return
}