กำหนดพร็อกซีเฉพาะให้ HTTP client ใน Go
โคลน transport เริ่มต้นของ Go แล้วตั้ง ProxyURL สำหรับ IP พร็อกซีที่เลือก เพื่อไม่ให้เปลี่ยนพฤติกรรมของไคลเอนต์อื่น
transport ของ HTTP client ใน 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