Spaces:
Sleeping
Sleeping
| // _ _ | |
| // __ _____ __ ___ ___ __ _| |_ ___ | |
| // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ | |
| // \ V V / __/ (_| |\ V /| | (_| | || __/ | |
| // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| | |
| // | |
| // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. | |
| // | |
| // CONTACT: hello@weaviate.io | |
| // | |
| package extensions | |
| import ( | |
| "context" | |
| "io" | |
| "net/http" | |
| "github.com/weaviate/weaviate/entities/models" | |
| ) | |
| type RESTUserFacingHandlers struct { | |
| proxy Proxy | |
| } | |
| func newRESTUserFacingHandlers(proxy Proxy) *RESTUserFacingHandlers { | |
| return &RESTUserFacingHandlers{ | |
| proxy: proxy, | |
| } | |
| } | |
| func (h *RESTHandlers) UserFacingHandler() http.Handler { | |
| return newRESTUserFacingHandlers(h.proxy).Handler() | |
| } | |
| func (h *RESTUserFacingHandlers) Handler() http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| switch r.Method { | |
| case http.MethodPost: | |
| h.post(w, r) | |
| default: | |
| w.WriteHeader(http.StatusMethodNotAllowed) | |
| } | |
| }) | |
| } | |
| func (h *RESTUserFacingHandlers) post(w http.ResponseWriter, r *http.Request) { | |
| ct := r.Header.Get("content-type") | |
| if ct != "application/json" { | |
| w.WriteHeader(http.StatusUnsupportedMediaType) | |
| return | |
| } | |
| defer r.Body.Close() | |
| body, err := io.ReadAll(r.Body) | |
| if err != nil { | |
| h.writeError(w, err, http.StatusInternalServerError) | |
| return | |
| } | |
| var ext models.C11yExtension | |
| if err := (&ext).UnmarshalBinary(body); err != nil { | |
| h.writeError(w, err, http.StatusUnprocessableEntity) | |
| return | |
| } | |
| if err := h.proxy.AddExtension(r.Context(), &ext); err != nil { | |
| h.writeError(w, err, http.StatusBadRequest) | |
| return | |
| } | |
| resBody, err := ext.MarshalBinary() | |
| if err != nil { | |
| h.writeError(w, err, http.StatusInternalServerError) | |
| return | |
| } | |
| w.Header().Add("content-type", "application/json") | |
| w.WriteHeader(http.StatusOK) | |
| w.Write(resBody) | |
| } | |
| // C11yProxy proxies the request through the separate container, only for it to | |
| // come back here for the storage. This is legacy from the pre-module times. | |
| // TODO: cleanup, there does not need to be a separation between user-facing | |
| // and internal storage endpoint in the long-term | |
| type Proxy interface { | |
| AddExtension(ctx context.Context, extension *models.C11yExtension) error | |
| } | |
| func (h *RESTUserFacingHandlers) writeError(w http.ResponseWriter, err error, code int) { | |
| res := &models.ErrorResponse{Error: []*models.ErrorResponseErrorItems0{{ | |
| Message: err.Error(), | |
| }}} | |
| json, mErr := res.MarshalBinary() | |
| if mErr != nil { | |
| // fallback to text | |
| w.Header().Add("content-type", "text/plain") | |
| w.WriteHeader(code) | |
| w.Write([]byte(err.Error())) | |
| } | |
| w.Header().Add("content-type", "application/json") | |
| w.WriteHeader(code) | |
| w.Write(json) | |
| } | |