Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Asignando Rutas HTTP

33/42
Recursos

Aportes 6

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Aqui el codigo actualizado

main.go

package main

func main()  {
	server := NewServer(":3000")

	//uso de la funcion handle con el path "/" y el handler
	server.Handle("/", HandleRoot)
	server.Handle("/api", HandleHome)
	server.Listen()
}

server.go

//el archivo main va a poder leer todo lo que este en el archivo server
package main

import (
	"net/http"
)

type Server struct{
	//puerto del servidor para escuchar las conexiones
	port string

	//se agrega el atributo router que es un apuntador al struct Router de router.go
	router *Router
}

//Funcion tipo global para ser leida en otros archivos
//Sirve para instanciar el servidor y que sea capaz de escuchar las conexiones
//recive el puerto que tiene que estar escuchando y devuelve el servidor como tal
func NewServer(port string) *Server {
	return &Server{
		port: port,

		//router instanciado
		router: NewRouter(),
		//con esto el servidor ya es capaz de instanciar el router y de tenerlo como propiedad
	}
}

//Handle es el nombre de la ruta por ejemplo "/api" asignado a un handler especifico
func (s *Server) Handle(path string, handler http.HandlerFunc){
	//Asociacion del handler con la ruta, es decir, el mapa con la llave path asignado al handler
	s.router.rules[path] = handler
	//asi el servidor es capaz de agregar la ruta especifica a un handler especifico
}


//Funcion tipo receiver, del struct Server, devuelve un error en caso de que haya problemas al conectar
func (s *Server) Listen() error{
	//el router va a ser el encargado de tomar las urls y procesarlas como se debe, crea el entry-point
	// los parametros son: el slash que es el punto de entrada, y el handler es el router recien creado
	http.Handle("/", s.router)
	
	//con la funcion listenanserve() del paquete http nos ayuda a escuchar todas las peticiones
	//colocas el puerto como primer parametro, el segundo es un handler 
	//pero nosotros haremos nuestros handlers por eso se coloca nil
	err := http.ListenAndServe(s.port, nil)

	if err != nil {
		return err
	}
	//si la ejecucion salio bien, retorna un valor nil
	return nil
	 
}

router.go

package main

import(
	
	"net/http"
)

//Struct router para hacer request en el servidor
type Router struct{
	//Reglas para definir de que rutas pasan a que handler, mapa que pasa de strings a handler
	//mapa que tenga como llaves strings y que mapee a HandlerFunc
	rules map[string]http.HandlerFunc

}

//forma de instanciar el router, similar al NewServer() del archivo servidor.go
func NewRouter() *Router {
	return &Router{
		//a diferencia del servidor, aqui el router debe empezar en un estado vacio, creamos un mapa vacio
		rules: make(map[string]http.HandlerFunc),
	}
}

//funcion que recibe el path que es un mapa y que devuelve dos valores:
//valor que devuelve y el valor booleano para saber si existe o no la llave dentro del mapa
func (r *Router) FindHandler(path string) (http.HandlerFunc, bool){
	//asignacion de el valor en el mapa de reglas a las variables handler y exist
	handler, exist := r.rules[path]
	return handler, exist
}



//Metodo ServeHTTP de router para poder implementar en el handler el atributo s.router en server.go
//parametros: el primero es el escritor, el segundo es el request en donde viene la informacion
//no olvidar colocar ServeHTTP con letras mayusculas
func (r *Router) ServeHTTP(w http.ResponseWriter, request *http.Request) {

	//manejo del mensaje de manera dinamica
	//r es la referencia al router y usar la funcion FindHandler
	//el FindHandler compara el request con el mapa de reglas para saber si existe o no.
	//los valores son asignados a las variables 'handler' y 'exist'
	handler, exist := r.FindHandler(request.URL.Path)

	//Evaluacion del booleano del handler para saber si existe o no, error 404
	if !exist{
		//WriteHeader es para indicar el status del request
		w.WriteHeader(http.StatusNotFound)
		//el return nos ayuda a romper la funcion si esto no existe el handler
		return 
	}
	//handler para enviar objeto w y request
	handler(w, request)


}

handlers.go

package main

import (
	"net/http"
	"fmt"
)


// Handler para manejar la ruta principal
//Parametros: escritor w del tipo http.ResponseWriter y objeto request
func HandleRoot(w http.ResponseWriter, r *http.Request)  {
	//Impresion en el navegador
	//parametros: escritor-objeto encargado de responder al cliente 
	//y mensaje escrito a travez del escritor
	fmt.Fprintf(w, "Hello World from handlers")
}

func HandleHome(w http.ResponseWriter, r *http.Request)  {
	fmt.Fprintf(w, "This is the API Endpoint")
}

Esta fue mi implementación luego de entender como funciona HandleFunc hace lo mismo pero me parecio mas sencilla

Main:

func main() {
	RoutesLayout()
	log.Println(http.ListenAndServe(":5000", nil))
}

Routes:

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

Handlers:

func Index(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		page404(w, r)
		return
	}
	fmt.Fprint(w, "Welcome to Index")
}

func Home(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Welcome to Home")
}

func page404(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(404)
	fmt.Fprint(w, "Web site not Found 404")
}

Hola, se que algunos se pueden estar preguntando si existe una forma mas rápida de hacer todo esto y simplemente sentarse a escribir las rutas del server, y la respuesta es si :3 el paquete de go que se encarga de todo esto se instala de esta forma
go get -u github.com/gorilla/mux

http.HandlerFunc es diferente de http.HandleFunc.

http.HandlerFunc es un type func significa que es una definición de una función. La diferencia radica en que es una signature específica y asociada a un tipo de función: las que reciben un (writer, request) y no tiene una implementación.

http.HandleFunc() puede definir un path directamente a una función, con mayor facilidad. Sin embargo, la forma completa de hacerlo y utilizar ServeHTTP, sirve para agregar procesos intermedios, middleware o nuestro propio router (como es el ejemplo).

package main

import (
	"net/http"
)

type Router struct {
	rules map[string]http.HandlerFunc
}

func NewRouter() *Router {
	return &Router{
		rules: make(map[string]http.HandlerFunc),
	}
}

func (r *Router) FindHandler(path string) (http.HandlerFunc, bool) {
	handler, exist := r.rules[path]
	return handler, exist
}

func (r *Router) ServeHTTP(w http.ResponseWriter, request *http.Request) {
	handler, exists := r.FindHandler(request.URL.Path)

	if !exists {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	handler(w, request)
}

Cuando intento ingresar a una dirección que no está mapeada dentro de las direcciones posibles no pasa nada. Tengo entendido que el w.WriteHeader(http.StatusNotFound) debería encargarse de mostrar algo pero parece que este no es el caso. ¿es normal?