From fa3058b006da77be00885d3c01670c75fe324486 Mon Sep 17 00:00:00 2001 From: CrazyBolillo Date: Mon, 19 Aug 2024 15:17:00 -0600 Subject: [PATCH] feat(endpoint): return endpoint on creation Besides this being customary, it saves consumers a roundtrip if they want to verify the state of the created resource. --- docs/swagger.yaml | 8 +++++-- internal/handler/endpoint.go | 46 ++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 85584a1..11d0e48 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -54,6 +54,8 @@ definitions: type: string maxContacts: type: integer + sid: + type: integer transport: type: string type: object @@ -152,8 +154,10 @@ paths: schema: $ref: '#/definitions/handler.createEndpointRequest' responses: - "204": - description: No Content + "201": + description: Created + schema: + $ref: '#/definitions/handler.getEndpointResponse' "400": description: Bad Request "500": diff --git a/internal/handler/endpoint.go b/internal/handler/endpoint.go index 8027c21..10d9139 100644 --- a/internal/handler/endpoint.go +++ b/internal/handler/endpoint.go @@ -48,6 +48,7 @@ type listEndpointsResponse struct { } type getEndpointResponse struct { + Sid int32 `json:"sid"` ID string `json:"id"` DisplayName string `json:"displayName"` Transport string `json:"transport"` @@ -128,6 +129,7 @@ func (e *Endpoint) get(w http.ResponseWriter, r *http.Request) { } endpoint := getEndpointResponse{ + Sid: int32(id), ID: row.ID, Transport: row.Transport.String, Context: row.Context.String, @@ -220,7 +222,7 @@ func (e *Endpoint) list(w http.ResponseWriter, r *http.Request) { // @Summary Create a new endpoint. // @Accept json // @Param payload body createEndpointRequest true "Endpoint's information" -// @Success 204 +// @Success 201 {object} getEndpointResponse // @Failure 400 // @Failure 500 // @Tags endpoints @@ -297,7 +299,47 @@ func (e *Endpoint) create(w http.ResponseWriter, r *http.Request) { return } - w.WriteHeader(http.StatusNoContent) + // TODO: Duplicate code, same as when fetching endpoint. Probably should put this into a service layer. + tx, err = e.Begin(r.Context()) + queries = sqlc.New(tx) + if err != nil { + slog.Error("Failed to create new transaction", slog.String("path", r.URL.Path), slog.String("reason", err.Error())) + w.WriteHeader(http.StatusInternalServerError) + return + } + res, err := queries.GetEndpointByID(r.Context(), sid) + if err != nil { + slog.Error( + "Failed to retrieve created endpoint", + slog.String("path", r.URL.Path), slog.String("reason", err.Error()), slog.Int("sid", int(sid)), + ) + w.WriteHeader(http.StatusInternalServerError) + return + } + + endpoint := getEndpointResponse{ + Sid: sid, + ID: res.ID, + Transport: res.Transport.String, + Context: res.Context.String, + Codecs: strings.Split(res.Allow.String, ","), + MaxContacts: res.MaxContacts.Int32, + Extension: res.Extension.String, + DisplayName: displayNameFromClid(res.Callerid.String), + } + content, err := json.Marshal(endpoint) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + slog.Error("Failed to marshall response", slog.String("path", r.URL.Path)) + return + } + + w.Header().Set("Content-Type", "application/json") + _, err = w.Write(content) + if err != nil { + slog.Error("Failed to write response", slog.String("path", r.URL.Path), slog.String("reason", err.Error())) + } + w.WriteHeader(http.StatusCreated) } // @Summary Delete an endpoint and its associated resources.