Skip to content

Commit

Permalink
refactor: render error with error code
Browse files Browse the repository at this point in the history
  • Loading branch information
litsynp committed Feb 3, 2024
1 parent fff4e61 commit 8bd3d80
Show file tree
Hide file tree
Showing 39 changed files with 797 additions and 591 deletions.
2 changes: 1 addition & 1 deletion api/commonviews/common.go → api/common.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package commonviews
package pnd

import (
"encoding/json"
Expand Down
87 changes: 0 additions & 87 deletions api/commonviews/errors.go

This file was deleted.

182 changes: 182 additions & 0 deletions api/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package pnd

import (
"net/http"
"strings"

"github.com/go-chi/render"
)

type AppErrorCode string

const (
// Common errors
ErrCodeBadRequest AppErrorCode = "ERR_BAD_REQUEST"
ErrCodeInvalidParam AppErrorCode = "ERR_INVALID_PARAM"
ErrCodeInvalidPagination AppErrorCode = "ERR_INVALID_PAGINATION"
ErrCodeInvalidQuery AppErrorCode = "ERR_INVALID_QUERY"
ErrCodeInvalidBody AppErrorCode = "ERR_INVALID_BODY"
ErrCodeMultipartForm AppErrorCode = "ERR_MULTIPART_FORM"

// Common errors - Auth
ErrCodeInvalidFBToken AppErrorCode = "ERR_INVALID_FB_TOKEN"
ErrCodeUserNotRegistered AppErrorCode = "ERR_USER_NOT_REGISTERED"
ErrCodeForbidden AppErrorCode = "ERR_FORBIDDEN"

// Common Errors - Resource
ErrCodeNotFound AppErrorCode = "ERR_NOT_FOUND"
ErrCodeConflict AppErrorCode = "ERR_CONFLICT"

ErrCodeUnknown AppErrorCode = "ERR_UNKNOWN"
)

type AppError struct {
Err error `json:"-"`
StatusCode int `json:"-"`

Code AppErrorCode `json:"code,omitempty"`
Message string `json:"message,omitempty"`
}

func (e *AppError) Render(w http.ResponseWriter, r *http.Request) error {
render.Status(r, e.StatusCode)
return nil
}

func (e *AppError) Error() string {
return e.Message
}

func ErrCustom(err error, statusCode int, code AppErrorCode, message string) *AppError {
return &AppError{
Err: err,
StatusCode: statusCode,
Code: code,
Message: message,
}
}

func ErrBadRequest(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeBadRequest,
Message: err.Error(),
}
}

func ErrInvalidParam(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeInvalidParam,
Message: err.Error(),
}
}

func ErrInvalidPagination(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeInvalidPagination,
Message: err.Error(),
}
}

func ErrInvalidQuery(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeInvalidQuery,
Message: err.Error(),
}
}

func ErrInvalidBody(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeInvalidBody,
Message: err.Error(),
}
}

func ErrMultipartFormError(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusBadRequest,
Code: ErrCodeMultipartForm,
Message: err.Error(),
}
}

func ErrInvalidFBToken(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusUnauthorized,
Code: ErrCodeInvalidFBToken,
Message: err.Error(),
}
}

func ErrUserNotRegistered(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusUnauthorized,
Code: ErrCodeUserNotRegistered,
Message: err.Error(),
}
}

func ErrForbidden(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusForbidden,
Code: ErrCodeForbidden,
Message: err.Error(),
}
}

func ErrNotFound(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusNotFound,
Code: ErrCodeNotFound,
Message: err.Error(),
}
}

func ErrConflict(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusConflict,
Code: ErrCodeConflict,
Message: err.Error(),
}
}

func ErrUnknown(err error) *AppError {
return &AppError{
Err: err,
StatusCode: http.StatusInternalServerError,
Code: ErrCodeUnknown,
Message: err.Error(),
}
}

func FromPGError(err error) *AppError {
errStr := err.Error()
if strings.Contains(errStr, "no rows in result set") {
return ErrCustom(err, http.StatusNotFound, ErrCodeNotFound, "해당하는 자원이 없습니다")
} else if strings.Contains(errStr, "violates foreign key constraint") {
return ErrCustom(err, http.StatusNotFound, ErrCodeNotFound, "해당하는 자원이 없습니다")
} else if strings.Contains(errStr, "violates not-null constraint") {
return ErrCustom(err, http.StatusBadRequest, ErrCodeBadRequest, "필수 값이 누락되었습니다")
} else if strings.Contains(errStr, "violates check constraint") {
return ErrCustom(err, http.StatusBadRequest, ErrCodeBadRequest, "잘못된 값입니다")
} else if strings.Contains(errStr, "violates unique constraint") {
return ErrCustom(err, http.StatusConflict, ErrCodeConflict, "중복된 값입니다")
} else {
return ErrCustom(err, http.StatusInternalServerError, ErrCodeUnknown, "알 수 없는 오류가 발생했습니다")
}
}
2 changes: 1 addition & 1 deletion api/commonviews/success.go → api/success.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package commonviews
package pnd

