Go

Go

Tutorial Go: Métodos HTTP con net/http

Go: métodos HTTP con net-http para desarrollar aplicaciones web realizando peticiones GET, POST, PUT, PATCH y DELETE. Aprende a manejar respuestas y errores en Golang.

Aprende Go GRATIS y certifícate

Realizar peticiones HTTP GET

Para realizar peticiones HTTP GET en Go, se utiliza el paquete net/http, que proporciona funciones para interactuar con servidores web. 

La función principal para realizar una petición GET es http.Get

Este método devuelve dos valores: un puntero a http.Response y un error. Es importante verificar siempre el error para manejar posibles fallos en la petición.

package main

import (
    "fmt"
    "io"
    "net/http"
)

func main() {
    response, err := http.Get("https://fakestoreapi.com/products")
    if err != nil {
        fmt.Println("Error realizando la petición:", err)
        return
    }
    defer response.Body.Close()

    body, err := io.ReadAll(response.Body)
    if err != nil {
        fmt.Println("Error leyendo la respuesta:", err)
        return
    }

    fmt.Println(string(body))
}

En este ejemplo, se realiza una solicitud GET a la URL https://fakestoreapi.com/products. La función defer se utiliza para asegurar que response.Body.Close() se llame al final de la función, liberando así los recursos asociados con la respuesta HTTP. Leer el cuerpo de la respuesta se hace mediante io.ReadAll, que devuelve el contenido completo del cuerpo en un []byte. Este byte slice se convierte a una cadena de texto para poder ser impreso.

El objeto http.Response contiene información valiosa sobre la respuesta HTTP, como el código de estado (StatusCode), el cuerpo de la respuesta (Body) y las cabeceras (Header). Es fundamental comprobar el StatusCode para asegurarse de que la petición se ha completado con éxito.

if response.StatusCode != http.StatusOK {
    fmt.Println("Error: estado no OK", response.StatusCode)
    return
}

Las cabeceras HTTP de la respuesta se encuentran en el campo Header del tipo http.Response. Estas cabeceras pueden proporcionar metadatos útiles sobre la respuesta, como el tipo de contenido (Content-Type) o la longitud del contenido (Content-Length). Un StatusCode en el rango 200-299 suele indicar éxito.

contentType := response.Header.Get("Content-Type")
fmt.Println("Tipo de contenido:", contentType)

El manejo adecuado de errores y la gestión de recursos son aspectos críticos al realizar peticiones HTTP. Asegúrate de cerrar siempre el cuerpo de la respuesta para evitar fugas de memoria.

Realizar peticiones HTTP POST

Para realizar peticiones HTTP POST en Go, el paquete net/http proporciona la función http.Post, que facilita el envío de datos a un servidor web. 

La función http.Post permite especificar la URL de destino, el tipo de contenido y un cuerpo que se envía en la solicitud. 

El método devuelve un puntero a http.Response y un error. Es esencial manejar el error adecuadamente para gestionar posibles fallos durante la solicitud.

package main

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
)

func main() {
    jsonData := []byte(`{"title":"foo","body":"bar","userId":1}`)
    response, err := http.Post("https://fakestoreapi.com/products", "application/json", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Println("Error realizando la petición:", err)
        return
    }
    defer response.Body.Close()

    body, err := io.ReadAll(response.Body)
    if err != nil {
        fmt.Println("Error leyendo la respuesta:", err)
        return
    }

    fmt.Println(string(body))
}

En este ejemplo, se realiza una solicitud POST a la URL https://fakestoreapi.com/products. Se envía un cuerpo JSON con los datos utilizando bytes.NewBuffer, que convierte el byte slice en un tipo adecuado para ser enviado en la solicitud. Verificar el código de estado de la respuesta es crucial para confirmar que la operación fue exitosa.

if response.StatusCode != http.StatusCreated {
    fmt.Println("Error: estado no Created", response.StatusCode)
    return
}

Es importante establecer correctamente el tipo de contenido en la cabecera Content-Type, que en este caso es application/json, para que el servidor interprete los datos de manera adecuada. Las cabeceras HTTP se pueden acceder a través del campo Header del tipo http.Response, lo que permite obtener información adicional sobre la respuesta.

location := response.Header.Get("Location")
fmt.Println("Recurso creado en:", location)

Para realizar una solicitud POST con mayor control sobre las cabeceras y el cuerpo, se puede utilizar http.NewRequest junto con http.Client

Este enfoque permite personalizar las cabeceras HTTP y gestionar la solicitud de manera más detallada.

package main

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
)

func main() {
    jsonData := []byte(`{"title":"foo","body":"bar","userId":1}`)
    client := &http.Client{}
    req, err := http.NewRequest("POST", "https://fakestoreapi.com/products", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Println("Error creando la solicitud:", err)
        return
    }
    req.Header.Set("Content-Type", "application/json")

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

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

    fmt.Println(string(body))
}

El uso de http.Client proporciona flexibilidad adicional, como la posibilidad de configurar tiempos de espera (Timeout) y gestionar cookies o redirecciones. Al igual que con las peticiones GET, es fundamental cerrar el cuerpo de la respuesta para evitar fugas de memoria. Además, el manejo adecuado de errores y la verificación del StatusCode son pasos críticos para asegurar el correcto funcionamiento de las peticiones HTTP POST.

