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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 59 additions and 105 deletions

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(),
})

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,
})
}

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,
})
}

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)

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!",
})
}),

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.

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) {

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 {

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) {

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) {

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))
}

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) {

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) {

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(),
})
}

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))
}

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) {