Окремий проксі для HTTP-клієнта Go
Клонуйте стандартний transport Go, задайте ProxyURL для обраного IP проксі й не змінюйте поведінку інших клієнтів.
Проксі обирає transport HTTP-клієнта Go. Перш ніж змінювати стандартний transport, клонуйте його, щоб інші користувачі типового клієнта зберегли свої маршрути.
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)
}
}
Адреса — заповнювач із документації. Замініть її справжніми IP і портом HTTP-проксі, наприклад кандидатом зі списку HTTP-проксі. Приклад використовує лише стандартну бібліотеку Go; для цього запиту через HTTP-проксі не потрібні ні пакет SOCKS, ні змінна середовища для всього процесу.
Чому не змінювати DefaultTransport безпосередньо?
Стандартний transport спільний. Його зміна може вплинути на код, який не збирався використовувати ваш проксі, а зміна під час запитів створює зайві проблеми одночасного доступу. Окремий transport робить маршрут частиною конфігурації саме цього клієнта.
http.ProxyURL повертає селектор, який завжди обирає переданий URL. Це відрізняється від типового селектора середовища, що враховує проксі-змінні й правила обходу. Якщо ви хочете перевірити один конкретний запис HTTP-списку, явний селектор прибирає це джерело неоднозначності.
Закрийте відповідь і використовуйте клієнт повторно
Приклад дочитує тіло відповіді й закриває його. Читання до кінця допомагає transport повторно використати з’єднання, коли це можливо. Якщо програма робить кілька запитів через один проксі, зберігайте клієнт і transport замість створення нової пари для кожного запиту.
Тайм-аут клієнта обмежує не лише відкриття сокета, а й життєвий цикл запиту, включно з читанням тіла відповіді. Помилки читання потрібно обробляти й після повернення Get. Статус на кшталт 403 — не помилка transport Go, тож перевіряйте StatusCode окремо від err.