mirror of
https://github.com/niusmallnan/steve.git
synced 2025-09-17 23:38:37 +00:00
Refactor
This commit is contained in:
124
pkg/schemaserver/writer/encoding.go
Normal file
124
pkg/schemaserver/writer/encoding.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package writer
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
)
|
||||
|
||||
type EncodingResponseWriter struct {
|
||||
ContentType string
|
||||
Encoder func(io.Writer, interface{}) error
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) start(apiOp *types.APIRequest, code int) {
|
||||
AddCommonResponseHeader(apiOp)
|
||||
apiOp.Response.Header().Set("content-type", j.ContentType)
|
||||
apiOp.Response.WriteHeader(code)
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) Write(apiOp *types.APIRequest, code int, obj types.APIObject) {
|
||||
j.start(apiOp, code)
|
||||
j.Body(apiOp, apiOp.Response, obj)
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) WriteList(apiOp *types.APIRequest, code int, list types.APIObjectList) {
|
||||
j.start(apiOp, code)
|
||||
j.BodyList(apiOp, apiOp.Response, list)
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) Body(apiOp *types.APIRequest, writer io.Writer, obj types.APIObject) error {
|
||||
return j.Encoder(writer, j.convert(apiOp, obj))
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) BodyList(apiOp *types.APIRequest, writer io.Writer, list types.APIObjectList) error {
|
||||
return j.Encoder(writer, j.convertList(apiOp, list))
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) convertList(apiOp *types.APIRequest, input types.APIObjectList) *types.GenericCollection {
|
||||
collection := newCollection(apiOp, input)
|
||||
for _, value := range input.Objects {
|
||||
converted := j.convert(apiOp, value)
|
||||
collection.Data = append(collection.Data, converted)
|
||||
}
|
||||
|
||||
if apiOp.Schema.CollectionFormatter != nil {
|
||||
apiOp.Schema.CollectionFormatter(apiOp, collection)
|
||||
}
|
||||
|
||||
return collection
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) convert(context *types.APIRequest, input types.APIObject) *types.RawResource {
|
||||
schema := context.Schemas.LookupSchema(input.Type)
|
||||
if schema == nil {
|
||||
schema = context.Schema
|
||||
}
|
||||
if schema == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
rawResource := &types.RawResource{
|
||||
ID: input.ID,
|
||||
Type: schema.ID,
|
||||
Schema: schema,
|
||||
Links: map[string]string{},
|
||||
Actions: map[string]string{},
|
||||
ActionLinks: context.Request.Header.Get("X-API-Action-Links") != "",
|
||||
APIObject: input,
|
||||
}
|
||||
|
||||
j.addLinks(schema, context, input, rawResource)
|
||||
|
||||
if schema.Formatter != nil {
|
||||
schema.Formatter(context, rawResource)
|
||||
}
|
||||
|
||||
return rawResource
|
||||
}
|
||||
|
||||
func (j *EncodingResponseWriter) addLinks(schema *types.APISchema, context *types.APIRequest, input types.APIObject, rawResource *types.RawResource) {
|
||||
if rawResource.ID == "" {
|
||||
return
|
||||
}
|
||||
|
||||
self := context.URLBuilder.ResourceLink(rawResource.Schema, rawResource.ID)
|
||||
if _, ok := rawResource.Links["self"]; !ok {
|
||||
rawResource.Links["self"] = self
|
||||
}
|
||||
if _, ok := rawResource.Links["update"]; !ok {
|
||||
if context.AccessControl.CanUpdate(context, input, schema) == nil {
|
||||
rawResource.Links["update"] = self
|
||||
}
|
||||
}
|
||||
if _, ok := rawResource.Links["remove"]; !ok {
|
||||
if context.AccessControl.CanDelete(context, input, schema) == nil {
|
||||
rawResource.Links["remove"] = self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newCollection(apiOp *types.APIRequest, list types.APIObjectList) *types.GenericCollection {
|
||||
result := &types.GenericCollection{
|
||||
Collection: types.Collection{
|
||||
Type: "collection",
|
||||
ResourceType: apiOp.Type,
|
||||
CreateTypes: map[string]string{},
|
||||
Links: map[string]string{
|
||||
"self": apiOp.URLBuilder.Current(),
|
||||
},
|
||||
Actions: map[string]string{},
|
||||
Continue: list.Continue,
|
||||
Revision: list.Revision,
|
||||
},
|
||||
}
|
||||
|
||||
if apiOp.Method == http.MethodGet {
|
||||
if apiOp.AccessControl.CanCreate(apiOp, apiOp.Schema) == nil {
|
||||
result.CreateTypes[apiOp.Schema.ID] = apiOp.URLBuilder.Collection(apiOp.Schema)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
24
pkg/schemaserver/writer/headers.go
Normal file
24
pkg/schemaserver/writer/headers.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package writer
|
||||
|
||||
import (
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
)
|
||||
|
||||
func AddCommonResponseHeader(apiOp *types.APIRequest) error {
|
||||
addExpires(apiOp)
|
||||
return addSchemasHeader(apiOp)
|
||||
}
|
||||
|
||||
func addSchemasHeader(apiOp *types.APIRequest) error {
|
||||
schema := apiOp.Schemas.Schemas["schema"]
|
||||
if schema == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
apiOp.Response.Header().Set("X-Api-Schemas", apiOp.URLBuilder.Collection(schema))
|
||||
return nil
|
||||
}
|
||||
|
||||
func addExpires(apiOp *types.APIRequest) {
|
||||
apiOp.Response.Header().Set("Expires", "Wed 24 Feb 1982 18:42:00 GMT")
|
||||
}
|
85
pkg/schemaserver/writer/html.go
Normal file
85
pkg/schemaserver/writer/html.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package writer
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
)
|
||||
|
||||
const (
|
||||
JSURL = "https://releases.rancher.com/api-ui/%API_UI_VERSION%/ui.min.js"
|
||||
CSSURL = "https://releases.rancher.com/api-ui/%API_UI_VERSION%/ui.min.css"
|
||||
DefaultVersion = "1.1.8"
|
||||
)
|
||||
|
||||
var (
|
||||
start = `
|
||||
<!DOCTYPE html>
|
||||
<!-- If you are reading this, there is a good chance you would prefer sending an
|
||||
"Accept: application/json" header and receiving actual JSON responses. -->
|
||||
<link rel="stylesheet" type="text/css" href="%CSSURL%" />
|
||||
<script src="%JSURL%"></script>
|
||||
<script>
|
||||
var user = "admin";
|
||||
var curlUser='${CATTLE_ACCESS_KEY}:${CATTLE_SECRET_KEY}';
|
||||
var schemas="%SCHEMAS%";
|
||||
var data =
|
||||
`
|
||||
end = []byte(`</script>
|
||||
`)
|
||||
)
|
||||
|
||||
type StringGetter func() string
|
||||
|
||||
type HTMLResponseWriter struct {
|
||||
EncodingResponseWriter
|
||||
CSSURL StringGetter
|
||||
JSURL StringGetter
|
||||
APIUIVersion StringGetter
|
||||
}
|
||||
|
||||
func (h *HTMLResponseWriter) start(apiOp *types.APIRequest, code int) {
|
||||
AddCommonResponseHeader(apiOp)
|
||||
apiOp.Response.Header().Set("content-type", "text/html")
|
||||
apiOp.Response.WriteHeader(code)
|
||||
}
|
||||
|
||||
func (h *HTMLResponseWriter) Write(apiOp *types.APIRequest, code int, obj types.APIObject) {
|
||||
h.write(apiOp, code, obj)
|
||||
}
|
||||
|
||||
func (h *HTMLResponseWriter) WriteList(apiOp *types.APIRequest, code int, list types.APIObjectList) {
|
||||
h.write(apiOp, code, list)
|
||||
}
|
||||
|
||||
func (h *HTMLResponseWriter) write(apiOp *types.APIRequest, code int, obj interface{}) {
|
||||
h.start(apiOp, code)
|
||||
schemaSchema := apiOp.Schemas.Schemas["schema"]
|
||||
headerString := start
|
||||
if schemaSchema != nil {
|
||||
headerString = strings.Replace(headerString, "%SCHEMAS%", apiOp.URLBuilder.Collection(schemaSchema), 1)
|
||||
}
|
||||
var jsurl, cssurl string
|
||||
if h.CSSURL != nil && h.JSURL != nil && h.CSSURL() != "" && h.JSURL() != "" {
|
||||
jsurl = h.JSURL()
|
||||
cssurl = h.CSSURL()
|
||||
} else if h.APIUIVersion != nil && h.APIUIVersion() != "" {
|
||||
jsurl = strings.Replace(JSURL, "%API_UI_VERSION%", h.APIUIVersion(), 1)
|
||||
cssurl = strings.Replace(CSSURL, "%API_UI_VERSION%", h.APIUIVersion(), 1)
|
||||
} else {
|
||||
jsurl = strings.Replace(JSURL, "%API_UI_VERSION%", DefaultVersion, 1)
|
||||
cssurl = strings.Replace(CSSURL, "%API_UI_VERSION%", DefaultVersion, 1)
|
||||
}
|
||||
headerString = strings.Replace(headerString, "%JSURL%", jsurl, 1)
|
||||
headerString = strings.Replace(headerString, "%CSSURL%", cssurl, 1)
|
||||
|
||||
apiOp.Response.Write([]byte(headerString))
|
||||
if apiObj, ok := obj.(types.APIObject); ok {
|
||||
h.Body(apiOp, apiOp.Response, apiObj)
|
||||
} else if list, ok := obj.(types.APIObjectList); ok {
|
||||
h.BodyList(apiOp, apiOp.Response, list)
|
||||
}
|
||||
if schemaSchema != nil {
|
||||
apiOp.Response.Write(end)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user