move send error to source lib (#12175)

* move send error to source lib

Move the sendError into library in case the cycle dependency as regsitry and core are now the consumers.

Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
Wang Yan 2020-06-19 01:04:50 +08:00 committed by GitHub
parent 8bcffb0a28
commit 58b7242a25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 80 additions and 80 deletions

View File

@ -18,6 +18,7 @@ import (
"encoding/json"
"errors"
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"strconv"
@ -25,7 +26,6 @@ import (
"github.com/astaxie/beego/validation"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/lib/log"
serror "github.com/goharbor/harbor/src/server/error"
)
const (
@ -64,7 +64,7 @@ func (b *BaseAPI) Render() error {
// RenderError provides shortcut to render http error
func (b *BaseAPI) RenderError(code int, text string) {
serror.SendError(b.Ctx.ResponseWriter, &commonhttp.Error{
lib_http.SendError(b.Ctx.ResponseWriter, &commonhttp.Error{
Code: code,
Message: text,
})
@ -255,5 +255,5 @@ func (b *BaseAPI) SendStatusServiceUnavailableError(err error) {
// ]
// }
func (b *BaseAPI) SendError(err error) {
serror.SendError(b.Ctx.ResponseWriter, err)
lib_http.SendError(b.Ctx.ResponseWriter, err)
}

View File

@ -12,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package error
package http
import (
"fmt"
openapi "github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
@ -94,20 +92,3 @@ func apiError(err error) (statusCode int, errPayload, stackTrace string) {
}
return code, errors.NewErrs(err).Error(), fullStack
}
var _ middleware.Responder = &ErrResponder{}
// ErrResponder error responder
type ErrResponder struct {
err error
}
// WriteResponse ...
func (r *ErrResponder) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
SendError(rw, r.err)
}
// NewErrResponder returns responder for err
func NewErrResponder(err error) *ErrResponder {
return &ErrResponder{err: err}
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package error
package http
import (
std_errors "errors"
@ -55,7 +55,7 @@ func TestAPIError(t *testing.T) {
statusCode, payload, stacktrace := apiError(err)
assert.Equal(t, http.StatusBadRequest, statusCode)
assert.Equal(t, `{"errors":[{"code":"BAD_REQUEST","message":"bad request"}]}`, payload)
assert.Contains(t, stacktrace, `error.apiError`)
assert.Contains(t, stacktrace, `http.apiError`)
// legacy error
err = &commonhttp.Error{
@ -65,14 +65,14 @@ func TestAPIError(t *testing.T) {
statusCode, payload, stacktrace = apiError(err)
assert.Equal(t, http.StatusNotFound, statusCode)
assert.Equal(t, `{"errors":[{"code":"NOT_FOUND","message":"not found"}]}`, payload)
assert.Contains(t, stacktrace, `error.apiError`)
assert.Contains(t, stacktrace, `http.apiError`)
// errors.Error
err = errors.New(nil).WithCode(errors.NotFoundCode).WithMessage("resource not found")
statusCode, payload, stacktrace = apiError(err)
assert.Equal(t, http.StatusNotFound, statusCode)
assert.Equal(t, `{"errors":[{"code":"NOT_FOUND","message":"resource not found"}]}`, payload)
assert.Contains(t, stacktrace, `error.TestAPIError`)
assert.Contains(t, stacktrace, `http.TestAPIError`)
// common error, common error has no stacktrace
e := std_errors.New("customized error")

View File

@ -17,7 +17,7 @@ package api
import (
"encoding/json"
"github.com/goharbor/harbor/src/lib/errors"
server_error "github.com/goharbor/harbor/src/server/error"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
)
@ -38,7 +38,7 @@ func HandleBadRequest(w http.ResponseWriter, err error) {
// HandleError ...
func HandleError(w http.ResponseWriter, err error) {
server_error.SendError(w, err)
lib_http.SendError(w, err)
}
// WriteJSON response status code will be written automatically if there is an error

View File

@ -16,6 +16,7 @@ package artifactinfo
import (
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"net/url"
"regexp"
@ -24,7 +25,6 @@ import (
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/middleware"
"github.com/opencontainers/go-digest"
)
@ -59,7 +59,7 @@ func Middleware() func(http.Handler) http.Handler {
repo := m[middleware.RepositorySubexp]
pn, err := projectNameFromRepo(repo)
if err != nil {
serror.SendError(rw, errors.BadRequestError(err))
lib_http.SendError(rw, errors.BadRequestError(err))
return
}
art := lib.ArtifactInfo{
@ -80,7 +80,7 @@ func Middleware() func(http.Handler) http.Handler {
// it's not clear in OCI spec how to handle invalid from parm
bmp, err := projectNameFromRepo(bmr)
if err != nil {
serror.SendError(rw, errors.BadRequestError(err))
lib_http.SendError(rw, errors.BadRequestError(err))
return
}
art.BlobMountDigest = m[blobMountDigest]

View File

@ -1,6 +1,7 @@
package csrf
import (
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"os"
"strings"
@ -11,7 +12,6 @@ import (
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/middleware"
"github.com/gorilla/csrf"
)
@ -45,7 +45,7 @@ func attachToken(w http.ResponseWriter, r *http.Request) {
func handleError(w http.ResponseWriter, r *http.Request) {
attachToken(w, r)
serror.SendError(w, errors.New(csrf.FailureReason(r)).WithCode(errors.ForbiddenCode))
lib_http.SendError(w, errors.New(csrf.FailureReason(r)).WithCode(errors.ForbiddenCode))
return
}

View File

@ -2,6 +2,7 @@ package immutable
import (
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
common_util "github.com/goharbor/harbor/src/common/utils"
@ -10,7 +11,6 @@ import (
"github.com/goharbor/harbor/src/lib"
errors "github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
serror "github.com/goharbor/harbor/src/server/error"
)
// Middleware ...
@ -21,11 +21,11 @@ func Middleware() func(http.Handler) http.Handler {
var e *ErrImmutable
if errors.As(err, &e) {
pkgE := errors.New(e).WithCode(errors.PreconditionCode)
serror.SendError(rw, pkgE)
lib_http.SendError(rw, pkgE)
return
}
pkgE := errors.New(fmt.Errorf("error occurred when to handle request in immutable handler: %v", err)).WithCode(errors.GeneralCode)
serror.SendError(rw, pkgE)
lib_http.SendError(rw, pkgE)
return
}
next.ServeHTTP(rw, req)

View File

@ -15,10 +15,10 @@
package middleware
import (
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"github.com/goharbor/harbor/src/lib"
serror "github.com/goharbor/harbor/src/server/error"
)
// Middleware receives a handler and returns another handler.
@ -63,7 +63,7 @@ func New(fn func(http.ResponseWriter, *http.Request, http.Handler), skippers ...
func BeforeRequest(hook func(*http.Request) error, skippers ...Skipper) func(http.Handler) http.Handler {
return New(func(w http.ResponseWriter, r *http.Request, next http.Handler) {
if err := hook(lib.NopCloseRequest(r)); err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -85,7 +85,7 @@ func AfterResponse(hook func(http.ResponseWriter, *http.Request, int) error, ski
if err := hook(res, r, res.StatusCode()); err != nil {
res.Reset()
serror.SendError(res, err)
lib_http.SendError(res, err)
}
}, skippers...)
}

View File

@ -16,6 +16,7 @@ package quota
import (
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"strings"
@ -27,7 +28,6 @@ import (
"github.com/goharbor/harbor/src/pkg/notifier/event"
"github.com/goharbor/harbor/src/pkg/quota"
"github.com/goharbor/harbor/src/pkg/types"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/middleware"
)
@ -63,7 +63,7 @@ func RequestMiddleware(config RequestConfig, skippers ...middleware.Skipper) fun
logger := log.G(r.Context()).WithFields(log.Fields{"middleware": "quota", "action": "request", "url": r.URL.Path})
if config.ReferenceObject == nil || config.Resources == nil {
serror.SendError(w, fmt.Errorf("invald config the for middleware"))
lib_http.SendError(w, fmt.Errorf("invald config the for middleware"))
return
}
@ -71,14 +71,14 @@ func RequestMiddleware(config RequestConfig, skippers ...middleware.Skipper) fun
if err != nil {
logger.Errorf("get reference object failed, error: %v", err)
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
enabled, err := quotaController.IsEnabled(r.Context(), reference, referenceID)
if err != nil {
logger.Errorf("check whether quota enabled for %s %s failed, error: %v", reference, referenceID, err)
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -93,7 +93,7 @@ func RequestMiddleware(config RequestConfig, skippers ...middleware.Skipper) fun
if err != nil {
logger.Errorf("get resources failed, error: %v", err)
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -171,9 +171,9 @@ func RequestMiddleware(config RequestConfig, skippers ...middleware.Skipper) fun
var errs quota.Errors
if errors.As(err, &errs) {
serror.SendError(res, errors.DeniedError(nil).WithMessage(errs.Error()))
lib_http.SendError(res, errors.DeniedError(nil).WithMessage(errs.Error()))
} else {
serror.SendError(res, err)
lib_http.SendError(res, err)
}
}

View File

@ -15,7 +15,7 @@
package readonly
import (
serror "github.com/goharbor/harbor/src/server/error"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"github.com/goharbor/harbor/src/core/config"
@ -70,7 +70,7 @@ func MiddlewareWithConfig(config Config, skippers ...middleware.Skipper) func(ht
return middleware.New(func(w http.ResponseWriter, r *http.Request, next http.Handler) {
if config.ReadOnly(r) {
pkgE := errors.New(nil).WithCode(errors.DENIED).WithMessage("The system is in read only mode. Any modification is prohibited.")
serror.SendError(w, pkgE)
lib_http.SendError(w, pkgE)
return
}

View File

@ -18,12 +18,12 @@ import (
"context"
"errors"
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/orm"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/middleware"
)
@ -77,7 +77,7 @@ func Middleware(skippers ...middleware.Skipper) func(http.Handler) http.Handler
log.Errorf("reset the response failed: %v", err)
return
}
serror.SendError(res, err)
lib_http.SendError(res, err)
}
}, skippers...)
}

View File

@ -16,6 +16,7 @@ package v2auth
import (
"fmt"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
"net/url"
"strings"
@ -28,7 +29,6 @@ import (
"github.com/goharbor/harbor/src/core/service/token"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
serror "github.com/goharbor/harbor/src/server/error"
)
const (
@ -141,7 +141,7 @@ func Middleware() func(http.Handler) http.Handler {
// the header is needed for "docker manifest" commands: https://github.com/docker/cli/issues/989
rw.Header().Set("Docker-Distribution-Api-Version", "registry/2.0")
rw.Header().Set("Www-Authenticate", challenge)
serror.SendError(rw, errors.UnauthorizedError(err).WithMessage(err.Error()))
lib_http.SendError(rw, errors.UnauthorizedError(err).WithMessage(err.Error()))
return
}
next.ServeHTTP(rw, req)

View File

@ -21,8 +21,8 @@ import (
"github.com/goharbor/harbor/src/controller/artifact"
"github.com/goharbor/harbor/src/controller/repository"
"github.com/goharbor/harbor/src/lib/errors"
lib_http "github.com/goharbor/harbor/src/lib/http"
"github.com/goharbor/harbor/src/lib/q"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/registry/util"
"net/http"
"sort"
@ -52,7 +52,7 @@ func (r *repositoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
maxEntries, err = strconv.Atoi(reqQ.Get("n"))
if err != nil || maxEntries < 0 {
err := errors.New(err).WithCode(errors.BadRequestCode).WithMessage("the N must be a positive int type")
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
}
@ -61,7 +61,7 @@ func (r *repositoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
// get all repositories
repoRecords, err := r.repoCtl.List(req.Context(), nil)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if len(repoRecords) <= 0 {
@ -71,7 +71,7 @@ func (r *repositoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
for _, repo := range repoRecords {
valid, err := r.validateRepo(req.Context(), repo.RepositoryID)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if valid {
@ -93,7 +93,7 @@ func (r *repositoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
lastEntryIndex := util.IndexString(repoNames, lastEntry)
if lastEntryIndex == -1 {
err := errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(fmt.Sprintf("the last: %s should be a valid repository name.", lastEntry))
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if lastEntryIndex+1+maxEntries > repoNamesLen {
@ -118,7 +118,7 @@ func (r *repositoryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request)
if repoNames[len(repoNames)-1] != resRepos[len(resRepos)-1] {
urlStr, err := util.SetLinkHeader(req.URL.String(), maxEntries, resRepos[len(resRepos)-1])
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
w.Header().Set("Link", urlStr)
@ -135,7 +135,7 @@ func (r *repositoryHandler) sendResponse(w http.ResponseWriter, req *http.Reques
if err := enc.Encode(catalogAPIResponse{
Repositories: repositoryNames,
}); err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
}

View File

@ -20,10 +20,10 @@ import (
"github.com/goharbor/harbor/src/controller/repository"
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/errors"
lib_http "github.com/goharbor/harbor/src/lib/http"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/pkg/notification"
"github.com/goharbor/harbor/src/pkg/registry"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/router"
"github.com/opencontainers/go-digest"
"net/http"
@ -36,7 +36,7 @@ func getManifest(w http.ResponseWriter, req *http.Request) {
reference := router.Param(req.Context(), ":reference")
art, err := artifact.Ctl.GetByReference(req.Context(), repository, reference, nil)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -74,16 +74,16 @@ func deleteManifest(w http.ResponseWriter, req *http.Request) {
// Do not add the logic into GetByReference as it's a shared method for PUT/GET/DELETE/Internal call,
// and NOT_FOUND satisfy PUT/GET/Internal call.
if _, err := digest.Parse(reference); err != nil {
serror.SendError(w, errors.Wrapf(err, "unsupported digest %s", reference).WithCode(errors.UNSUPPORTED))
lib_http.SendError(w, errors.Wrapf(err, "unsupported digest %s", reference).WithCode(errors.UNSUPPORTED))
return
}
art, err := artifact.Ctl.GetByReference(req.Context(), repository, reference, nil)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if err = artifact.Ctl.Delete(req.Context(), art.ID); err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
w.WriteHeader(http.StatusAccepted)
@ -96,7 +96,7 @@ func putManifest(w http.ResponseWriter, req *http.Request) {
// make sure the repository exist before pushing the manifest
_, _, err := repository.Ctl.Ensure(req.Context(), repo)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -124,7 +124,7 @@ func putManifest(w http.ResponseWriter, req *http.Request) {
_, _, err = artifact.Ctl.Ensure(req.Context(), repo, dgt, tags...)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}

View File

@ -20,8 +20,8 @@ import (
"github.com/goharbor/harbor/src/controller/repository"
"github.com/goharbor/harbor/src/controller/tag"
"github.com/goharbor/harbor/src/lib/errors"
lib_http "github.com/goharbor/harbor/src/lib/http"
"github.com/goharbor/harbor/src/lib/q"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/registry/util"
"github.com/goharbor/harbor/src/server/router"
"net/http"
@ -65,7 +65,7 @@ func (t *tagHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
maxEntries, err = strconv.Atoi(reqQ.Get("n"))
if err != nil || maxEntries < 0 {
err := errors.New(err).WithCode(errors.BadRequestCode).WithMessage("the N must be a positive int type")
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
}
@ -75,7 +75,7 @@ func (t *tagHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
t.repositoryName = router.Param(req.Context(), ":splat")
repository, err := t.repoCtl.GetByName(req.Context(), t.repositoryName)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
@ -85,7 +85,7 @@ func (t *tagHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
"RepositoryID": repository.RepositoryID,
}}, nil)
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if len(tags) == 0 {
@ -111,7 +111,7 @@ func (t *tagHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
lastEntryIndex := util.IndexString(tagNames, lastEntry)
if lastEntryIndex == -1 {
err := errors.New(nil).WithCode(errors.BadRequestCode).WithMessage(fmt.Sprintf("the last: %s should be a valid tag name.", lastEntry))
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
if lastEntryIndex+1+maxEntries > tagNamesLen {
@ -136,7 +136,7 @@ func (t *tagHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if tagNames[len(tagNames)-1] != resTags[len(resTags)-1] {
urlStr, err := util.SetLinkHeader(req.URL.String(), maxEntries, resTags[len(resTags)-1])
if err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
w.Header().Set("Link", urlStr)
@ -153,7 +153,7 @@ func (t *tagHandler) sendResponse(w http.ResponseWriter, req *http.Request, tagN
Name: t.repositoryName,
Tags: tagNames,
}); err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
return
}
}

View File

@ -18,9 +18,12 @@ package handler
import (
"context"
"github.com/go-openapi/runtime"
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/errors"
lib_http "github.com/goharbor/harbor/src/lib/http"
"github.com/goharbor/harbor/src/lib/q"
"net/http"
"net/url"
"strconv"
@ -30,7 +33,6 @@ import (
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/controller/project"
"github.com/goharbor/harbor/src/lib/log"
errs "github.com/goharbor/harbor/src/server/error"
)
// BaseAPI base API handler
@ -43,7 +45,7 @@ func (*BaseAPI) Prepare(ctx context.Context, operation string, params interface{
// SendError returns response for the err
func (*BaseAPI) SendError(ctx context.Context, err error) middleware.Responder {
return errs.NewErrResponder(err)
return NewErrResponder(err)
}
// HasPermission returns true when the request has action permission on resource
@ -179,3 +181,20 @@ func (b *BaseAPI) Links(ctx context.Context, u *url.URL, total, pageNumber, page
}
return links
}
var _ middleware.Responder = &ErrResponder{}
// ErrResponder error responder
type ErrResponder struct {
err error
}
// WriteResponse ...
func (r *ErrResponder) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
lib_http.SendError(rw, r.err)
}
// NewErrResponder returns responder for err
func NewErrResponder(err error) *ErrResponder {
return &ErrResponder{err: err}
}

View File

@ -15,10 +15,10 @@
package handler
import (
lib_http "github.com/goharbor/harbor/src/lib/http"
"log"
"net/http"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/middleware"
"github.com/goharbor/harbor/src/server/middleware/blob"
"github.com/goharbor/harbor/src/server/middleware/quota"
@ -52,5 +52,5 @@ func New() http.Handler {
// The response format of the default ServeError implementation does not match the internal error response format.
// So we needed to convert the format to the internal error response format.
func serveError(rw http.ResponseWriter, r *http.Request, err error) {
serror.SendError(rw, err)
lib_http.SendError(rw, err)
}

View File

@ -16,9 +16,9 @@ package server
import (
"encoding/json"
lib_http "github.com/goharbor/harbor/src/lib/http"
"net/http"
serror "github.com/goharbor/harbor/src/server/error"
"github.com/goharbor/harbor/src/server/v2.0/route"
)
@ -34,6 +34,6 @@ type APIVersion struct {
// GetAPIVersion returns the current supported API version
func GetAPIVersion(w http.ResponseWriter, r *http.Request) {
if err := json.NewEncoder(w).Encode(&APIVersion{Version: version}); err != nil {
serror.SendError(w, err)
lib_http.SendError(w, err)
}
}