Quay lại blog

Cài đặt proxy trong Ruby qua Net::HTTP và Faraday: hướng dẫn đầy đủ cho Rails và script độc lập

Cách cấu hình proxy đúng cách trong các dự án Ruby thông qua Net::HTTP và Faraday - với ví dụ cho Rails và các script độc lập, xoay vòng IP và vượt qua các khối.

📅13 tháng 8, 2026
```html

Nếu bạn đang viết một parser, tích hợp API bên ngoài hoặc tự động hóa việc thu thập dữ liệu trên Ruby - sớm hay muộn bạn sẽ gặp phải các chặn theo IP. Wildberries, Ozon, Instagram và hàng chục dịch vụ khác cắt giảm các yêu cầu từ một địa chỉ sau vài trăm lần truy cập. Giải pháp duy nhất là - proxy. Trong bài viết này, chúng ta sẽ tìm hiểu cách kết nối proxy vào dự án Ruby thông qua Net::HTTP tiêu chuẩn và HTTP client phổ biến Faraday, thiết lập xoay vòng IP và xử lý lỗi một cách chính xác - như trong ứng dụng Rails, cũng như trong các script đơn giản.

Tại sao lập trình viên Ruby cần proxy: các kịch bản chính

Ruby được sử dụng rộng rãi cho các tác vụ mà không có proxy thì không thể thực hiện. Trước khi đi vào mã, bạn nên hiểu trong những tình huống nào chúng cần thiết - điều này sẽ giúp bạn chọn loại và kiến trúc giải pháp phù hợp.

Phân tích và thu thập dữ liệu. Đây là kịch bản phổ biến nhất. Bạn viết một script trên Ruby, truy cập các trang của Wildberries, Ozon hoặc Avito, thu thập giá cả và thông số kỹ thuật của sản phẩm. Nếu không có proxy, script như vậy sẽ bị chặn theo IP chỉ sau vài phút. Các trang web thấy hàng trăm yêu cầu từ một địa chỉ và tự động kích hoạt bảo vệ - captcha, cấm tạm thời hoặc từ chối hoàn toàn dịch vụ.

Tích hợp với API phụ thuộc vào địa lý. Một số dịch vụ bên ngoài trả về nội dung khác nhau tùy thuộc vào quốc gia gửi yêu cầu. Nếu ứng dụng Rails của bạn truy cập một API như vậy, proxy cho phép giả lập các yêu cầu từ khu vực cần thiết. Ví dụ, kiểm tra kết quả tìm kiếm cho các quốc gia khác nhau hoặc nhận giá cả phù hợp cho thị trường cụ thể.

Kiểm tra và QA. Các lập trình viên sử dụng proxy để kiểm tra hành vi của ứng dụng khi nhận yêu cầu từ các địa chỉ IP và quốc gia khác nhau. Điều này đặc biệt quan trọng đối với các dịch vụ có chặn địa lý hoặc giới hạn tần suất theo IP.

Tự động hóa marketing. Các script Ruby thường được sử dụng để theo dõi các chiến dịch quảng cáo, kiểm tra vị trí trong kết quả tìm kiếm hoặc theo dõi hoạt động của đối thủ. Ở đây, proxy cần thiết để phân phối tải và vượt qua các hạn chế.

Quản lý nhiều tài khoản. Nếu script của bạn quản lý nhiều tài khoản trên một nền tảng, mỗi tài khoản phải hoạt động qua một IP riêng biệt - nếu không, nền tảng sẽ dễ dàng phát hiện mối liên hệ và chặn tất cả ngay lập tức.

Chọn loại proxy nào cho các tác vụ Ruby

Không phải tất cả các proxy đều phù hợp cho các tác vụ khác nhau. Việc chọn loại proxy ảnh hưởng trực tiếp đến sự thành công của script của bạn. Hãy cùng xem xét các tùy chọn chính liên quan đến phát triển Ruby.

Loại proxy Tác vụ tốt nhất trong Ruby Tốc độ Vượt qua bảo vệ
Proxy trung tâm dữ liệu Phân tích mà không có bảo vệ nghiêm ngặt, yêu cầu API, kiểm tra Cao Trung bình
Proxy cư trú Phân tích các trang web bảo mật, làm việc với mạng xã hội, thị trường Trung bình Cao
Proxy di động Facebook, Instagram, TikTok API, làm việc với tài khoản Trung bình Tối đa

Proxy trung tâm dữ liệu - là lựa chọn nhanh nhất và rẻ nhất. Phù hợp cho việc phân tích các trang web không có bảo vệ nghiêm ngặt, yêu cầu API hàng loạt và kiểm tra tải. Tuy nhiên, các nền tảng lớn (Facebook, Google, Cloudflare) dễ dàng nhận diện chúng qua ASN của trung tâm dữ liệu.

Proxy cư trú sử dụng IP của người dùng thực. Đối với các script Ruby phân tích Wildberries, Ozon hoặc làm việc với các trang web bảo mật - đây là lựa chọn tối ưu. Các trang web thấy một người dùng bình thường, không phải là máy chủ.

Proxy di động hoạt động qua IP của các nhà mạng di động (4G/5G). Đây là những địa chỉ đáng tin cậy nhất từ góc độ các nền tảng - một IP di động có thể được hàng trăm người dùng thực sử dụng đồng thời, do đó việc chặn theo IP này rất hiếm. Nếu script Ruby của bạn làm việc với mạng xã hội hoặc các nền tảng quảng cáo - proxy di động sẽ giảm thiểu nguy cơ bị chặn đến mức tối thiểu.

Proxy trong Net::HTTP: thiết lập cơ bản

Net::HTTP - thư viện tiêu chuẩn của Ruby cho các yêu cầu HTTP, được bao gồm trong bản phân phối tiêu chuẩn của ngôn ngữ. Nó hỗ trợ proxy "ngay từ đầu" thông qua phương thức đặc biệt Net::HTTP::Proxy.

Cách đơn giản nhất là tạo một lớp proxy và sử dụng nó thay cho Net::HTTP thông thường:

require 'net/http'
require 'uri'

# Dữ liệu proxy
proxy_host = 'proxy.example.com'
proxy_port = 8080

# Tạo lớp proxy
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port)

# Thực hiện yêu cầu qua proxy
uri = URI('https://httpbin.org/ip')

proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
  request = Net::HTTP::Get.new(uri)
  response = http.request(request)
  puts response.body
end

Phương thức Net::HTTP::Proxy nhận bốn tham số: máy chủ proxy, cổng, tên người dùng và mật khẩu. Hai tham số đầu tiên là bắt buộc, hai tham số cuối cùng là tùy chọn cho các proxy không yêu cầu xác thực.

Cách thay thế là truyền các tham số proxy trực tiếp vào phương thức Net::HTTP.new:

require 'net/http'

uri = URI('https://httpbin.org/ip')

http = Net::HTTP.new(
  uri.host,
  uri.port,
  'proxy.example.com',  # proxy_addr
  8080,                  # proxy_port
  nil,                   # proxy_user (nil nếu không có xác thực)
  nil                    # proxy_pass
)

http.use_ssl = true

response = http.get(uri.path)
puts response.body

Cách tiếp cận này thuận tiện khi bạn cần tái sử dụng cùng một đối tượng HTTP cho nhiều yêu cầu đến một máy chủ. Lưu ý: các tham số proxy được truyền dưới dạng tham số thứ ba và thứ tư, không thông qua một phương thức riêng biệt.

Xác thực và HTTPS qua Net::HTTP

Hầu hết các proxy thương mại yêu cầu xác thực - tên đăng nhập và mật khẩu. Hơn nữa, khi làm việc với các trang web HTTPS cần có cấu hình SSL bổ sung. Hãy cùng xem xét cả hai trường hợp.

Proxy có tên đăng nhập và mật khẩu:

require 'net/http'
require 'uri'

proxy_host = 'proxy.example.com'
proxy_port = 8080
proxy_user = 'your_username'
proxy_pass = 'your_password'

# Tạo lớp proxy với xác thực
proxy_class = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass)

uri = URI('https://httpbin.org/ip')

proxy_class.start(uri.host, uri.port, use_ssl: true) do |http|
  # Tắt xác thực SSL (chỉ để thử nghiệm!)
  # http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  
  request = Net::HTTP::Get.new(uri)
  request['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
  
  response = http.request(request)
  puts "IP: #{response.body}"
  puts "Status: #{response.code}"
end

Một điểm quan trọng: khi sử dụng proxy HTTPS (tunneling qua CONNECT) Net::HTTP tự động thiết lập kết nối SSL với máy chủ đích qua proxy tunnel. Điều này hoạt động chính xác cho hầu hết các máy chủ proxy.

Cấu hình qua biến môi trường. Một thực hành tốt là không mã hóa dữ liệu proxy trong mã, mà đọc chúng từ các biến môi trường:

require 'net/http'
require 'uri'

# Đọc cấu hình proxy từ ENV
proxy_uri = URI(ENV.fetch('HTTP_PROXY', 'http://proxy.example.com:8080'))

proxy_class = Net::HTTP::Proxy(
  proxy_uri.host,
  proxy_uri.port,
  proxy_uri.user,
  proxy_uri.password
)

target_uri = URI('https://httpbin.org/ip')

proxy_class.start(target_uri.host, target_uri.port, use_ssl: true) do |http|
  response = http.get(target_uri.path)
  puts response.body
end

Biến môi trường có thể được đặt ở định dạng HTTP_PROXY=http://user:[email protected]:8080. Cách tiếp cận này cho phép thay đổi proxy mà không cần thay đổi mã - chỉ cần cập nhật biến trong .env hoặc trong cài đặt máy chủ.

Kết nối proxy qua Faraday

Faraday - một trong những HTTP client phổ biến nhất trong hệ sinh thái Ruby. Nó được sử dụng trong nhiều ứng dụng Rails nhờ vào cách tiếp cận middleware tiện lợi và hỗ trợ nhiều adapter khác nhau (Net::HTTP, HTTParty, Typhoeus và nhiều hơn nữa). Thiết lập proxy trong Faraday hơi khác nhau tùy thuộc vào adapter đang sử dụng.

Thiết lập cơ bản proxy trong Faraday:

require 'faraday'

# Tạo kết nối Faraday với proxy
conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
  faraday.proxy = {
    uri: 'http://proxy.example.com:8080',
    user: 'your_username',
    password: 'your_password'
  }
  
  faraday.headers['User-Agent'] = 'Mozilla/5.0 (compatible; MyBot/1.0)'
  faraday.adapter Faraday.default_adapter
end

response = conn.get('/ip')
puts response.body
puts "Status: #{response.status}"

Tham số faraday.proxy nhận một hash với các khóa uri, userpassword. Bạn cũng có thể truyền một chuỗi URI trực tiếp nếu proxy không yêu cầu xác thực.

Faraday với adapter Net::HTTP và cài đặt mở rộng:

require 'faraday'

conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
  faraday.proxy = 'http://user:[email protected]:8080'
  
  # Cài đặt thời gian chờ
  faraday.options.timeout = 30
  faraday.options.open_timeout = 10
  
  # Middleware cho việc ghi log (tiện lợi khi gỡ lỗi)
  faraday.response :logger
  
  # Retry khi có lỗi kết nối
  faraday.request :retry, max: 3, interval: 1
  
  # Adapter
  faraday.adapter :net_http
end

begin
  response = conn.get('/ip')
  puts response.body
rescue Faraday::ConnectionFailed => e
  puts "Lỗi kết nối: #{e.message}"
rescue Faraday::TimeoutError => e
  puts "Thời gian chờ: #{e.message}"
end

Middleware :retry đặc biệt hữu ích khi làm việc với proxy - nếu một địa chỉ tạm thời không khả dụng, Faraday sẽ tự động lặp lại yêu cầu. Điều này rất quan trọng cho việc hoạt động đáng tin cậy của script trong môi trường sản xuất.

Faraday với adapter Typhoeus (cho các yêu cầu song song):

# Gemfile: gem 'typhoeus'
require 'faraday'
require 'typhoeus/adapters/faraday'

conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
  faraday.proxy = 'http://user:[email protected]:8080'
  faraday.adapter :typhoeus
end

# Các yêu cầu song song qua proxy
responses = []
conn.in_parallel do
  responses << conn.get('/ip')
  responses << conn.get('/headers')
  responses << conn.get('/user-agent')
end

responses.each { |r| puts r.body }

Xoay vòng proxy: tự động thay đổi IP

Một địa chỉ proxy, ngay cả khi là cư trú, sớm hay muộn cũng sẽ bị giới hạn khi phân tích dữ liệu một cách liên tục. Giải pháp là - xoay vòng: tự động thay đổi IP sau mỗi yêu cầu hoặc qua các khoảng thời gian nhất định. Chúng ta sẽ triển khai một bộ xoay vòng đơn giản cho các script Ruby.

Bộ xoay vòng đơn giản dựa trên mảng proxy:

require 'net/http'
require 'uri'

class ProxyRotator
  def initialize(proxies)
    @proxies = proxies
    @index = 0
    @mutex = Mutex.new
  end

  def next_proxy
    @mutex.synchronize do
      proxy = @proxies[@index % @proxies.length]
      @index += 1
      proxy
    end
  end

  def random_proxy
    @proxies.sample
  end
end

# Danh sách proxy ở định dạng [host, port, user, pass]
proxies = [
  ['proxy1.example.com', 8080, 'user1', 'pass1'],
  ['proxy2.example.com', 8080, 'user2', 'pass2'],
  ['proxy3.example.com', 8080, 'user3', 'pass3'],
]

rotator = ProxyRotator.new(proxies)

# Phân tích danh sách URL qua các proxy khác nhau
urls = [
  'https://httpbin.org/ip',
  'https://httpbin.org/headers',
  'https://httpbin.org/user-agent'
]

urls.each do |url|
  proxy = rotator.next_proxy
  proxy_class = Net::HTTP::Proxy(proxy[0], proxy[1], proxy[2], proxy[3])
  
  uri = URI(url)
  
  begin
    proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
      http.read_timeout = 15
      response = http.get(uri.path)
      puts "#{url} -> Status: #{response.code}, Proxy: #{proxy[0]}"
    end
  rescue => e
    puts "Lỗi với proxy #{proxy[0]}: #{e.message}"
    # Tự động chuyển sang proxy tiếp theo
  end
  
  sleep(rand(0.5..2.0)) # Thời gian trễ ngẫu nhiên giữa các yêu cầu
end

Thời gian trễ ngẫu nhiên giữa các yêu cầu (sleep(rand(0.5..2.0))) - là một yếu tố quan trọng. Mô hình yêu cầu với các khoảng thời gian cố định dễ dàng bị phát hiện bởi các hệ thống chống bot. Thời gian trễ ngẫu nhiên mô phỏng hành vi của người dùng thực.

Xoay vòng qua Faraday với middleware:

require 'faraday'

class ProxyMiddleware < Faraday::Middleware
  PROXIES = [
    'http://user1:[email protected]:8080',
    'http://user2:[email protected]:8080',
    'http://user3:[email protected]:8080',
  ].freeze

  def call(env)
    # Chọn một proxy ngẫu nhiên cho mỗi yêu cầu
    proxy_uri = URI(PROXIES.sample)
    
    env[:request][:proxy] = {
      uri: proxy_uri,
      user: proxy_uri.user,
      password: proxy_uri.password
    }
    
    @app.call(env)
  end
end

# Đăng ký middleware
Faraday::Middleware.register_middleware proxy_rotator: ProxyMiddleware

conn = Faraday.new(url: 'https://httpbin.org') do |faraday|
  faraday.use :proxy_rotator
  faraday.adapter :net_http
end

5.times do
  response = conn.get('/ip')
  puts response.body
end

Tích hợp proxy vào ứng dụng Rails

Trong ứng dụng Rails, proxy thường cần thiết cho các yêu cầu HTTP bên ngoài: tích hợp với API, các tác vụ phân tích nền hoặc webhook. Hãy xem xét một số mẫu thực tiễn.

Mẫu 1: Đối tượng dịch vụ với Faraday. Tạo một lớp dịch vụ cơ bản, mà tất cả các yêu cầu HTTP bên ngoài đều thực hiện qua proxy:

# app/services/http_client.rb
class HttpClient
  def self.connection(base_url)
    Faraday.new(url: base_url) do |faraday|
      # Proxy từ các biến môi trường Rails
      if Rails.env.production? && ENV['PROXY_URL'].present?
        faraday.proxy = ENV['PROXY_URL']
      end
      
      faraday.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
      faraday.options.timeout = 30
      faraday.options.open_timeout = 10
      
      faraday.request :retry, max: 3, interval: 2,
                      exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError]
      
      faraday.response :raise_error
      faraday.adapter :net_http
    end
  end
end

# Sử dụng trong controller hoặc dịch vụ:
# client = HttpClient.connection('https://api.example.com')
# response = client.get('/products', { category: 'electronics' })

Mẫu 2: Cấu hình qua Rails credentials. Để lưu trữ dữ liệu proxy, hãy sử dụng credentials được mã hóa của Rails:

# config/credentials.yml.enc (chỉnh sửa qua rails credentials:edit)
# proxy:
#   host: proxy.example.com
#   port: 8080
#   username: your_user
#   password: your_pass

# app/services/proxy_service.rb
class ProxyService
  def self.faraday_proxy_config
    creds = Rails.application.credentials.proxy
    return nil unless creds
    
    {
      uri: "http://#{creds[:host]}:#{creds[:port]}",
      user: creds[:username],
      password: creds[:password]
    }
  end
  
  def self.net_http_proxy
    creds = Rails.application.credentials.proxy
    return Net::HTTP::Proxy(nil, nil) unless creds
    
    Net::HTTP::Proxy(
      creds[:host],
      creds[:port],
      creds[:username],
      creds[:password]
    )
  end
end

Mẫu 3: Các tác vụ nền với Sidekiq. Nếu việc phân tích hoặc yêu cầu API được thực hiện trong các worker nền, cấu hình proxy vẫn giữ nguyên, nhưng cần lưu ý đến tính cạnh tranh:

# app/workers/price_parser_worker.rb
class PriceParserWorker
  include Sidekiq::Worker
  
  sidekiq_options retry: 3, queue: :parsers
  
  def perform(product_url)
    # Tạo một kết nối mới cho mỗi worker
    proxy = ProxyService.net_http_proxy
    uri = URI(product_url)
    
    proxy.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
      http.read_timeout = 20
      
      request = Net::HTTP::Get.new(uri)
      request['User-Agent'] = random_user_agent
      
      response = http.request(request)
      
      if response.code == '200'
        parse_and_save(response.body, product_url)
      else
        Rails.logger.warn "Trạng thái không mong đợi #{response.code} cho #{product_url}"
      end
    end
  rescue Net::OpenTimeout, Net::ReadTimeout => e
    Rails.logger.error "Thời gian chờ cho #{product_url}: #{e.message}"
    raise # Sidekiq sẽ lặp lại tác vụ
  end
  
  private
  
  def random_user_agent
    agents = [
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
      'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
    ]
    agents.sample
  end
  
  def parse_and_save(html, url)
    # Logic phân tích...
  end
end

Xử lý lỗi và thời gian chờ

Làm việc qua proxy thêm một lớp bổ sung, có thể tạo ra các lỗi đặc thù. Xử lý ngoại lệ một cách khôn ngoan - đó là sự khác biệt giữa một script sẽ ngừng hoạt động sau 5 phút và một script hoạt động hàng giờ mà không cần can thiệp.

Các loại lỗi chính khi làm việc với proxy trong Ruby:

Ngoại lệ Nguyên nhân Phải làm gì
Net::OpenTimeout Proxy không phản hồi Thay đổi proxy, lặp lại
Net::ReadTimeout Proxy chậm hoặc trang web không phản hồi Tăng thời gian chờ hoặc thay đổi proxy
Errno::ECONNREFUSED Máy chủ proxy từ chối kết nối Kiểm tra dữ liệu proxy
OpenSSL::SSL::SSLError Vấn đề với SSL qua proxy Kiểm tra cài đặt SSL
HTTP 407 Tên đăng nhập/mật khẩu proxy không đúng Kiểm tra credentials
HTTP 403/429 IP bị chặn bởi trang web Thay đổi proxy, thêm thời gian nghỉ

Xử lý lỗi toàn diện với việc tự động thay đổi proxy:

require 'net/http'
require 'uri'

class RobustHttpClient
  MAX_RETRIES = 3
  RETRIABLE_ERRORS = [
    Net::OpenTimeout,
    Net::ReadTimeout,
    Errno::ECONNREFUSED,
    Errno::ECONNRESET,
    OpenSSL::SSL::SSLError
  ].freeze

  def initialize(proxies)
    @proxies = proxies.dup
    @failed_proxies = []
  end

  def get(url, retries: MAX_RETRIES)
    uri = URI(url)
    attempt = 0

    begin
      attempt += 1
      proxy = current_proxy
      proxy_class = Net::HTTP::Proxy(*proxy)

      proxy_class.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
        http.open_timeout = 10
        http.read_timeout = 20

        request = Net::HTTP::Get.new(uri)
        request['User-Agent'] = 'Mozilla/5.0 (compatible; RubyBot/1.0)'

        response = http.request(request)

        case response.code.to_i
        when 200..299
          response
        when 407
          raise "Xác thực proxy thất bại cho #{proxy[0]}"
        when 403, 429
          rotate_proxy!
          raise "IP bị chặn (#{response.code}), đang xoay vòng proxy"
        else
          raise "Trạng thái HTTP không mong đợi: #{response.code}"
        end
      end

    rescue *RETRIABLE_ERRORS => e
      Rails.logger.warn "Lỗi kết nối (cố gắng #{attempt}/#{retries}): #{e.message}"
      rotate_proxy!
      retry if attempt < retries
      raise "Thất bại sau #{retries} lần thử: #{e.message}"

    rescue RuntimeError => e
      Rails.logger.warn "Lỗi HTTP (cố gắng #{attempt}/#{retries}): #{e.message}"
      retry if attempt < retries
      raise
    end
  end

  private

  def current_proxy
    @proxies.first || raise("Không có proxy nào khả dụng!")
  end

  def rotate_proxy!
    failed = @proxies.shift
    @failed_proxies << failed
    Rails.logger.info "Đã xoay vòng proxy. Số lượng còn lại: #{@proxies.length}"
  end
end

Proxy SOCKS5 trong Ruby: thiết lập qua socksify

Net::HTTP tiêu chuẩn không hỗ trợ SOCKS5 một cách tự nhiên - chỉ hỗ trợ proxy HTTP/HTTPS. Để làm việc với SOCKS5, cần một thư viện bổ sung. Lựa chọn phổ biến nhất là gem socksify.

Tại sao SOCKS5 có thể được ưa chuộng hơn proxy HTTP? Giao thức SOCKS5 hoạt động ở mức thấp hơn - nó proxy bất kỳ lưu lượng TCP nào, không chỉ HTTP. Hơn nữa, SOCKS5 hỗ trợ xác thực và truyền ít siêu dữ liệu về yêu cầu, khiến nó ít bị phát hiện hơn bởi các hệ thống phát hiện bot.

# Gemfile
# gem 'socksify'

require 'socksify'
require 'socksify/http'
require 'net/http'
require 'uri'

# Cài đặt toàn cầu cho proxy SOCKS5
TCPSocket::socks_server = 'proxy.example.com'
TCPSocket::socks_port = 1080

# Tùy chọn: xác thực (SOCKS5 username/password)
# TCPSocket::socks_username = 'your_user'
# TCPSocket::socks_password = 'your_pass'

# Bây giờ tất cả các yêu cầu Net::HTTP đều đi qua SOCKS5
uri = URI('https://httpbin.org/ip')
response = Net::HTTP.get_response(uri)
puts response.body

Lưu ý: khi sử dụng socksify, cài đặt được áp dụng toàn cầu cho tất cả các kết nối TCP trong quá trình. Nếu bạn cần cài đặt linh hoạt hơn - hãy sử dụng Net::HTTP.SOCKSProxy từ gem đó:

require 'socksify/http'

# Tạo lớp proxy SOCKS5 (tương tự như Net::HTTP::Proxy cho HTTP)
socks_proxy = Net::HTTP.SOCKSProxy('proxy.example.com', 1080)

uri = URI('https://httpbin.org/ip')

socks_proxy.start(uri.host, uri.port, use_ssl: true) do |http|
  response = http.get(uri.path)
  puts response.body
end

Đối với Faraday với SOCKS5, bạn sẽ cần một adapter hỗ trợ giao thức này. Một lựa chọn tốt là faraday-net_http kết hợp với socksify, hoặc sử dụng adapter dựa trên curl faraday-typhoeus, mà hỗ trợ SOCKS5 một cách tự nhiên qua libcurl.

💡 Lời khuyên về việc chọn giao thức

Đối với hầu hết các tác vụ phân tích và làm việc với API, proxy HTTP/HTTPS là đủ - chúng dễ thiết lập và được hỗ trợ tự nhiên. SOCKS5 nên được sử dụng khi bạn cần proxy không chỉ lưu lượng HTTP, hoặc khi proxy HTTP dễ dàng bị phát hiện bởi dịch vụ mục tiêu. Proxy di động và cư trú có sẵn trong cả hai giao thức.

Kết luận và khuyến nghị

Thiết lập proxy trong Ruby không yêu cầu các thư viện phức tạp - Net::HTTP hỗ trợ proxy HTTP "ngay từ đầu", trong khi Faraday làm cho việc tích hợp trở nên thuận tiện hơn nhờ kiến trúc middleware. Những điểm chính từ hướng dẫn này:

  • Đối với Net::HTTP, hãy sử dụng Net::HTTP::Proxy - đây là cách tích hợp đáng tin cậy và tích hợp sẵn.
  • Đối với Faraday, tham số faraday.proxy nhận một chuỗi URI hoặc hash với credentials.
  • Lưu trữ dữ liệu proxy trong các biến môi trường hoặc credentials của Rails - không mã hóa trong mã.
  • Triển khai xoay vòng proxy và xử lý lỗi để đảm bảo hoạt động đáng tin cậy trong môi trường sản xuất.
  • Thêm thời gian trễ ngẫu nhiên và xoay vòng User-Agent để mô phỏng hành vi của con người.
  • Đối với SOCKS5, hãy sử dụng gem socksify.

Việc chọn loại proxy phụ thuộc vào tác vụ. Nếu bạn đang viết một parser cho Wildberries hoặc Ozon - proxy cư trú sẽ mang lại sự cân bằng tốt nhất giữa tốc độ và khả năng vượt qua bảo vệ: các IP thực của người dùng gia đình rất hiếm khi bị đưa vào danh sách chặn. Đối với các tác vụ có tải cao với khối lượng yêu cầu lớn đến các nguồn ít bảo vệ hơn, proxy trung tâm dữ liệu sẽ nhanh hơn và rẻ hơn tính theo yêu cầu. Nếu script Ruby của bạn làm việc với mạng xã hội hoặc API quảng cáo - hãy chú ý đến proxy di động: các địa chỉ IP của chúng có mức độ tin cậy cao nhất trên hầu hết các nền tảng.

```