aicra/http.go

117 lines
2.6 KiB
Go
Raw Permalink Normal View History

package aicra
import (
"log"
"net/http"
"git.xdrm.io/go/aicra/api"
"git.xdrm.io/go/aicra/internal/reqdata"
)
// httpServer wraps the aicra server to allow handling http requests
type httpServer Server
// ServeHTTP implements http.Handler and has to be called on each request
2020-03-21 13:49:36 +00:00
func (server httpServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
defer req.Body.Close()
// 1. find a matching service in the config
service := server.config.Find(req)
if service == nil {
response := api.EmptyResponse().WithError(api.ErrorUnknownService)
2020-03-21 13:49:36 +00:00
response.ServeHTTP(res, req)
logError(response)
return
}
2020-03-21 13:49:36 +00:00
// 2. build input parameter receiver
dataset := reqdata.New(service)
2020-03-21 13:49:36 +00:00
// 3. extract URI data
err := dataset.ExtractURI(req)
if err != nil {
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
2020-03-21 13:49:36 +00:00
response.ServeHTTP(res, req)
logError(response)
return
}
2020-03-21 13:49:36 +00:00
// 4. extract query data
err = dataset.ExtractQuery(req)
if err != nil {
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
2020-03-21 13:49:36 +00:00
response.ServeHTTP(res, req)
logError(response)
return
}
2020-03-21 13:49:36 +00:00
// 5. extract form/json data
err = dataset.ExtractForm(req)
if err != nil {
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
2020-03-21 13:49:36 +00:00
response.ServeHTTP(res, req)
logError(response)
return
}
2020-03-21 13:49:36 +00:00
// 6. find a matching handler
var foundHandler *handler
var found bool
for _, handler := range server.handlers {
if handler.Method == service.Method && handler.Path == service.Pattern {
2020-03-22 13:05:32 +00:00
foundHandler = handler
found = true
}
}
2020-03-21 13:49:36 +00:00
// 7. fail if found no handler
if foundHandler == nil {
if found {
r := api.EmptyResponse().WithError(api.ErrorUncallableService)
2020-03-21 13:49:36 +00:00
r.ServeHTTP(res, req)
logError(r)
return
}
r := api.EmptyResponse().WithError(api.ErrorUnknownService)
2020-03-21 13:49:36 +00:00
r.ServeHTTP(res, req)
logError(r)
return
}
2020-03-21 13:49:36 +00:00
// 8. build api.Request from http.Request
apireq, err := api.NewRequest(req)
if err != nil {
log.Fatal(err)
}
2020-03-21 13:49:36 +00:00
// 9. feed request with scope & parameters
apireq.Scope = service.Scope
apireq.Param = dataset.Data
2020-03-21 13:49:36 +00:00
// 10. execute
returned, apiErr := foundHandler.dynHandler.Handle(dataset.Data)
response := api.EmptyResponse().WithError(apiErr)
for key, value := range returned {
// find original name from rename
for name, param := range service.Output {
if param.Rename == key {
response.SetData(name, value)
}
}
}
2020-03-21 13:49:36 +00:00
// 11. apply headers
res.Header().Set("Content-Type", "application/json; charset=utf-8")
2020-03-21 13:49:36 +00:00
for key, values := range response.Headers {
for _, value := range values {
2020-03-21 13:49:36 +00:00
res.Header().Add(key, value)
}
}
2020-03-21 13:49:36 +00:00
// 12. write to response
response.ServeHTTP(res, req)
}