No tienes acceso a esta clase

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

Agregando Multiples Middlewares

35/42
Recursos

Aportes 9

Preguntas 5

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

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),
		)
	}
}

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) ???

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

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

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 ?

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)
}

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)
		}
	}
}

cu√°l es la diferencia entre usar

middlewares ...Middleware

y

middlewares []Middleware

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