Как работает поддержка HTTP-операций?ruby-79

Ruby предлагает несколько способов работы с HTTP, от низкоуровневых сокетов до высокоуровневых клиентских библиотек. Рассмотрим основные подходы.

1. Низкоуровневый подход

require 'socket'

socket = TCPSocket.new('example.com', 80)
request = [
  "GET / HTTP/1.1",
  "Host: example.com",
  "Connection: close",
  "\r\n"
].join("\r\n")

socket.write(request)
response = socket.read
socket.close

puts response.split("\r\n\r\n", 2).last # Тело ответа

2. Стандартная библиотека Net::HTTP

Базовый пример GET-запроса:

require 'net/http'

uri = URI('https://example.com/api/v1/users')
response = Net::HTTP.get_response(uri)

puts response.code       # "200"
puts response.body       # Тело ответа

POST-запрос с JSON:

require 'net/http'
require 'json'

uri = URI('https://example.com/api/v1/users')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'

request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = { user: { name: 'John' } }.to_json

response = http.request(request)
puts JSON.parse(response.body)

3. Популярные HTTP-клиенты

a) HTTParty

require 'httparty'

class MyClient
  include HTTParty
  base_uri 'https://api.example.com'

  def get_user(id)
    self.class.get("/users/#{id}")
  end
end

response = MyClient.new.get_user(1)
puts response.parsed_response

b) Faraday

require 'faraday'

conn = Faraday.new(
  url: 'https://api.example.com',
  headers: { 'Content-Type' => 'application/json' }
) do |f|
  f.request :json
  f.response :json
  f.adapter Faraday.default_adapter
end

response = conn.post('/users') do |req|
  req.body = { name: 'John' }
end

puts response.body

c) Async HTTP

require 'async/http/internet'

Async do
  internet = Async::HTTP::Internet.new
  response = internet.get("https://example.com")

  puts response.status
  puts response.read
ensure
  internet.close
end

4. HTTP-серверы в Ruby

a) WEBrick

require 'webrick'

server = WEBrick::HTTPServer.new(Port: 8000)

server.mount_proc '/' do |req, res|
  res.body = "Hello, world! Method: #{req.request_method}"
end

trap('INT') { server.shutdown }
server.start

b) Rack

require 'rack'

app = Proc.new do |env|
  [
    200,
    { 'Content-Type' => 'text/plain' },
    ["Hello from Rack!"]
  ]
end

Rack::Handler::WEBrick.run(app, Port: 3000)

c) Sinatra

require 'sinatra'

get '/' do
  'Hello World!'
end

post '/users' do
  # Создание пользователя
  status 201
end

5. Обработка ошибок и ретраи

require 'net/http'

def safe_request
  retries ||= 0
  uri = URI('https://example.com')
  response = Net::HTTP.get_response(uri)

  case response
  when Net::HTTPSuccess
    response.body
  when Net::HTTPRedirection
    follow_redirect(response['Location'])
  else
    raise "HTTP error: #{response.code}"
  end
rescue Timeout::Error, Errno::ECONNRESET => e
  if (retries += 1) < 3
    sleep 1
    retry
  else
    raise "Failed after 3 retries: #{e.message}"
  end
end

6. Продвинутые возможности

a) Потоковая обработка

uri = URI('https://example.com/large-file')
Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new(uri)

  http.request(request) do |response|
    response.read_body do |chunk|
      process_chunk(chunk) # Обработка по частям
    end
  end
end

b) Поддержка HTTP/2

require 'http/2'
require 'socket'

socket = TCPSocket.new('example.com', 443)
conn = HTTP2::Client.new
conn.on(:frame) { |bytes| socket.write(bytes) }

socket.sync = true
while !socket.eof?
  conn << socket.readpartial(1024)
end

Резюмируем

Поддержка HTTP в Ruby включает:

  1. Клиентские библиотеки:

    • Net::HTTP (встроенный)
    • HTTParty, Faraday, Async::HTTP
    • Специализированные (RestClient, Typhoeus)
  2. Серверные решения:

    • WEBrick (базовый)
    • Rack (стандартный интерфейс)
    • Sinatra, Rails (фреймворки)
  3. Ключевые особенности:

    • Поддержка HTTPS через OpenSSL
    • Возможность тонкой настройки
    • Асинхронные варианты (Ruby 3+)
    • Поддержка REST, GraphQL, WebSockets

Рекомендации:

  • Для простых запросов: HTTParty
  • Для гибкости: Faraday
  • Для современных приложений: Async::HTTP
  • Для серверов: Rack-совместимые фреймворки

Помните про:

  • Обработку ошибок
  • Таймауты
  • Пул соединений для высоконагруженных приложений
  • Безопасность (HTTPS, проверку сертификатов)