je voulais créer des erreurs personnalisées pour mon service d'authentification que je travaille actuellement. Puisque je dois créer une erreur pour chaque réponse HTTP, et je suis assez nouveau à Golang, je suis confronté à des difficultés. Le code ci-dessous est la réplique du code de code JavaScript que je souhaitais implémenter ici.
export abstract class CustomError extends Error {
abstract statusCode: number;
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, CustomError.prototype);
}
abstract serializeErrors(): { message: string; field?: string }[];
}
Pour créer des classes étendues en fonction de l'erreur personnalisée comme celle-ci
import { CustomError } from "./custom-error";
export class NotFoundError extends CustomError {
statusCode = 404;
constructor() {
super("Route not found");
Object.setPrototypeOf(this, NotFoundError.prototype);
}
serializeErrors() {
return [{ message: "Not Found" }];
}
}
afin que je puisse être lancé ou connecté du fichier principal, c'est-à-dire existant existant = attendre l'utilisateur.findone ({email});
if (existingUser) {
throw new BadRequestError("Email is already in use");
}
donc, en langage simple, je voulais créer un objet/modèle de CustomErrors qui peut aider à créer des erros plus diverses comme BADREQUESTERROR ()
donc, j'ai besoin d'aide pour créer celui-ci. Et ceci est ma première question ici
Si vous souhaitez des réponses d'erreur HTTP dans le texte brut, http.Error
devrait être votre choix. Mais si votre service d'authentification nécessite une réponse d'erreur dans un format spécifique (JSON/XML), vous devez créer des erreurs HTTP personnalisées pouvant être sérialisées et écrites dans la réponse.
Pour créer des réponses d'erreur HTTP personnalisées pour le format JSON (pour la série de modification du format XML), vous devez d'abord créer des types -
type ErrFields map[string]string // Error field-value pair type
type ResponseError struct {
Msg string `json:"message"` // Error message
Status int `json:"status"` // Http status code
Data ErrFields // For extra error fields e.g. reason, details, etc.
}
type ErrList []ResponseError // Multiple http errors type
Méthodes pour ResponseError
Type -
// AddErrField adds a new field to the response error with given key and value
func (err *ResponseError) AddErrField(key, value string) {
if err.Data == nil {
err.Data = make(ErrFields)
}
err.Data[key] = value
}
// RemoveErrField removes existing field matching given key from response error
func (err *ResponseError) RemoveErrField(key string) {
delete(err.Data, key)
}
// MarshalJSON marshals the response error into json
func (err *ResponseError) MarshalJSON() ([]byte, error) {
// Determine json field name for error message
errType := reflect.TypeOf(*err)
msgField, ok := errType.FieldByName("Msg")
msgJsonName := "message"
if ok {
msgJsonTag := msgField.Tag.Get("json")
if msgJsonTag != "" {
msgJsonName = msgJsonTag
}
}
// Determine json field name for error status code
statusField, ok := errType.FieldByName("Status")
statusJsonName := "status"
if ok {
statusJsonTag := statusField.Tag.Get("json")
if statusJsonTag != "" {
statusJsonName = statusJsonTag
}
}
fieldMap := make(map[string]string)
fieldMap[msgJsonName] = err.Msg
fieldMap[statusJsonName] = fmt.Sprintf("%d", err.Status)
for key, value := range err.Data {
fieldMap[key] = value
}
return json.Marshal(fieldMap)
}
// SerializeJSON converts response error into serialized json string
func (resErr *ResponseError) SerializeJSON() (string, error) {
value, err := json.Marshal(resErr)
if err != nil {
return "", err
}
return string(value), nil
}
Méthodes pour ErrList
Type -
// SerializeJSON converts error list into serialized json string
func (errList ErrList) SerializeJSON() (string, error) {
value, err := json.Marshal(errList)
if err != nil {
return "", err
}
return string(value), nil
}
Maintenant, vous pouvez créer des réponses d'erreur HTTP personnalisées en créant des valeurs différentes de ResponseError
Type -
// Error returns a general response error
func Error(msg string, status int) ResponseError {
return ResponseError{msg, status, nil}
}
// Errors returns a error list containing given response errors
func Errors(errors ...ResponseError) ErrList {
return errors
}
// Specific HTTP error responses
func ErrorNotFound() ResponseError {
return Error("not found", http.StatusNotFound)
}
func ErrorBadRequest() ResponseError {
return Error("bad request", http.StatusBadRequest)
}
func ErrorInternalServerError() ResponseError {
return Error("internal server error", http.StatusInternalServerError)
}
func ErrorForbidden() ResponseError {
return Error("forbidden", http.StatusForbidden)
}
Vous pouvez ajouter/supprimer des champs personnalisés sur les valeurs ResponseError
-
notFoundErr := ErrorNotFound()
notFoundErr.AddErrField("reason", "given 'id' does not exist")
notFoundErr.RemoveErrField("reason")
Étant donné qu'en aller, il n'y a pas de concept de lancer, vous ne pouvez que renvoyer une erreur de réponse d'une fonction -
func Foo() (resErr ResponseError, ok bool) {
...
if existingUser {
resErr = ErrorBadRequest()
resErr.AddErrField("reason", "Email is already in use")
return resErr, true
}
...
return ResponseError{}, false
}
Pour sérialiser l'erreur de réponse dans JSON -
resErr, ok := Foo()
if !ok {
json, err := resErr.SerializeJSON()
if err != nil {
// Handle serialization error
}
}
Voir l'exemple Go Playground ici .