chore: idea: unify http responses further (#941)

This commit is contained in:
Garrett Delfosse
2022-04-12 10:17:33 -05:00
committed by GitHub
parent 4f0f216015
commit d9d4599ba9
16 changed files with 59 additions and 105 deletions
+1 -3
View File
@@ -9,7 +9,6 @@ import (
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"google.golang.org/api/idtoken"
chitrace "gopkg.in/DataDog/dd-trace-go.v1/contrib/go-chi/chi.v5"
@@ -67,8 +66,7 @@ func New(options *Options) (http.Handler, func()) {
})
r.Route("/buildinfo", func(r chi.Router) {
r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.BuildInfoResponse{
httpapi.Write(rw, http.StatusOK, codersdk.BuildInfoResponse{
ExternalURL: buildinfo.ExternalURL(),
Version: buildinfo.Version(),
})
+3 -5
View File
@@ -10,7 +10,6 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
@@ -44,8 +43,7 @@ func (api *api) postFile(rw http.ResponseWriter, r *http.Request) {
file, err := api.Database.GetFileByHash(r.Context(), hash)
if err == nil {
// The file already exists!
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.UploadResponse{
httpapi.Write(rw, http.StatusOK, codersdk.UploadResponse{
Hash: file.Hash,
})
return
@@ -63,8 +61,8 @@ func (api *api) postFile(rw http.ResponseWriter, r *http.Request) {
})
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, codersdk.UploadResponse{
httpapi.Write(rw, http.StatusCreated, codersdk.UploadResponse{
Hash: file.Hash,
})
}
+3 -8
View File
@@ -4,8 +4,6 @@ import (
"fmt"
"net/http"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/httpapi"
@@ -44,8 +42,7 @@ func (api *api) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.GitSSHKey{
httpapi.Write(rw, http.StatusOK, codersdk.GitSSHKey{
UserID: newKey.UserID,
CreatedAt: newKey.CreatedAt,
UpdatedAt: newKey.UpdatedAt,
@@ -64,8 +61,7 @@ func (api *api) gitSSHKey(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.GitSSHKey{
httpapi.Write(rw, http.StatusOK, codersdk.GitSSHKey{
UserID: gitSSHKey.UserID,
CreatedAt: gitSSHKey.CreatedAt,
UpdatedAt: gitSSHKey.UpdatedAt,
@@ -108,8 +104,7 @@ func (api *api) agentGitSSHKey(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.AgentGitSSHKey{
httpapi.Write(rw, http.StatusOK, codersdk.AgentGitSSHKey{
PrivateKey: gitSSHKey.PrivateKey,
})
}
+1 -1
View File
@@ -63,7 +63,7 @@ type Error struct {
}
// Write outputs a standardized format to an HTTP response body.
func Write(rw http.ResponseWriter, status int, response Response) {
func Write(rw http.ResponseWriter, status int, response interface{}) {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(true)
+1 -3
View File
@@ -5,7 +5,6 @@ import (
"time"
"github.com/go-chi/httprate"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
@@ -26,8 +25,7 @@ func RateLimitPerMinute(count int) func(http.Handler) http.Handler {
return httprate.KeyByIP(r)
}, httprate.KeyByEndpoint),
httprate.WithLimitHandler(func(w http.ResponseWriter, r *http.Request) {
render.Status(r, http.StatusTooManyRequests)
render.JSON(w, r, httpapi.Response{
httpapi.Write(w, http.StatusTooManyRequests, httpapi.Response{
Message: "You've been rate limited for sending too many requests!",
})
}),
+7 -13
View File
@@ -7,7 +7,6 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"golang.org/x/xerrors"
@@ -20,8 +19,7 @@ import (
func (*api) organization(rw http.ResponseWriter, r *http.Request) {
organization := httpmw.OrganizationParam(r)
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertOrganization(organization))
httpapi.Write(rw, http.StatusOK, convertOrganization(organization))
}
func (api *api) provisionerDaemonsByOrganization(rw http.ResponseWriter, r *http.Request) {
@@ -38,8 +36,7 @@ func (api *api) provisionerDaemonsByOrganization(rw http.ResponseWriter, r *http
if daemons == nil {
daemons = []database.ProvisionerDaemon{}
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, daemons)
httpapi.Write(rw, http.StatusOK, daemons)
}
// Creates a new version of a template. An import job is queued to parse the storage method provided.
@@ -147,8 +144,7 @@ func (api *api) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob)))
httpapi.Write(rw, http.StatusCreated, convertTemplateVersion(templateVersion, convertProvisionerJob(provisionerJob)))
}
// Create a new template in an organization.
@@ -252,8 +248,7 @@ func (api *api) postTemplatesByOrganization(rw http.ResponseWriter, r *http.Requ
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, template)
httpapi.Write(rw, http.StatusCreated, template)
}
func (api *api) templatesByOrganization(rw http.ResponseWriter, r *http.Request) {
@@ -284,8 +279,8 @@ func (api *api) templatesByOrganization(rw http.ResponseWriter, r *http.Request)
})
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertTemplates(templates, workspaceCounts))
httpapi.Write(rw, http.StatusOK, convertTemplates(templates, workspaceCounts))
}
func (api *api) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Request) {
@@ -325,8 +320,7 @@ func (api *api) templateByOrganizationAndName(rw http.ResponseWriter, r *http.Re
count = uint32(workspaceCounts[0].Count)
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertTemplate(template, count))
httpapi.Write(rw, http.StatusOK, convertTemplate(template, count))
}
// convertOrganization consumes the database representation and outputs an API friendly representation.
+2 -5
View File
@@ -7,7 +7,6 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/coder/coder/coderd/database"
@@ -59,8 +58,7 @@ func (api *api) postParameter(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertParameterValue(parameterValue))
httpapi.Write(rw, http.StatusCreated, convertParameterValue(parameterValue))
}
func (api *api) parameters(rw http.ResponseWriter, r *http.Request) {
@@ -86,8 +84,7 @@ func (api *api) parameters(rw http.ResponseWriter, r *http.Request) {
apiParameterValues = append(apiParameterValues, convertParameterValue(parameterValue))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiParameterValues)
httpapi.Write(rw, http.StatusOK, apiParameterValues)
}
func (api *api) deleteParameter(rw http.ResponseWriter, r *http.Request) {
+4 -5
View File
@@ -10,7 +10,6 @@ import (
"strconv"
"time"
"github.com/go-chi/render"
"github.com/google/uuid"
"cdr.dev/slog"
@@ -87,8 +86,8 @@ func (api *api) provisionerJobLogs(rw http.ResponseWriter, r *http.Request, job
if logs == nil {
logs = []database.ProvisionerJobLog{}
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, logs)
httpapi.Write(rw, http.StatusOK, logs)
return
}
@@ -229,8 +228,8 @@ func (api *api) provisionerJobResources(rw http.ResponseWriter, r *http.Request,
}
apiResources = append(apiResources, convertWorkspaceResource(resource, agents))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiResources)
httpapi.Write(rw, http.StatusOK, apiResources)
}
func convertProvisionerJobLog(provisionerJobLog database.ProvisionerJobLog) codersdk.ProvisionerJobLog {
+4 -7
View File
@@ -7,7 +7,6 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/coder/coder/coderd/database"
@@ -34,8 +33,7 @@ func (api *api) template(rw http.ResponseWriter, r *http.Request) {
count = uint32(workspaceCounts[0].Count)
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertTemplate(template, count))
httpapi.Write(rw, http.StatusOK, convertTemplate(template, count))
}
func (api *api) deleteTemplate(rw http.ResponseWriter, r *http.Request) {
@@ -114,8 +112,8 @@ func (api *api) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque
}
apiVersion = append(apiVersion, convertTemplateVersion(version, convertProvisionerJob(job)))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiVersion)
httpapi.Write(rw, http.StatusOK, apiVersion)
}
func (api *api) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
@@ -148,8 +146,7 @@ func (api *api) templateVersionByName(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
}
func (api *api) patchActiveTemplateVersion(rw http.ResponseWriter, r *http.Request) {
+6 -8
View File
@@ -6,8 +6,6 @@ import (
"fmt"
"net/http"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
@@ -24,8 +22,8 @@ func (api *api) templateVersion(rw http.ResponseWriter, r *http.Request) {
})
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
httpapi.Write(rw, http.StatusOK, convertTemplateVersion(templateVersion, convertProvisionerJob(job)))
}
func (api *api) patchCancelTemplateVersion(rw http.ResponseWriter, r *http.Request) {
@@ -95,8 +93,8 @@ func (api *api) templateVersionSchema(rw http.ResponseWriter, r *http.Request) {
if schemas == nil {
schemas = []database.ParameterSchema{}
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, schemas)
httpapi.Write(rw, http.StatusOK, schemas)
}
func (api *api) templateVersionParameters(rw http.ResponseWriter, r *http.Request) {
@@ -132,8 +130,8 @@ func (api *api) templateVersionParameters(rw http.ResponseWriter, r *http.Reques
if values == nil {
values = []parameter.ComputedValue{}
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, values)
httpapi.Write(rw, http.StatusOK, values)
}
func (api *api) templateVersionResources(rw http.ResponseWriter, r *http.Request) {
+16 -24
View File
@@ -10,7 +10,6 @@ import (
"time"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"golang.org/x/xerrors"
@@ -138,8 +137,7 @@ func (api *api) postFirstUser(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, codersdk.CreateFirstUserResponse{
httpapi.Write(rw, http.StatusCreated, codersdk.CreateFirstUserResponse{
UserID: user.ID,
OrganizationID: organization.ID,
})
@@ -258,8 +256,7 @@ func (api *api) postUsers(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertUser(user))
httpapi.Write(rw, http.StatusCreated, convertUser(user))
}
// Returns the parameterized user requested. All validation
@@ -267,7 +264,7 @@ func (api *api) postUsers(rw http.ResponseWriter, r *http.Request) {
func (*api) userByName(rw http.ResponseWriter, r *http.Request) {
user := httpmw.UserParam(r)
render.JSON(rw, r, convertUser(user))
httpapi.Write(rw, http.StatusOK, convertUser(user))
}
func (api *api) putUserProfile(rw http.ResponseWriter, r *http.Request) {
@@ -355,8 +352,7 @@ func (api *api) organizationsByUser(rw http.ResponseWriter, r *http.Request) {
publicOrganizations = append(publicOrganizations, convertOrganization(organization))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, publicOrganizations)
httpapi.Write(rw, http.StatusOK, publicOrganizations)
}
func (api *api) organizationByUserAndName(rw http.ResponseWriter, r *http.Request) {
@@ -392,8 +388,7 @@ func (api *api) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertOrganization(organization))
httpapi.Write(rw, http.StatusOK, convertOrganization(organization))
}
func (api *api) postOrganizationsByUser(rw http.ResponseWriter, r *http.Request) {
@@ -446,8 +441,7 @@ func (api *api) postOrganizationsByUser(rw http.ResponseWriter, r *http.Request)
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertOrganization(organization))
httpapi.Write(rw, http.StatusCreated, convertOrganization(organization))
}
// Authenticates the user with an email and password.
@@ -522,8 +516,7 @@ func (api *api) postLogin(rw http.ResponseWriter, r *http.Request) {
Secure: api.SecureAuthCookie,
})
render.Status(r, http.StatusCreated)
render.JSON(rw, r, codersdk.LoginWithPasswordResponse{
httpapi.Write(rw, http.StatusCreated, codersdk.LoginWithPasswordResponse{
SessionToken: sessionToken,
})
}
@@ -568,12 +561,11 @@ func (api *api) postAPIKey(rw http.ResponseWriter, r *http.Request) {
// This format is consumed by the APIKey middleware.
generatedAPIKey := fmt.Sprintf("%s-%s", keyID, keySecret)
render.Status(r, http.StatusCreated)
render.JSON(rw, r, codersdk.GenerateAPIKeyResponse{Key: generatedAPIKey})
httpapi.Write(rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: generatedAPIKey})
}
// Clear the user's session cookie
func (*api) postLogout(rw http.ResponseWriter, r *http.Request) {
func (*api) postLogout(rw http.ResponseWriter, _ *http.Request) {
// Get a blank token cookie
cookie := &http.Cookie{
// MaxAge < 0 means to delete the cookie now
@@ -583,7 +575,9 @@ func (*api) postLogout(rw http.ResponseWriter, r *http.Request) {
}
http.SetCookie(rw, cookie)
render.Status(r, http.StatusOK)
httpapi.Write(rw, http.StatusOK, httpapi.Response{
Message: "Logged out!",
})
}
// Create a new workspace for the currently authenticated user.
@@ -767,8 +761,7 @@ func (api *api) postWorkspacesByUser(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertWorkspace(workspace,
httpapi.Write(rw, http.StatusCreated, convertWorkspace(workspace,
convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(templateVersionJob)), template))
}
@@ -865,8 +858,8 @@ func (api *api) workspacesByUser(rw http.ResponseWriter, r *http.Request) {
apiWorkspaces = append(apiWorkspaces,
convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiWorkspaces)
httpapi.Write(rw, http.StatusOK, apiWorkspaces)
}
func (api *api) workspaceByUserAndName(rw http.ResponseWriter, r *http.Request) {
@@ -910,8 +903,7 @@ func (api *api) workspaceByUserAndName(rw http.ResponseWriter, r *http.Request)
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertWorkspace(workspace,
httpapi.Write(rw, http.StatusOK, convertWorkspace(workspace,
convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
}
+2 -3
View File
@@ -8,7 +8,6 @@ import (
"net/http"
"time"
"github.com/go-chi/render"
"github.com/hashicorp/yamux"
"golang.org/x/xerrors"
"nhooyr.io/websocket"
@@ -32,8 +31,8 @@ func (api *api) workspaceAgent(rw http.ResponseWriter, r *http.Request) {
})
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiAgent)
httpapi.Write(rw, http.StatusOK, apiAgent)
}
func (api *api) workspaceAgentDial(rw http.ResponseWriter, r *http.Request) {
+2 -4
View File
@@ -5,8 +5,6 @@ import (
"fmt"
"net/http"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
@@ -22,8 +20,8 @@ func (api *api) workspaceBuild(rw http.ResponseWriter, r *http.Request) {
})
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(job)))
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(job)))
}
func (api *api) patchCancelWorkspaceBuild(rw http.ResponseWriter, r *http.Request) {
+2 -4
View File
@@ -7,8 +7,6 @@ import (
"fmt"
"net/http"
"github.com/go-chi/render"
"github.com/coder/coder/coderd/awsidentity"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
@@ -134,8 +132,8 @@ func (api *api) handleAuthInstanceID(rw http.ResponseWriter, r *http.Request, in
})
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, codersdk.WorkspaceAgentAuthenticateResponse{
httpapi.Write(rw, http.StatusOK, codersdk.WorkspaceAgentAuthenticateResponse{
SessionToken: agent.AuthToken.String(),
})
}
+1 -3
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"net/http"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/coder/coder/coderd/httpapi"
@@ -52,6 +51,5 @@ func (api *api) workspaceResource(rw http.ResponseWriter, r *http.Request) {
apiAgents = append(apiAgents, convertedAgent)
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertWorkspaceResource(workspaceResource, apiAgents))
httpapi.Write(rw, http.StatusOK, convertWorkspaceResource(workspaceResource, apiAgents))
}
+4 -9
View File
@@ -8,7 +8,6 @@ import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/google/uuid"
"github.com/moby/moby/pkg/namesgenerator"
"golang.org/x/xerrors"
@@ -22,7 +21,6 @@ import (
func (api *api) workspace(rw http.ResponseWriter, r *http.Request) {
workspace := httpmw.WorkspaceParam(r)
render.Status(r, http.StatusOK)
build, err := api.Database.GetWorkspaceBuildByWorkspaceIDWithoutAfter(r.Context(), workspace.ID)
if err != nil {
@@ -45,7 +43,7 @@ func (api *api) workspace(rw http.ResponseWriter, r *http.Request) {
})
return
}
render.JSON(rw, r, convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
httpapi.Write(rw, http.StatusOK, convertWorkspace(workspace, convertWorkspaceBuild(build, convertProvisionerJob(job)), template))
}
func (api *api) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
@@ -92,8 +90,7 @@ func (api *api) workspaceBuilds(rw http.ResponseWriter, r *http.Request) {
apiBuilds = append(apiBuilds, convertWorkspaceBuild(build, convertProvisionerJob(job)))
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, apiBuilds)
httpapi.Write(rw, http.StatusOK, apiBuilds)
}
func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
@@ -256,8 +253,7 @@ func (api *api) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusCreated)
render.JSON(rw, r, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(provisionerJob)))
httpapi.Write(rw, http.StatusCreated, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(provisionerJob)))
}
func (api *api) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
@@ -287,8 +283,7 @@ func (api *api) workspaceBuildByName(rw http.ResponseWriter, r *http.Request) {
return
}
render.Status(r, http.StatusOK)
render.JSON(rw, r, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(job)))
httpapi.Write(rw, http.StatusOK, convertWorkspaceBuild(workspaceBuild, convertProvisionerJob(job)))
}
func (api *api) putWorkspaceAutostart(rw http.ResponseWriter, r *http.Request) {