Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Thành thạo HTTP Request trong Ruby: Hướng dẫn hoàn chỉnh

Nếu muốn lấy thông tin từ website, hoặc submit form, upload file, v.v.

Bạn cần gửi HTTP request và xử lý response.

Bài này bạn học cách:

  • Làm HTTP request đơn giản với net/http
  • Gửi SSL request
  • Submit data với POST request
  • Gửi custom header
  • Chọn HTTP client tốt nhất cho tình huống

Làm nào!

Cách gửi HTTP Request

Ruby có built-in http client, gọi là net/http, dùng gửi bất kỳ request nào.

Ví dụ net/http:

 require 'net/http'
Net::HTTP.get('example.com', '/index.html') 

Này trả string HTML content trang.

Thường bạn muốn hơn HTML content.

Như HTTP response status.

Không có status bạn không biết request thành công hay fail.

Cách lấy status:

 response = Net::HTTP.get_response('example.com', '/')
response.code # 200 

Nếu muốn response content gọi method body:

 response.body 

Cách dùng Gem HTTParty

Nhiều gem làm dễ cho bạn.

Một gem là httparty.

Cách dùng:

 require 'httparty'
response = HTTParty.get('https://example.com')
response.code # 200
response.body # ... 

Lợi ích dùng HTTP gem:

  • Dễ dùng hơn.
  • Không có get_response riêng, get đã cho response object.
  • Như bạn thấy sau, họ làm SSL request transparent

Gửi SSL Request

Nếu thử gửi SSL request với net/http:

 Net::HTTP.get_response("example.com", "/", 443) 

Bạn nhận:

 Errno::ECONNRESET: Connection reset by peer 

Phải làm thế này:

 net = Net::HTTP.new("example.com", 443)
net.use_ssl = true
net.get_response("/") 

Tiết kiệm công sức, dùng gem 🙂

Cách Submit Data với Post Request

GET request dùng yêu cầu thông tin.

Như download ảnh, css, javascript…

Nhưng nếu muốn gửi thông tin dùng POST request.

Ví dụ:

 HTTParty.post("https://example.com/login", body: { user: "test@example.com", password: "chunky_bacon" }) 

Upload file cần multipart request, không supported bởi HTTParty.

Dùng rest-client gem:

 require 'rest-client'
RestClient.post '/profile', file: File.new('photo.jpg', 'rb') 

Hoặc Faraday gem:

 require 'faraday'
conn = Faraday.new do |f|
  f.request :multipart
  f.request :url_encoded
  f.adapter :net_http
end
file_io = Faraday::UploadIO.new('photo.jpg', 'image/jpeg')
conn.post('https://example.com/profile', file: file_io) 

Cách gửi Custom HTTP Headers

Bạn gửi custom header với HTTP request.

Giúp gửi thêm data với request, bao gồm:

  • Cookies
  • User-agent
  • Caching preferences
  • Content-type
  • Accept (để nhận JSON, hoặc khác)

Cách làm:

 Faraday.new('https://example.com', headers: { 'User-Agent' => 'test' }).get 

Tôi tạo Faraday object (dùng new), rồi gọi get.

Hoặc làm kiểu này:

 Faraday.post(
  "https://example.com/login/oauth/access_token",
  URI.encode_www_form(
    code: params[:code],
    client_id: ENV["example_client_id"],
    client_secret: ENV["example_client_secret"],
  ),
  { "Content-Type" => "application/x-www-form-urlencoded",
    "Accept" => "application/json" }
) 

Này chạy tốt cho OAuth request.

Chọn Best Ruby HTTP Client

Nhiều HTTP client Ruby.

Nên chọn cái nào?

Để giúp decide tôi chuẩn bị bảng so sánh.

Đây:

REPO STARS RECENT_COMMIT_COUNT LAST_COMMIT LATEST_RELEASE CREATED_DATE
lostisland/faraday 4817 26 2020-07-09 09:43:09 2020-03-29 13:46:47 2009-12-10 17:14:55
rest-client/rest-client 4913 0 2019-08-25 21:41:17 2019-08-21 22:50:21 2009-12-07 19:34:29
typhoeus/typhoeus 3739 2 2020-05-17 19:33:54 2020-01-15 16:24:17 2009-02-18 23:14:50
jnunemaker/httparty 5220 11 2020-06-10 18:40:13 2020-06-10 18:40:13 2008-07-28 20:55:11
excon/excon 1018 14 2020-06-30 11:30:12 2020-06-17 12:07:02 2009-10-25 17:50:46
httprb/http 2623 13 2020-03-30 12:34:38 2020-02-26 17:33:37 2011-10-06 04:19:10

Xem popularity và maintenance là bước đầu evaluate option.

Nhưng khác biệt kỹ thuật là gì?

Nhiều gem là wrapper quanh net/http:

  • excon
  • httparty
  • rest client

Trong khi Faraday là adapter gem, dùng implementation khác nhau.

Và Typhoeus wrapper C libcurl library.

Typhoeus cho Multi-Threading

Typhoeus hỗ trợ concurrent request không viết concurrent code.

Làm Typhoeus best choice nếu maximize requests/second.

Dùng Typhoeus multi-threading:

 require 'typhoeus'
hydra = Typhoeus::Hydra.hydra
request = Typhoeus::Request.new("https://www.rubyguides.com")
hydra.queue(request)
hydra.queue(request)
hydra.run 

Faraday Gem cho Adaptability

Faraday cho phép chọn implementation từ net/http, Typhoeus, rest-client từ cùng interface.

Mặc định net/http, đổi như sau:

 Faraday.default_adapter = :typhoeus 

Điều thú vị khác: Faraday hỗ trợ middleware.

Middleware như plugin modify request/response cách cụ thể.

Ví dụ:

 require 'faraday_middleware'
client = Faraday.new do |f|
  f.response :json
  f.adapter :net_http
end
client.get('https://api.github.com/repos/vmg/redcarpet/issues') 

Middleware này parse response JSON tự động.

Nếu muốn gửi JSON thay vì parse, dùng f.request :json thay f.response :json.

Faraday Video

Bonus: Cách Debug HTTP Request

Nếu muốn xem chính xác code gửi gì để chắc chắn chạy đúng…

…thì tôi có trick nhỏ.

Bạn dùng one-liner:

 ruby -rsocket -e "trap('SIGINT') { exit }; Socket.tcp_server_loop(8080) { |s,_| puts s.readpartial(1024); puts; s.puts 'HTTP/1.1 200'; s.close } 

Này tạo server port 8080 in mọi thứ nhận, trả HTTP status và close connection.

Bạn gửi request対 localhost:8080 xem chúng.

Như sau:

 Faraday.new('https://localhost:8080', headers: { 'User-Agent' => 'test', 'foo' => '1234' }).get
# GET / HTTP/1.1
# User-Agent: test
# Foo: 1234
# Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
# Accept: */*
# Connection: close
# Host: localhost:8080 

Option khác: gem httplog, hoặc tool mitmproxy.

Tóm tắt

Bạn học gửi mọi loại HTTP request, từ GET cơ bản lấy thông tin, đến POST submit thông tin.

Bạn xem overview gem Ruby phổ biến cho HTTP. Favorite của tôi faraday vì flexibility, nhưng chọn gem khác nếu fit needs hơn.

Nếu thích post hãy chia sẻ bạn bè để họ tận hưởng 🙂

Cảm ơn đã đọc!