1

I have 2 middlewares and the final HandleFunc.

But the Request.Body only works in the first Middleware. When the 2nd starts, the Body is Empty.

What could be happening?

This is my call to the route.

router.HandleFunc("/registro", middleW.Validaciones(middleW.UsuarioYaExiste(routes.Registro))).Methods("POST")

and the first Middleware is

func Validaciones (next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request)  {

        if bd.ChequeoConnection()==0 {
           http.Error(w,"Conexión Perdida con la Base de Datos",500)
           return
        } 

        var t models.Usuario
        err := json.NewDecoder(r.Body).Decode(&t)
        http.Error(w,"Nombre "+t.Nombre+" - Email "+t.Email+" - Password "+t.Password, 400)
        if err != nil {
            mensaje:="Validaciones : Usuario y/o Contraseña inválidos <br> Password ="+t.Password+"<br>Email = "+t.Email+"<br>Nombre = "+t.Nombre
            http.Error(w, mensaje, 400)
            return
        }

        if len(t.Email)==0 {
            http.Error(w, "El email de usuario es requerido", 400)
            return
        }

        if len(t.Password)<6 {
            http.Error(w, "Debe especificar una contraseña de al menos 6 caracteres", 400)
            return
        }

        /* si todo estuvo OK devuelve la función de la Ruta */
        next.ServeHTTP(w, r)
    }
}

this is the second Middleware

func UsuarioYaExiste (next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request)  {
        var t models.Usuario
        err := json.NewDecoder(r.Body).Decode(&t)

        http.Error(w,"Nombre 1ro. "+t.Nombre+" - Email "+t.Email+" - Password "+t.Password, 400)

        if err != nil {
            mensaje:="UsuarioYaExiste : Usuario y/o Contraseña inválidos <br> Password ="+t.Password+"<br>Email = "+t.Email+"<br>Nombre = "+t.Nombre
            http.Error(w, mensaje, 400)
            return
        }

        existe := bd.ChequeoYaExisteUsuario(t.Email)
        if existe == true && r.Method == "POST" {
            http.Error(w, "ya existe un usuario con ese email", 400)
            return
        }

        if existe == false && r.Method == "GET" {
            http.Error(w, "Usuario no existe", 400)
            return
        }

        /* si todo estuvo OK devuelve la función de la Ruta */
        next.ServeHTTP(w, r)
    }
}

In this 2nd Middleware, this line

http.Error(w,"Nombre 1ro. "+t.Nombre+" - Email "+t.Email+" - Password "+t.Password, 400)

show empty values, but not in the first Middleware.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Elba Nanero
  • 507
  • 1
  • 4
  • 10
  • Does this answer your question? [Golang read request body](https://stackoverflow.com/questions/43021058/golang-read-request-body) – FuXiang Shu Jan 14 '20 at 00:16

1 Answers1

1

HTTP request body is a stream, you can only read it once. Your first middleware reads the body, so there is nothing left for your second middleware.

Validating the body in the middleware is probably not the best solution for what you're trying to do. I suggest you remove the middleware, unmarshal the body in your handler, and refactor the middleware to a utility function into which you pass the unmarshaled message so it can do what it needs to do.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59
  • Hi , Thanks for your Answer, but the spirit of the Middleware is intercept the call, process it and pass control to a second middleware. And all HandleFunc have the Request as Parameter... Why the Body is lost ? – Elba Nanero Jan 14 '20 at 00:26
  • The body is a stream. You can read from it only once. Usually middleware is used to look at the headers, cookies, log the request, etc. and not the body. HandleFunc is usually where you read the body, process it, and write a response. What do you mean HandleFunc has the request as parameter? It has the response writer and the request as the parameter, the same as the middleware funcs. – Burak Serdar Jan 14 '20 at 00:35