Интеграции · Средний

Прокси в Go и PHP: net/http Transport, x/net/proxy, cURL и Guzzle

В обоих языках прокси задаётся на транспортном уровне, где как раз определяется ротация IP и повторное использование соединений. По два приёма для каждого языка дают точный контроль над выходным узлом.

2 минуты чтения 6 разделов Обновлено Опубликовано

Go: http.Transport#

Go
package main

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

func main() {
	proxyURL, _ := url.Parse("http://USER-cc-us:[email protected]:9000")
	client := &http.Client{
		Timeout: 45 * time.Second,
		Transport: &http.Transport{
			Proxy:             http.ProxyURL(proxyURL),
			DisableKeepAlives: true, // новое соединение = новый выходной узел на шлюзе с ротацией IP
		},
	}
	resp, err := client.Get("https://api.ipify.org")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)
	fmt.Println(string(body))
}

Для работы с закреплённой сессией оставьте DisableKeepAlives со значением по умолчанию (false): транспорт повторно использует соединения, а значит, и выходной узел. При параллельной работе с закреплёнными сессиями используйте отдельный Transport для каждого идентификатора сессии.

Go: выбор прокси для каждого запроса#

Go
tr := &http.Transport{
	Proxy: func(r *http.Request) (*url.URL, error) {
		sid := r.Header.Get("X-Session") // собственная подсказка, которая не отправляется прокси
		r.Header.Del("X-Session")
		return url.Parse(fmt.Sprintf("http://USER-cc-de-sid-%s-ttl-10m:[email protected]:9000", sid))
	},
}

Go: SOCKS5#

Go
import "golang.org/x/net/proxy"

dialer, err := proxy.SOCKS5("tcp", "res.hodlproxy.com:9001", &proxy.Auth{User: "USER-cc-us", Password: "PASS"}, proxy.Direct)
if err != nil { panic(err) }
tr := &http.Transport{Dial: dialer.Dial}
client := &http.Client{Transport: tr, Timeout: 45 * time.Second}

PHP: cURL#

PHP
<?php
$ch = curl_init("https://api.ipify.org");
curl_setopt_array($ch, [
    CURLOPT_PROXY          => "http://res.hodlproxy.com:9000",
    CURLOPT_PROXYUSERPWD   => "USER-cc-us:PASS",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 15,
    CURLOPT_TIMEOUT        => 45,
    CURLOPT_FORBID_REUSE   => true, // новый выходной узел при каждом вызове на шлюзе с ротацией IP
]);
echo curl_exec($ch);

// SOCKS5 с удалённым разрешением DNS
curl_setopt($ch, CURLOPT_PROXY, "res.hodlproxy.com:9001");
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);

PHP: Guzzle#

PHP
<?php
use GuzzleHttp\Client;

$sticky = "http://USER-cc-de-city-berlin-sid-cart42-ttl-15m:[email protected]:9000";
$client = new Client(['proxy' => $sticky, 'timeout' => 45, 'connect_timeout' => 15]);

$r = $client->get('https://api.ipify.org');
echo $r->getBody();

Контрольный список#

  • Повторно используйте соединения в последовательностях с закреплённой сессией и отключайте повторное использование для интенсивной ротации IP.
  • Выбирайте тайм-ауты с учётом типа выходного узла; при транспортных ошибках выполняйте одну повторную попытку.
  • Никогда не записывайте URL прокси в журнал: он содержит пароль. Вместо него записывайте идентификатор сессии.

Частые вопросы#

Работает ли http.ProxyFromEnvironment в Go?

Да: экспортируйте HTTPS_PROXY и HTTP_PROXY с URL HodlProxy и используйте http.ProxyFromEnvironment как функцию Proxy объекта Transport. Переменная NO_PROXY исключает локальные хосты.

Можно начинать

Попробуйте на практике.

Создайте аккаунт, пополните баланс на $20 и вставьте конечную точку из этого руководства в свой инструмент. Срок действия оплаченного трафика не ограничен.