Go: Comunicación por HTTP

Go
Go
Actualizado: 14/02/2025

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

El paquete net/http de Go es una herramienta fundamental para desarrolladores que buscan crear servidores y clientes HTTP eficientes. Este paquete forma parte de la biblioteca estándar de Go y ofrece una amplia gama de funcionalidades para manejar comunicaciones HTTP de manera efectiva. A continuación, exploraremos en profundidad cómo utilizar el paquete net/http para construir aplicaciones web sólidas y escalables.

Introducción al paquete net/http

El paquete net/http proporciona las capacidades necesarias para:

  • Crear servidores HTTP.
  • Desarrollar clientes HTTP.
  • Manipular solicitudes y respuestas HTTP.
  • Implementar middleware y manejadores personalizados.

Al ser parte de la biblioteca estándar, no es necesario instalar dependencias externas para comenzar a utilizarlo.

Creación de un servidor HTTP básico

Para iniciar un servidor web en Go, se puede utilizar la función http.ListenAndServe. A continuación se muestra un ejemplo básico:

package main

import (
    "fmt"
    "net/http"
)

func manejadorSaludo(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "¡Bienvenido al servidor HTTP en Go!")
}

func main() {
    http.HandleFunc("/", manejadorSaludo)
    if err := http.ListenAndServe(":8080", nil); err != nil {
        fmt.Println("Error al iniciar el servidor:", err)
    }
}

Este código inicia un servidor que escucha en el puerto 8080 y responde con un mensaje de bienvenida a cualquier solicitud entrante.

Manejo de solicitudes y respuestas

Guarda tu progreso

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

El paquete net/http utiliza las estructuras http.Request y http.ResponseWriter para representar solicitudes y respuestas HTTP respectivamente.

Estructura de http.Request

La estructura http.Request contiene información sobre la solicitud entrante, como:

  • Método HTTP (GET, POST, etc.).
  • URL solicitada.
  • Encabezados y cookies.
  • Cuerpo de la solicitud.

Uso de http.ResponseWriter

El http.ResponseWriter permite enviar respuestas al cliente. Se puede escribir directamente en él para enviar el cuerpo de la respuesta y establecer encabezados HTTP.

