2019-09-26 17:03:37 +00:00
|
|
|
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 {
|
2020-03-28 13:57:28 +00:00
|
|
|
response := api.EmptyResponse().WithError(api.ErrorUnknownService)
|
2020-03-21 13:49:36 +00:00
|
|
|
response.ServeHTTP(res, req)
|
|
|
|
logError(response)
|
2019-09-26 17:03:37 +00:00
|
|
|
return
|
|
|
|
}
|
2020-03-03 17:36:52 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 2. build input parameter receiver
|
|
|
|
dataset := reqdata.New(service)
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 3. extract URI data
|
|
|
|
err := dataset.ExtractURI(req)
|
|
|
|
if err != nil {
|
2020-03-28 13:57:28 +00:00
|
|
|
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
|
2020-03-21 13:49:36 +00:00
|
|
|
response.ServeHTTP(res, req)
|
|
|
|
logError(response)
|
2019-09-26 17:03:37 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 4. extract query data
|
|
|
|
err = dataset.ExtractQuery(req)
|
|
|
|
if err != nil {
|
2020-03-28 13:57:28 +00:00
|
|
|
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
|
2020-03-21 13:49:36 +00:00
|
|
|
response.ServeHTTP(res, req)
|
|
|
|
logError(response)
|
2019-09-26 17:03:37 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 5. extract form/json data
|
|
|
|
err = dataset.ExtractForm(req)
|
|
|
|
if err != nil {
|
2020-03-28 13:57:28 +00:00
|
|
|
response := api.EmptyResponse().WithError(api.ErrorMissingParam)
|
2020-03-21 13:49:36 +00:00
|
|
|
response.ServeHTTP(res, req)
|
|
|
|
logError(response)
|
|
|
|
return
|
|
|
|
}
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 6. find a matching handler
|
2020-03-29 15:01:02 +00:00
|
|
|
var foundHandler *handler
|
2020-03-03 17:36:52 +00:00
|
|
|
var found bool
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-03-03 17:36:52 +00:00
|
|
|
for _, handler := range server.handlers {
|
2020-03-29 15:01:02 +00:00
|
|
|
if handler.Method == service.Method && handler.Path == service.Pattern {
|
2020-03-22 13:05:32 +00:00
|
|
|
foundHandler = handler
|
2020-03-03 17:36:52 +00:00
|
|
|
found = true
|
2019-09-26 17:03:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 7. fail if found no handler
|
2020-03-03 17:36:52 +00:00
|
|
|
if foundHandler == nil {
|
|
|
|
if found {
|
2020-03-28 13:57:28 +00:00
|
|
|
r := api.EmptyResponse().WithError(api.ErrorUncallableService)
|
2020-03-21 13:49:36 +00:00
|
|
|
r.ServeHTTP(res, req)
|
|
|
|
logError(r)
|
2019-09-26 17:03:37 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-03-28 13:57:28 +00:00
|
|
|
r := api.EmptyResponse().WithError(api.ErrorUnknownService)
|
2020-03-21 13:49:36 +00:00
|
|
|
r.ServeHTTP(res, req)
|
|
|
|
logError(r)
|
2019-09-26 17:03:37 +00:00
|
|
|
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)
|
|
|
|
}
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 9. feed request with scope & parameters
|
|
|
|
apireq.Scope = service.Scope
|
|
|
|
apireq.Param = dataset.Data
|
2019-09-26 17:03:37 +00:00
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 10. execute
|
2020-03-29 15:01:02 +00:00
|
|
|
returned, apiErr := foundHandler.dynHandler.Handle(dataset.Data)
|
|
|
|
response := api.EmptyResponse().WithError(apiErr)
|
|
|
|
for key, value := range returned {
|
|
|
|
|
|
|
|
response.SetData(name, value)
|
|
|
|
}
|
2020-03-21 13:49:36 +00:00
|
|
|
|
|
|
|
// 11. apply headers
|
2020-03-22 13:05:47 +00:00
|
|
|
res.Header().Set("Content-Type", "application/json; charset=utf-8")
|
2020-03-21 13:49:36 +00:00
|
|
|
for key, values := range response.Headers {
|
2019-09-26 17:03:37 +00:00
|
|
|
for _, value := range values {
|
2020-03-21 13:49:36 +00:00
|
|
|
res.Header().Add(key, value)
|
2019-09-26 17:03:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-21 13:49:36 +00:00
|
|
|
// 12. write to response
|
|
|
|
response.ServeHTTP(res, req)
|
2019-09-26 17:03:37 +00:00
|
|
|
}
|