Configura un proxy propio para un cliente HTTP de Go
Clona el transporte predeterminado de Go, establece ProxyURL para la IP elegida y evita cambiar el comportamiento de otros clientes.
El transporte del cliente HTTP de Go elige el proxy. Clona el transporte estándar antes de cambiarlo para que los demás usuarios del cliente predeterminado conserven sus rutas.
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"time"
)
func main() {
proxyURL, err := url.Parse("http://203.0.113.10:8080")
if err != nil {
log.Fatal(err)
}
transport := http.DefaultTransport.(*http.Transport).Clone()
transport.Proxy = http.ProxyURL(proxyURL)
defer transport.CloseIdleConnections()
client := &http.Client{
Transport: transport,
Timeout: 15 * time.Second,
}
response, err := client.Get("https://example.com/")
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
fmt.Println(response.StatusCode)
if _, err := io.Copy(io.Discard, response.Body); err != nil {
log.Fatal(err)
}
}
La dirección es un marcador de documentación. Sustitúyela por la IP y el puerto de un proxy HTTP real, por ejemplo un candidato de la lista de proxies HTTP. El ejemplo solo usa la biblioteca estándar de Go; esta petición mediante proxy HTTP no necesita un paquete SOCKS ni una variable de entorno para todo el proceso.
¿Por qué no cambiar DefaultTransport directamente?
El transporte predeterminado es compartido. Modificarlo puede cambiar el comportamiento de código que nunca pidió usar tu proxy, y hacerlo mientras hay peticiones utilizándolo introduce problemas de concurrencia evitables. Un transporte dedicado hace que la ruta forme parte de la configuración de este cliente.
http.ProxyURL devuelve un selector que siempre elige la URL indicada. Es distinto del selector de entorno predeterminado, que considera las variables de proxy y las reglas de exclusión. Si quieres probar una entrada concreta de la lista HTTP, el selector explícito elimina esa fuente de ambigüedad.
Cierra la respuesta y reutiliza el cliente
El ejemplo lee todo el cuerpo de la respuesta y lo cierra. Leerlo hasta el final ayuda al transporte a reutilizar la conexión cuando es posible. Si el programa hace varias peticiones por el mismo proxy, conserva el cliente y el transporte en vez de crear un par nuevo para cada petición.
El tiempo límite del cliente no solo cubre la apertura del socket; también limita el ciclo de la petición, incluida la lectura del cuerpo de respuesta. Debes seguir gestionando los errores de lectura después de que Get retorne. Un estado como 403 no es un error del transporte de Go, así que revisa StatusCode por separado de err.