Transportul unui client HTTP din Go alege proxy-ul. Clonează transportul standard înainte să îl modifici, astfel încât ceilalți utilizatori ai clientului implicit să își păstreze rutele existente.

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)
    }
}

Adresa este un exemplu de documentație. Înlocuiește-o cu IP-ul și portul unui proxy HTTP real, de exemplu un candidat din lista de proxy-uri HTTP. Exemplul folosește doar biblioteca standard Go; această cerere prin proxy HTTP nu are nevoie de un pachet SOCKS sau de o variabilă de mediu pentru întregul proces.

De ce să nu modifici direct DefaultTransport?

Transportul implicit este partajat. Modificarea lui poate schimba comportamentul codului care nu a cerut niciodată proxy-ul tău, iar schimbarea în timp ce cererile îl folosesc introduce probleme de concurență evitabile. Un transport dedicat face ruta parte din configurația acestui client.

http.ProxyURL întoarce un selector care alege mereu URL-ul furnizat. Este diferit de selectorul implicit de mediu, care ia în calcul variabilele proxy și regulile de ocolire. Dacă vrei să testezi o anumită intrare din lista HTTP, selectorul explicit elimină această sursă de ambiguitate.

Închide răspunsul și reutilizează clientul

Exemplul citește complet corpul răspunsului și îl închide. Citirea până la capăt ajută transportul să reutilizeze conexiunea când este posibil. Într-un program cu mai multe cereri prin același proxy, păstrează clientul și transportul în loc să creezi o pereche nouă pentru fiecare cerere.

Limita de timp a clientului acoperă mai mult decât deschiderea socketului: limitează și ciclul cererii, inclusiv citirea corpului răspunsului. Erorile de citire trebuie tratate și după ce Get revine. Un cod precum 403 nu este o eroare de transport Go, așa că verifică StatusCode separat de err.

Articole similare