No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

20 Días
0 Hrs
41 Min
51 Seg

Agregando Multiples Middlewares

35/42
Recursos

Aportes 10

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

En esta parte se complica bastante porque se juntan 2 conceptos que no se tocaron tan a detalle:

  1. El tipo func: Es un type que es una función. Lo que hace es definir una firma definida y las funciones que cuadren con esa firma se consideran de ese tipo. Similar a los métodos de las interfaces.

  2. Closures: Funciones anónimas que tienen acceso al scope que las está rodeando.
    Se complica un poco más porque tenemos dos func types anidadas.

// CheckAuth ...
func CheckAuth() Middleware {
	check := 1
	fmt.Println(check) // prints: 1

	return func(f http.HandlerFunc) http.HandlerFunc {
		fmt.Println(check + 1) // prints: 2

		return func(w http.ResponseWriter, r *http.Request) {
			fmt.Println(check + 1) // prints: 2

			fmt.Println("Checking authentication")
			flag := false
			if flag == false {
				fmt.Println("Unauthorized")
				return
			}
			f(w, r)
		}
	}
}

La función principal tiene la firma:

func CheckAuth() Middleware

Aquí retorna un a func type Middleware Lo que significa que retorna una función con la firma func(http.HandlerFunc) http.HandlerFunc. Por eso regresa la función de la manera en que vemos:

return func(f http.HandlerFunc) http.HandlerFunc

Lo relevante es que http.HandlerFunc también es una func type por eso debe tener en otro return la firma que tienen los handlers:

return func(w http.ResponseWriter, r *http.Request)

Así explícitamente está regresando la firma definida.

Hasta aquí todo me hacia sentido, pero me preguntaba. ¿Cómo es que en main podemos pasarla sin parámetros y en AddMiddlewares cuando se vuelve m(f) si lleva uno? ¿Cómo llega esa f al final?

Luego de varios test haciendo debugging (y leer más acerca de closures), encontré que CheckAuth() se ejecutaba 3 veces dependiendo la sección y la firma con la que se llamó. Dejé los prints para experimentar como salía y fue así.

En Main cuando se mandaba a llamar solo CheckAuth() sin parámetros imprimía 1 y nada más, como si solo se inicializara la función y su scope. En AddMiddleware se ejecutaba la función del primer return y únicamente ese scope, ya teniendo acceso a la variable check, por eso se imprimía 2. Mientras que al final cuando hacia el request a localhost y ya llegaban el (writer y request) se ejecutaba la función del segundo return. Pero en esta se volvía a imprimir 2 porque la anterior modificación no persistía. Como en el ejemplo se quedaron las funciones en blanco era difícil de percibir, pero creo es un comportamiento interesante de las func types y confuso con tanto func type.

Un ejemplo más sencillo de visualizar:

type Add func(int) int

func adder() Add { // es decir regresa una función con firma func(int) int
	sum := 0
	return func(x int) int {
		sum += x
		return sum
	}
}

func main() {
	// se manda a llamar sin recibir valores porque asi es la firma
	// pareciera solo se inicializara la variable función
	// asignando el valor de cero a la variable sum de dentro
	pos, neg := adder(), adder()
	for i := 0; i < 10; i++ {
		fmt.Println(
			// aquí es la verdadera implementación ya recibiendo un argumento
			// y se ejecuta la funcion del return
			pos(i),
			neg(-2*i),
		)
	}
}

en la sesion 34 estaba el codigo de AddMidleware. Que mala edición de los videos.

alguien me podría explicar qué hace esto??

for _, m := range middlewares {
	f = m(f)
}

Entiendo que itera los middlewares y toma cada uno, pero f es el http.HandlerFunc que recibimos por parámetro, qué está haciendo cuando asigna a f m(f) ???

Sería bueno que usen otros tipos de nombres para identificar los handlers y no solo f así es difícil de entender

Ejemplo:

func CheckAuth() Middleware {
	return func(nextHandler http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			// Here we do the authentication logic
			fmt.Println("Authentication Middleware")
			// and then we call the next middleware in the chain
			nextHandler(w, r)
		}
	}
}

SIn una explicación previa sobre funciones y clousres, esta sesión se complica extremadamente, hubiese sido mejor que agregaran un modulo explicando esto en vez de no sé todo eso que se hizo con la calculadora al comienzo que era super básico y sencillo

Mi implementacion de los middlewares

middlewares.go

func CheckAuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, request *http.Request) {
		flag := false
		if flag {
			next.ServeHTTP(w, request)
		} else {
			fmt.Fprint(w, "No authenticated")
			return
		}
	}
}

routes.go

func RoutesLayout() {
	http.HandleFunc("/", CheckAuthMiddleware(Index) )
	http.HandleFunc("/home", Home)
}

Para los que no pueden ver el autocompletar de Vscode en su código Go les dejo este tutorial muy bueno que me funcionó, es útil esta función ya que después de tanto código, tantos struct y funciones es necesario para no perderse

https://medium.com/backend-habit/setting-golang-plugin-on-vscode-for-autocomplete-and-auto-import-30bf5c58138a

cuál es la diferencia entre usar

middlewares ...Middleware

y

middlewares []Middleware

Si defino middlewares como un slice, no sería lo mismo?

package main // Conoce todo lo de este paquete
import "net/http"

// Puerto del servidor
type Server struct {
	port string
	router *Router
}


// Instanciar servidor y escuchar conexciones
func NewServer(port string) *Server {
	return &Server{
		port: port,
		router: NewRouter(),
	}
}

// Asioca un handler con una ruta
func (s *Server) Handle(path string, handler http.HandlerFunc) {
	s.router.rules[path] = handler
}

func (s *Server) AddMidleware(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
	for _, m := range middlewares {
		f = m(f)
	}

	return f
}

func (s *Server) Listen() error {
	// Punto de entrada de la aplicacion
	http.Handle("/", s.router)


	// Seguno parametro es un handler
	err := http.ListenAndServe(s.port, nil)
	
	return err
}

En Go, Cómo se podría reducir el riesgo de suplantación de identidad o de ataques tipo Man in the Middle, que pueden porpagarse como middleware maliciosos ?