import "net/http"

Expand Down
19 changes: 10 additions & 9 deletions cmd/server/handler/auth_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"fmt"
"net/http"

"github.com/pet-sitter/pets-next-door-api/api/commonviews"
"github.com/go-chi/render"
app "github.com/pet-sitter/pets-next-door-api/api"
utils "github.com/pet-sitter/pets-next-door-api/internal/common"
"github.com/pet-sitter/pets-next-door-api/internal/configs"
"github.com/pet-sitter/pets-next-door-api/internal/domain/auth"
"github.com/pet-sitter/pets-next-door-api/internal/domain/user"
Expand Down Expand Up @@ -47,31 +49,30 @@ func (h *authHandler) KakaoLogin(w http.ResponseWriter, r *http.Request) {
// @Success 200 {object} auth.KakaoCallbackResponse
// @Router /auth/callback/kakao [get]
func (h *authHandler) KakaoCallback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")

tokenView, err := h.kakaoClient.FetchAccessToken(code)
code := utils.ParseOptionalStringQuery(r, "code")
tokenView, err := h.kakaoClient.FetchAccessToken(*code)
if err != nil {
commonviews.Unauthorized(w, nil, err.Error())
render.Render(w, r, app.ErrUnknown(err))
return
}

userProfile, err := h.kakaoClient.FetchUserProfile(tokenView.AccessToken)
if err != nil {
commonviews.Unauthorized(w, nil, err.Error())
render.Render(w, r, app.ErrUnknown(err))
return
}

ctx := r.Context()
customToken, err := h.authService.CustomToken(ctx, fmt.Sprintf("%d", userProfile.ID))
customToken, err2 := h.authService.CustomToken(ctx, fmt.Sprintf("%d", userProfile.ID))
if err != nil {
commonviews.Unauthorized(w, nil, err.Error())
render.Render(w, r, err2)
return
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(auth.KakaoCallbackResponse{
AuthToken: customToken,
AuthToken: *customToken,
FirebaseProviderType: user.FirebaseProviderTypeKakao,
FirebaseUID: fmt.Sprintf("%d", userProfile.ID),
Email: userProfile.KakaoAccount.Email,
Expand Down
26 changes: 10 additions & 16 deletions cmd/server/handler/breed_handler.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package handler

import (
"github.com/pet-sitter/pets-next-door-api/api/commonviews"
"github.com/pet-sitter/pets-next-door-api/internal/common"
"github.com/pet-sitter/pets-next-door-api/internal/domain/pet"
"net/http"

"github.com/go-chi/render"
pnd "github.com/pet-sitter/pets-next-door-api/api"
utils "github.com/pet-sitter/pets-next-door-api/internal/common"
"github.com/pet-sitter/pets-next-door-api/internal/domain/pet"
)

type BreedHandler struct {
Expand All @@ -24,29 +26,21 @@ func NewBreedHandler(breedService *pet.BreedService) *BreedHandler {
// @Param page query int false "페이지 번호" default(1)
// @Param size query int false "페이지 사이즈" default(20)
// @Param pet_type query string false "펫 종류" Enums(dog, cat)
// @Success 200 {object} commonviews.PaginatedView[pet.BreedView]
// @Success 200 {object} pnd.PaginatedView[pet.BreedView]
// @Router /breeds [get]
func (h *BreedHandler) FindBreeds(w http.ResponseWriter, r *http.Request) {
petTypeQuery := r.URL.Query().Get("pet_type")

petType := utils.ParseOptionalStringQuery(r, "pet_type")
page, size, err := utils.ParsePaginationQueries(r, 1, 20)
if err != nil {
commonviews.BadRequest(w, nil, err.Error())
render.Render(w, r, err)
return
}

var petType *string
if petTypeQuery == "" {
petType = nil
} else {
petType = &petTypeQuery
}

res, err := h.breedService.FindBreeds(page, size, petType)
if err != nil {
commonviews.InternalServerError(w, nil, err.Error())
render.Render(w, r, err)
return
}

commonviews.OK(w, nil, commonviews.NewPaginatedView(page, size, res))
pnd.OK(w, nil, pnd.NewPaginatedView(page, size, res))
}
Loading

0 comments on commit 8bd3d80

Please sign in to comment.