Realizar peticiones HTTP PUT y PATCH

En Go, las peticiones HTTP PUT y PATCH se utilizan para modificar recursos existentes en un servidor. El paquete net/http proporciona las herramientas necesarias para implementar estos métodos. Una petición PUT se utiliza para actualizar un recurso completo, mientras que PATCH se centra en la modificación parcial de un recurso.

Para realizar una petición HTTP PUT, se puede utilizar la función http.NewRequest para crear una solicitud con el método PUT. Posteriormente, se utiliza un cliente HTTP para enviar la solicitud.

package main

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
)

func main() {
    jsonData := []byte(`{"title":"updated title","body":"updated body","userId":1}`)
    req, err := http.NewRequest(http.MethodPut, "https://fakestoreapi.com/products/1", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Println("Error creando la solicitud PUT:", err)
        return
    }
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error enviando la solicitud PUT:", err)
        return
    }
    defer resp.Body.Close()

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

    fmt.Println("Respuesta PUT:", string(body))
}

En este ejemplo, se crea una solicitud PUT para actualizar un producto con ID 1 en la API fakestoreapi.com. El cuerpo de la solicitud contiene datos JSON que representan el nuevo estado del recurso. Es crucial establecer la cabecera Content-Type a application/json para que el servidor interprete correctamente los datos enviados. Verificar el código de estado de la respuesta es esencial para confirmar que la operación se realizó con éxito.

Para realizar una petición HTTP PATCH, el proceso es similar, pero se cambia el método de la solicitud a PATCH. Esta técnica se utiliza cuando solo se requiere modificar ciertas partes de un recurso.

package main

import (
    "bytes"
    "fmt"
    "io"
    "net/http"
)

func main() {
    jsonData := []byte(`{"title":"partially updated title"}`)
    req, err := http.NewRequest(http.MethodPatch, "https://fakestoreapi.com/products/1", bytes.NewBuffer(jsonData))
    if err != nil {
        fmt.Println("Error creando la solicitud PATCH:", err)
        return
    }
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error enviando la solicitud PATCH:", err)
        return
    }
    defer resp.Body.Close()

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

    fmt.Println("Respuesta PATCH:", string(body))
}

En este caso, se envía una solicitud PATCH para modificar parcialmente el recurso. El cuerpo de la solicitud incluye solo el campo que se desea actualizar. Establecer correctamente las cabeceras es fundamental para asegurar que el servidor procese la solicitud adecuadamente.

En ambos casos, es importante gestionar los errores y cerrar el cuerpo de la respuesta para evitar fugas de memoria. Utilizar http.Client permite personalizar aspectos de la solicitud como tiempos de espera y manejo de redirecciones.

Realizar peticiones HTTP DELETE

En Go, para realizar peticiones HTTP DELETE, se utiliza el paquete net/http, que permite enviar solicitudes para eliminar recursos en un servidor. Para crear una solicitud DELETE, se emplea la función http.NewRequest, especificando el método http.MethodDelete. Una vez creada la solicitud, se utiliza un cliente HTTP para enviarla al servidor.

package main

import (
    "fmt"
    "net/http"
)

func main() {
    req, err := http.NewRequest(http.MethodDelete, "https://fakestoreapi.com/products/1", nil)
    if err != nil {
        fmt.Println("Error creando la solicitud DELETE:", err)
        return
    }

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error enviando la solicitud DELETE:", err)
        return
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        fmt.Println("Error: estado no OK", resp.StatusCode)
        return
    }

    fmt.Println("Recurso eliminado correctamente")
}

En este ejemplo, se envía una solicitud DELETE para eliminar un producto con ID 1 en la API fakestoreapi.com. Es esencial verificar el código de estado de la respuesta para confirmar que la operación se completó exitosamente.

El cuerpo de la solicitud DELETE generalmente es nil, ya que este tipo de peticiones no suelen requerir un cuerpo. Sin embargo, algunos servidores pueden aceptar un cuerpo con información adicional, aunque es menos común.

Es importante manejar adecuadamente los errores al crear y enviar la solicitud, así como cerrar el cuerpo de la respuesta con defer resp.Body.Close() para liberar los recursos asociados. La gestión de recursos y errores es crucial para evitar fugas de memoria y asegurar el funcionamiento correcto del cliente HTTP.

Las cabeceras HTTP pueden ser configuradas si es necesario. Aunque en la mayoría de las peticiones DELETE, las cabeceras adicionales no son requeridas, puedes utilizar el método Header.Set para establecer cabeceras específicas si el servidor lo demanda. La flexibilidad del paquete net/http permite ajustar las solicitudes según las necesidades del servidor con el que se interactúa.

Aprende Go GRATIS online

Todas las lecciones de Go

Accede a todas las lecciones de Go y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Go y certifícate

Certificados de superación de Go

Supera todos los ejercicios de programación del curso de Go y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  • Entender la funcionalidad y uso del paquete net/http en Go.
  • Realizar y gestionar peticiones HTTP GET, POST, PUT, PATCH y DELETE.
  • Manejar errores y recursos de respuesta adecuadamente.
  • Configurar y enviar solicitudes HTTP personalizadas con http.NewRequest.
  • Analizar y verificar los códigos de estado de las respuestas HTTP.
  • Personalizar las cabeceras HTTP para solicitudes HTTP específicas.