No tienes acceso a esta clase

¬°Contin√ļa aprendiendo! √önete y comienza a potenciar tu carrera

Agregando Multiples Middlewares

35/42
Recursos

Aportes 10

Preguntas 6

Ordenar por:

¬ŅQuieres ver m√°s aportes, preguntas y respuestas de la comunidad?

o inicia sesión.

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 ?