transfer local

This commit is contained in:
2025-12-28 14:12:31 +01:00
commit 31e4273903
8 changed files with 283 additions and 0 deletions

27
src/router/definition.go Normal file
View File

@@ -0,0 +1,27 @@
package router
import (
"sync"
)
// Interface de fonction pour les routes statiques
type HandlerFunc func(
method string,
path string,
args map[string]string,
queries map[string]string,
) (int, string)
type dynamicRoute struct {
method string
path string
elements []string
function HandlerFunc
}
// Définition du routeur
type Router struct {
lock sync.RWMutex
staticRoutes map[string]HandlerFunc
dynamicRoutes []dynamicRoute
}

35
src/router/init.go Normal file
View File

@@ -0,0 +1,35 @@
package router
import (
"fmt"
"strings"
)
// Création d'un routeur
func NewRouter() *Router {
return &Router{
staticRoutes: make(map[string]HandlerFunc),
dynamicRoutes: make([]dynamicRoute, 0),
}
}
// Ajout de nouvelles routes
func (router *Router) Register(method, path string, handler HandlerFunc) {
//Vérouille en écriture la map
router.lock.Lock()
defer router.lock.Unlock()
//On vérifie si le chemin est dynamique, si tel est le cas on push dans dynamicRoutes
if strings.Contains(path, "{") && strings.Contains(path, "}") {
router.dynamicRoutes = append(router.dynamicRoutes, dynamicRoute{
method: method,
path: path,
elements: strings.Split(path, "/"),
function: handler,
})
//Si le chemin ne contient pas de paramètres, alors on l'ajoute dans staticRoutes
} else {
router.staticRoutes[fmt.Sprintf("%s %s", method, path)] = handler
}
}

95
src/router/main.go Normal file
View File

@@ -0,0 +1,95 @@
package router
import (
"bufio"
"fmt"
"httpRouter/src/parser"
"net"
"strings"
)
func (router *Router) HandleClient(conn net.Conn) error {
//Création du lecteur
reader := bufio.NewReader(conn)
requestHeader, _, err := parser.ReadRequest(reader)
if err != nil {
return err
}
response := buildResponse(router.Handle(strings.Split(requestHeader[0], " ")[0], strings.Split(requestHeader[0], " ")[1]))
conn.Write([]byte(response))
conn.Close()
return nil
}
// Recherche et éxécution des routes sauvegardées
func (router *Router) Handle(method, path string) (int, string) {
endpoint, parameters, err := parser.ParseURL(path)
if err != nil {
return 400, endpoint
}
//Vérouille en lecture la map
router.lock.RLock()
defer router.lock.RUnlock()
fmt.Printf("%w\n", router.staticRoutes)
fmt.Printf("%s - %s", method, path)
//Vérification de l'existence de la route dans les routes statiques enregistrées
Handler, exists := router.staticRoutes[fmt.Sprintf("%s %s", method, endpoint)]
if exists {
return Handler(method, path, make(map[string]string), parameters)
}
elements := strings.Split(endpoint, "/")
//Vérification de la cohérence du chemin avec chaque route dynamique (O(n))
for _, route := range router.dynamicRoutes {
if len(elements) == len(route.elements) && route.method == method {
//On récupère les sous parties du chemin dynamique pour les comparer avec le chemin découpé
dynPath := route.elements
args := make(map[string]string)
//Pour chacun des sous ensembles on compare un a un les éléments
for index, item := range dynPath {
//S'il n'y a pas égalité stricte et que l'élément n'est pas un paramètre, on passe directement au prochain chemin dynamique
if elements[index] != item && (item[0] != '{' || item[len(item)-1] != '}') {
break
//Sinon si le chemin est un paramètre alors on ajoute dans le dictionnaire des paramètres la valeur du sous élément d'entrée
} else if len(item) > 0 && item[0] == '{' && item[len(item)-1] == '}' {
args[item[1:len(item)-1]] = elements[index]
}
//Si on a pas échappé à la boucle et qu'on est arrivés à la fin, c'est que c'était le bon chemin, on exécute la fonction associée
if index == len(elements)-1 {
return route.function(method, path, args, parameters)
}
}
} else {
continue
}
}
//Si aucun chemin n'a été validé, c'est qu'il n'est pas renseigné dans le routeur
return 404, "NOT FOUND"
}
// Logique de code
func buildResponse(code int, message string) string {
var codes = map[int]string{
200: "OK",
400: "WRONG REQUEST",
404: "NOT FOUND",
}
response := fmt.Sprintf("HTTP/1.1 %d %s", code, codes[code])
response += "Content-Type: text/plain\r\n"
response += fmt.Sprintf("Content-Length: %d\r\n", len(message))
response += "\r\n"
response += message
return response
}