func manejadorDatos(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"mensaje": "Datos procesados correctamente"}`))
}

Rutas y enrutamiento

Aunque el paquete net/http no incluye un enrutador sofisticado, permite asociar manejadores a rutas específicas usando http.HandleFunc o http.Handle.

http.HandleFunc("/usuarios", manejadorUsuarios)
http.HandleFunc("/productos", manejadorProductos)

Para aplicaciones más complejas, es común utilizar enrutadores externos, pero es posible implementar enrutamiento básico con las herramientas estándar.

Manejadores personalizados y la interfaz http.Handler

Un manejador en Go es cualquier objeto que implemente la interfaz http.Handler, es decir, que tenga un método ServeHTTP.

type miManejador struct{}

func (h *miManejador) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Este es un manejador personalizado utilizando http.Handler")
}

func main() {
    manejador := &miManejador{}
    http.Handle("/personalizado", manejador)
    http.ListenAndServe(":8080", nil)
}

Este enfoque permite mayor flexibilidad y reutilización de código en aplicaciones de gran escala.

Middleware y composición de manejadores

Los middleware son componentes que se ejecutan antes o después de los manejadores principales, permitiendo agregar funcionalidades transversales como autenticación, registro de solicitudes o manejo de errores.

func registroMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("Solicitud recibida:", r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

func manejadorPrincipal(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Respuesta del manejador principal")
}

func main() {
    http.Handle("/", registroMiddleware(http.HandlerFunc(manejadorPrincipal)))
    http.ListenAndServe(":8080", nil)
}

Servir archivos estáticos

Para servir archivos estáticos, como archivos HTML, CSS o imágenes, se utiliza http.FileServer.

func main() {
    fs := http.FileServer(http.Dir("./public"))
    http.Handle("/static/", http.StripPrefix("/static/", fs))
    http.ListenAndServe(":8080", nil)
}

Este código sirve los archivos ubicados en el directorio public bajo la ruta /static/.

Manejando parámetros de consulta y formularios

Parámetros de consulta

Los parámetros de consulta en la URL pueden obtenerse a través de r.URL.Query().

func manejadorConsulta(w http.ResponseWriter, r *http.Request) {
    valores := r.URL.Query()
    id := valores.Get("id")
    fmt.Fprintf(w, "El ID proporcionado es: %s", id)
}

Procesamiento de formularios

Para procesar datos enviados mediante formularios (método POST), se utiliza r.ParseForm().

func manejadorFormulario(w http.ResponseWriter, r *http.Request) {
    if err := r.ParseForm(); err != nil {
        http.Error(w, "Error al procesar el formulario", http.StatusBadRequest)
        return
    }
    nombre := r.FormValue("nombre")
    correo := r.FormValue("correo")
    fmt.Fprintf(w, "Nombre: %s, Correo: %s", nombre, correo)
}

Subida de archivos al servidor

El manejo de archivos enviados desde formularios se realiza mediante r.FormFile.

func manejadorSubida(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Método no permitido", http.StatusMethodNotAllowed)
        return
    }
    archivo, encabezado, err := r.FormFile("archivo")
    if err != nil {
        http.Error(w, "Error al obtener el archivo", http.StatusBadRequest)
        return
    }
    defer archivo.Close()

    // Procesar el archivo (por ejemplo, guardarlo en el servidor)
    rutaDestino := "./uploads/" + encabezado.Filename
    ficheroDestino, err := os.Create(rutaDestino)
    if err != nil {
        http.Error(w, "Error al guardar el archivo", http.StatusInternalServerError)
        return
    }
    defer ficheroDestino.Close()
    io.Copy(ficheroDestino, archivo)

    fmt.Fprintf(w, "Archivo subido exitosamente: %s", encabezado.Filename)
}

Implementación de clientes HTTP

Además de crear servidores, el paquete net/http permite realizar solicitudes HTTP como cliente.

func realizarSolicitud() {
    resp, err := http.Get("https://api.ejemplo.com/datos")
    if err != nil {
        fmt.Println("Error en la solicitud:", err)
        return
    }
    defer resp.Body.Close()

    cuerpo, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error al leer la respuesta:", err)
        return
    }

    fmt.Println("Respuesta del servidor:", string(cuerpo))
}

Para solicitudes más complejas, se puede utilizar http.Client y construir solicitudes con http.NewRequest.

Configuración de tiempo de espera y transporte

Es posible establecer configuraciones personalizadas en el cliente HTTP, como tiempos de espera y proxies.

func clientePersonalizado() {
    transport := &http.Transport{
        Proxy: http.ProxyFromEnvironment,
    }
    client := &http.Client{
        Transport: transport,
        Timeout:   30 * time.Second,
    }

    req, err := http.NewRequest("GET", "https://api.ejemplo.com/datos", nil)
    if err != nil {
        fmt.Println("Error al crear la solicitud:", err)
        return
    }

    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error en la solicitud:", err)
        return
    }
    defer resp.Body.Close()
    // Procesar la respuesta
}

Uso de contexto para cancelación y plazos

El uso del paquete context permite manejar cancelaciones y plazos de tiempo en solicitudes.

func solicitudConContexto() {
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    req, err := http.NewRequestWithContext(ctx, "GET", "https://api.ejemplo.com/lento", nil)
    if err != nil {
        fmt.Println("Error al crear la solicitud:", err)
        return
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("Error en la solicitud:", err)
        return
    }
    defer resp.Body.Close()
    // Procesar la respuesta
}

Implementación de HTTPS y manejo de certificados

Para servir contenido sobre HTTPS, se utilizan las funciones ListenAndServeTLS y se proporcionan los certificados SSL.

func main() {
    http.HandleFunc("/", manejadorSeguro)
    if err := http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", nil); err != nil {
        fmt.Println("Error al iniciar el servidor HTTPS:", err)
    }
}

Es importante gestionar correctamente los certificados y asegurar las conexiones para proteger la información transmitida.

Mejoras de rendimiento con HTTP/2

El soporte para HTTP/2 en Go es automático cuando se sirve sobre TLS usando ListenAndServeTLS. HTTP/2 mejora el rendimiento mediante multiplexación de solicitudes y reducción de latencia.

Consejos de seguridad en aplicaciones web

Al desarrollar aplicaciones web, es crucial seguir prácticas de seguridad para proteger el servicio y a los usuarios.

Validación y saneamiento de entradas

Siempre validar y sanear los datos recibidos de los usuarios para prevenir inyecciones y otros ataques.

import "html"

func manejadorSeguro(w http.ResponseWriter, r *http.Request) {
    entrada := r.FormValue("entrada")
    entradaSegura := html.EscapeString(entrada)
    fmt.Fprintf(w, "Entrada segura: %s", entradaSegura)
}

Uso de encabezados de seguridad

Establecer encabezados que indiquen a los navegadores cómo manejar el contenido.

func seguridadMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Strict-Transport-Se

Completa Go y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración