Appearance
バリデーション実装
リクエストパラメータのバリデーションを実装します。
cf.
事前準備
validatorパッケージをインストールします:
shell
go get github.com/go-playground/validator/v10実装
internal/validation
バリデータを実装します。NewValidationErrorにてバリデーションエラーからエラーメッセージを作成しerror型として返します。
validator.go
go
package validation
import (
"fmt"
"github.com/go-playground/validator/v10"
)
var Validate = validator.New()
type ValidationError struct {
Messages []string
}
func (e ValidationError) Error() string {
return fmt.Sprintf("%v", e.Messages)
}
func NewValidationError(err error) ValidationError {
validationErrors, ok := err.(validator.ValidationErrors)
if !ok {
return ValidationError{[]string{"unknown error"}}
}
var errorMessages []string
for _, e := range validationErrors {
errorMessages = append(
errorMessages,
fmt.Sprintf("invalid parameter. field: %s, tag: %s, value: %v",
e.Field(),
e.Tag(),
e.Value(),
),
)
}
return ValidationError{Messages: errorMessages}
}internal/presentation/handler/model
validateタグを用いてバリデーションを宣言し、validation.Validate.Structで値の検証を行います。
user_model.go
go
type LoginRequest struct {
Name string `json:"name"` // ユーザ名
Password string `json:"password" validate:"required"` // パスワード
}
func NewLoginRequest(r *http.Request) (LoginRequest, error) {
var req LoginRequest
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&req); err != nil {
return LoginRequest{}, err
}
if err := validation.Validate.Struct(req); err != nil {
return LoginRequest{}, validation.NewValidationError(err)
}
return req, nil
}internal/presentation/handler
NewLoginRequestからバリデーションエラーが返ってきた場合、そのエラーをAPIレスポンスとして返します。
user_handler.go
go
req, err := model.NewLoginRequest(r)
if err != nil {
if err, ok := err.(validation.ValidationError); ok {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusUnprocessableEntity)
json.NewEncoder(w).Encode(err)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(
struct {
Message string `json:"message"`
}{
Message: "bad request",
},
)
return
}