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 // RequestParam defines input parameters of an api request
type RequestParam map[string]interface{} type RequestParam map[string]interface{}
// GetString returns a string and an error if not found or string // Get returns the raw value (not typed) and an error if not found
func (rp RequestParam) GetString(key string) (string, error) { func (rp RequestParam) Get(key string) (interface{}, error) {
rawValue, found := rp[key] rawValue, found := rp[key]
if !found { if !found {
return "", ErrReqParamNotFound 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) convertedValue, canConvert := rawValue.(string)
if !canConvert { if !canConvert {

View File

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