Skip to content

Commit

Permalink
feat(http): add document labe handler
Browse files Browse the repository at this point in the history
  • Loading branch information
kelwang committed Apr 10, 2019
1 parent 76f002f commit ec68955
Show file tree
Hide file tree
Showing 5 changed files with 757 additions and 140 deletions.
118 changes: 105 additions & 13 deletions http/document_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ type DocumentBackend struct {
Logger *zap.Logger

DocumentService influxdb.DocumentService
LabelService influxdb.LabelService
}

// NewDocumentBackend returns a new instance of DocumentBackend.
func NewDocumentBackend(b *APIBackend) *DocumentBackend {
return &DocumentBackend{
Logger: b.Logger.With(zap.String("handler", "document")),
DocumentService: b.DocumentService,
LabelService: b.LabelService,
}
}

Expand All @@ -35,21 +37,25 @@ type DocumentHandler struct {
Logger *zap.Logger

DocumentService influxdb.DocumentService
LabelService influxdb.LabelService
}

const (
documentsPath = "/api/v2/documents/:ns"
documentPath = "/api/v2/documents/:ns/:id"
documentsPath = "/api/v2/documents/:ns"
documentPath = "/api/v2/documents/:ns/:id"
documentLabelsPath = "/api/v2/documents/:ns/:id/labels"
documentLabelsIDPath = "/api/v2/documents/:ns/:id/labels/:lid"
)

// TODO(desa): this should probably take a namespace
// NewDocumentHandler returns a new instance of DocumentHandler.
// TODO(desa): this should probably take a namespace
func NewDocumentHandler(b *DocumentBackend) *DocumentHandler {
h := &DocumentHandler{
Router: NewRouter(),
Logger: b.Logger,

DocumentService: b.DocumentService,
LabelService: b.LabelService,
}

h.HandlerFunc("POST", documentsPath, h.handlePostDocument)
Expand All @@ -58,6 +64,10 @@ func NewDocumentHandler(b *DocumentBackend) *DocumentHandler {
h.HandlerFunc("PUT", documentPath, h.handlePutDocument)
h.HandlerFunc("DELETE", documentPath, h.handleDeleteDocument)

h.HandlerFunc("GET", documentLabelsPath, h.handleGetDocumentLabel)
h.HandlerFunc("POST", documentLabelsPath, h.handlePostDocumentLabel)
h.HandlerFunc("DELETE", documentLabelsIDPath, h.handleDeleteDocumentLabel)

return h
}

Expand Down Expand Up @@ -260,46 +270,128 @@ func decodeGetDocumentsRequest(ctx context.Context, r *http.Request) (*getDocume
}, nil
}

// handleGetDocument is the HTTP handler for the GET /api/v2/documents/:ns/:id route.
func (h *DocumentHandler) handleGetDocument(w http.ResponseWriter, r *http.Request) {
func (h *DocumentHandler) handlePostDocumentLabel(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
_, _, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
return
}
req, err := decodePostLabelMappingRequest(ctx, r, influxdb.DocumentsResourceType)
if err != nil {
EncodeError(ctx, err, w)
return
}

req, err := decodeGetDocumentRequest(ctx, r)
if err := req.Mapping.Validate(); err != nil {
EncodeError(ctx, err, w)
return
}

if err := h.LabelService.CreateLabelMapping(ctx, &req.Mapping); err != nil {
EncodeError(ctx, err, w)
return
}

label, err := h.LabelService.FindLabelByID(ctx, req.Mapping.LabelID)
if err != nil {
EncodeError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusCreated, newLabelResponse(label)); err != nil {
logEncodingError(h.Logger, r, err)
return
}
}

s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
// handleDeleteDocumentLabel will first remove the label from the document,
// then remove that label.
func (h *DocumentHandler) handleDeleteDocumentLabel(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
req, err := decodeDeleteLabelMappingRequest(ctx, r)
if err != nil {
EncodeError(ctx, err, w)
return
}
_, _, err = h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
return
}

a, err := pcontext.GetAuthorizer(ctx)
_, err = h.LabelService.FindLabelByID(ctx, req.LabelID)
if err != nil {
EncodeError(ctx, err, w)
return
}

ds, err := s.FindDocuments(ctx, influxdb.AuthorizedWhereID(a, req.ID), influxdb.IncludeContent, influxdb.IncludeLabels)
mapping := &influxdb.LabelMapping{
LabelID: req.LabelID,
ResourceID: req.ResourceID,
ResourceType: influxdb.DocumentsResourceType,
}

// remove the label
if err := h.LabelService.DeleteLabelMapping(ctx, mapping); err != nil {
EncodeError(ctx, err, w)
return
}

w.WriteHeader(http.StatusNoContent)
}

func (h *DocumentHandler) handleGetDocumentLabel(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
d, _, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
return
}
if err := encodeResponse(ctx, w, http.StatusOK, newLabelsResponse(d.Labels)); err != nil {
logEncodingError(h.Logger, r, err)
return
}
}

func (h *DocumentHandler) getDocument(w http.ResponseWriter, r *http.Request) (*influxdb.Document, string, error) {
ctx := r.Context()

req, err := decodeGetDocumentRequest(ctx, r)
if err != nil {
return nil, "", err
}
s, err := h.DocumentService.FindDocumentStore(ctx, req.Namespace)
if err != nil {
return nil, "", err
}
a, err := pcontext.GetAuthorizer(ctx)
if err != nil {
return nil, "", err
}
ds, err := s.FindDocuments(ctx, influxdb.AuthorizedWhereID(a, req.ID), influxdb.IncludeContent, influxdb.IncludeLabels)
if err != nil {
return nil, "", err
}

if len(ds) != 1 {
err := &influxdb.Error{
return nil, "", &influxdb.Error{
Code: influxdb.EInternal,
Msg: fmt.Sprintf("found more than one document with id %s; please report this error", req.ID),
}
}
return ds[0], req.Namespace, nil
}

// handleGetDocument is the HTTP handler for the GET /api/v2/documents/:ns/:id route.
func (h *DocumentHandler) handleGetDocument(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
d, namspace, err := h.getDocument(w, r)
if err != nil {
EncodeError(ctx, err, w)
return
}

d := ds[0]

if err := encodeResponse(ctx, w, http.StatusOK, newDocumentResponse(req.Namespace, d)); err != nil {
if err := encodeResponse(ctx, w, http.StatusOK, newDocumentResponse(namspace, d)); err != nil {
logEncodingError(h.Logger, r, err)
return
}
Expand Down
Loading

0 comments on commit ec68955

Please sign in to comment.