برای یک کلاینت 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 هنگام استفادهٔ درخواستها نیز مشکلات همزمانی قابلاجتناب ایجاد میکند. transport اختصاصی مسیر را بخشی از تنظیمات همین کلاینت میکند.
http.ProxyURL انتخابگری برمیگرداند که همواره URL دادهشده را انتخاب میکند. این با انتخابگر محیطی پیشفرض که متغیرهای پراکسی و قواعد دور زدن را در نظر میگیرد متفاوت است. اگر قصد دارید یک ردیف مشخص از فهرست HTTP را آزمایش کنید، انتخابگر صریح این منشأ ابهام را حذف میکند.
پاسخ را ببندید و کلاینت را دوباره استفاده کنید
مثال بدنهٔ پاسخ را تا پایان میخواند و میبندد. خواندن کامل به transport کمک میکند در صورت امکان اتصال را دوباره استفاده کند. در برنامهای با چند درخواست از یک پراکسی، کلاینت و transport را نگه دارید، نه اینکه برای هر درخواست جفت تازهای بسازید.
مهلت کلاینت فقط باز کردن سوکت را پوشش نمیدهد؛ چرخهٔ عمر درخواست، از جمله خواندن بدنهٔ پاسخ، را هم محدود میکند. خطاهای خواندن پس از بازگشت Get نیز باید مدیریت شوند. وضعیتی مانند 403 خطای transport در Go نیست؛ پس StatusCode را جدا از err بررسی کنید.