mirror of
https://github.com/rancher/steve.git
synced 2025-09-07 10:21:33 +00:00
Refactor
This commit is contained in:
168
pkg/schemaserver/parse/parse.go
Normal file
168
pkg/schemaserver/parse/parse.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package parse
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
"github.com/rancher/steve/pkg/schemaserver/urlbuilder"
|
||||
)
|
||||
|
||||
const (
|
||||
maxFormSize = 2 * 1 << 20
|
||||
)
|
||||
|
||||
var (
|
||||
allowedFormats = map[string]bool{
|
||||
"html": true,
|
||||
"json": true,
|
||||
"yaml": true,
|
||||
}
|
||||
)
|
||||
|
||||
type ParsedURL struct {
|
||||
Type string
|
||||
Name string
|
||||
Link string
|
||||
Method string
|
||||
Action string
|
||||
Prefix string
|
||||
SubContext map[string]string
|
||||
Query url.Values
|
||||
}
|
||||
|
||||
type URLParser func(rw http.ResponseWriter, req *http.Request, schemas *types.APISchemas) (ParsedURL, error)
|
||||
|
||||
type Parser func(apiOp *types.APIRequest, urlParser URLParser) error
|
||||
|
||||
func Parse(apiOp *types.APIRequest, urlParser URLParser) error {
|
||||
var err error
|
||||
|
||||
if apiOp.Request == nil {
|
||||
apiOp.Request, err = http.NewRequest("GET", "/", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
apiOp = types.StoreAPIContext(apiOp)
|
||||
|
||||
if apiOp.Method == "" {
|
||||
apiOp.Method = parseMethod(apiOp.Request)
|
||||
}
|
||||
if apiOp.ResponseFormat == "" {
|
||||
apiOp.ResponseFormat = parseResponseFormat(apiOp.Request)
|
||||
}
|
||||
|
||||
// The response format is guaranteed to be set even in the event of an error
|
||||
parsedURL, err := urlParser(apiOp.Response, apiOp.Request, apiOp.Schemas)
|
||||
// wait to check error, want to set as much as possible
|
||||
|
||||
if apiOp.Type == "" {
|
||||
apiOp.Type = parsedURL.Type
|
||||
}
|
||||
if apiOp.Name == "" {
|
||||
apiOp.Name = parsedURL.Name
|
||||
}
|
||||
if apiOp.Link == "" {
|
||||
apiOp.Link = parsedURL.Link
|
||||
}
|
||||
if apiOp.Action == "" {
|
||||
apiOp.Action = parsedURL.Action
|
||||
}
|
||||
if apiOp.Query == nil {
|
||||
apiOp.Query = parsedURL.Query
|
||||
}
|
||||
if apiOp.Method == "" && parsedURL.Method != "" {
|
||||
apiOp.Method = parsedURL.Method
|
||||
}
|
||||
if apiOp.URLPrefix == "" {
|
||||
apiOp.URLPrefix = parsedURL.Prefix
|
||||
}
|
||||
|
||||
if apiOp.URLBuilder == nil {
|
||||
// make error local to not override the outer error we have yet to check
|
||||
var err error
|
||||
apiOp.URLBuilder, err = urlbuilder.New(apiOp.Request, &urlbuilder.DefaultPathResolver{
|
||||
Prefix: apiOp.URLPrefix,
|
||||
}, apiOp.Schemas)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if apiOp.Schema == nil && apiOp.Schemas != nil {
|
||||
apiOp.Schema = apiOp.Schemas.LookupSchema(apiOp.Type)
|
||||
}
|
||||
|
||||
if apiOp.Schema != nil && apiOp.Type == "" {
|
||||
apiOp.Type = apiOp.Schema.ID
|
||||
}
|
||||
|
||||
if err := ValidateMethod(apiOp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseResponseFormat(req *http.Request) string {
|
||||
format := req.URL.Query().Get("_format")
|
||||
|
||||
if format != "" {
|
||||
format = strings.TrimSpace(strings.ToLower(format))
|
||||
}
|
||||
|
||||
/* Format specified */
|
||||
if allowedFormats[format] {
|
||||
return format
|
||||
}
|
||||
|
||||
// User agent has Mozilla and browser accepts */*
|
||||
if IsBrowser(req, true) {
|
||||
return "html"
|
||||
}
|
||||
|
||||
if isYaml(req) {
|
||||
return "yaml"
|
||||
}
|
||||
return "json"
|
||||
}
|
||||
|
||||
func isYaml(req *http.Request) bool {
|
||||
return strings.Contains(req.Header.Get("Accept"), "application/yaml")
|
||||
}
|
||||
|
||||
func parseMethod(req *http.Request) string {
|
||||
method := req.URL.Query().Get("_method")
|
||||
if method == "" {
|
||||
method = req.Method
|
||||
}
|
||||
return method
|
||||
}
|
||||
|
||||
func Body(req *http.Request) (types.APIObject, error) {
|
||||
req.ParseMultipartForm(maxFormSize)
|
||||
if req.MultipartForm != nil {
|
||||
return valuesToBody(req.MultipartForm.Value), nil
|
||||
}
|
||||
|
||||
if req.PostForm != nil && len(req.PostForm) > 0 {
|
||||
return valuesToBody(map[string][]string(req.Form)), nil
|
||||
}
|
||||
|
||||
return ReadBody(req)
|
||||
}
|
||||
|
||||
func valuesToBody(input map[string][]string) types.APIObject {
|
||||
result := map[string]interface{}{}
|
||||
for k, v := range input {
|
||||
result[k] = v
|
||||
}
|
||||
return toAPI(result)
|
||||
}
|
Reference in New Issue
Block a user