12/08/2018, 15:54

Net::HTTP

Một HTTP client API của Ruby Net::HTTP cung cấp một thư viện rất mạnh, nó có thể sử dụng để xây dựng các HTTP user-agent. Để biết thêm về HTTP bạn hãy xem RFC2616. Net::HTTP được thiết kế để làm việc được với URI. URI::HTTP#host, URI::HTTP#port và URI::HTTP#request_uri được thiết kế để làm việc ...

Một HTTP client API của Ruby Net::HTTP cung cấp một thư viện rất mạnh, nó có thể sử dụng để xây dựng các HTTP user-agent. Để biết thêm về HTTP bạn hãy xem RFC2616. Net::HTTP được thiết kế để làm việc được với URI. URI::HTTP#host, URI::HTTP#port và URI::HTTP#request_uri được thiết kế để làm việc được với Net::HTTP. Nếu bạn chỉ thực hiện một vài yêu cầu GET, bạn nên thử OpenURI

Tất cả ví dụ này bạn nên tải Net::HTTP với lệnh:

require 'net/http'

Khi khai báo như trên thì chúng ta cũng đã tải uri. Vì vậy bạn không cần tải riêng.

GET

Net::HTTP.get('example.com', '/index.html') # => String

GET bởi URI

uri = URI('http://example.com/index.html?count=10')
Net::HTTP.get(uri) # => String

GET bởi những tham số động

uri = URI('http://example.com/index.html')
params = { :limit => 10, :page => 3 }
uri.query = URI.encode_www_form(params)

res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)

POST

uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => 'ruby', 'max' => '50')
puts res.body

POST cùng với nhiều giá trị

uri = URI('http://www.example.com/search.cgi')
res = Net::HTTP.post_form(uri, 'q' => ['ruby', 'perl'], 'max' => '50')
puts res.body

Làm thế nào để sử dụng Net::HTTP

Theo như ví dụ dưới đây, chúng ta có thể sử dụng HTTP user-agent để thực hiện nhiều loại request với các kết nối liên tục.

uri = URI('http://example.com/some_path?query=string')

Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new uri

  response = http.request request # Net::HTTPResponse object
end

::start ngay lập tức tạo ra kết nối đến một HTTP server và được giữ kết nối trong suốt thời gian của block. Kết nối được mở cho nhiều request trong khối nếu server có thể hỗ trợ các kết nối liên tục. Các request Net::HTTP hỗ trợ được liệt kê trong phần HTTP Request Classes bên dưới.

Nếu bạn muốn sử dụng lại HTTP request qua nhiều lần mà không tự động đóng thì bạn có thể sử dụng ::new thay cho :start. Request sẽ tự động mở một kết nối đến server nếu server chưa có kết nối. Bạn có thể đóng kết nối nếu đã kết thúc.

Đối với tất cả các đối tượng HTTP request và các phương thức request bạn có thể cung cấp một String của request path hoặc một URI trích xuất ra từ request path của Net::HTTP.

Dữ liệu trả về

uri = URI('http://example.com/index.html')
res = Net::HTTP.get_response(uri)

# Headers
res['Set-Cookie']            # => String
res.get_fields('set-cookie') # => Array
res.to_hash['set-cookie']    # => Array
puts "Headers: #{res.to_hash.inspect}"

# Status
puts res.code       # => '200'
puts res.message    # => 'OK'
puts res.class.name # => 'HTTPOK'

# Body
puts res.body if res.response_body_permitted?

Following Redirection

Mỗi đối tượng Net::HTTPResponse thuộc về một lớp cùng với response code của nó.

Ví dụ, tất cả các response 2XX là những instance của một lớp con Net::HTTPSuccess, response 3XX là một instance của một lớp con Net::HTTPRedirection và một response 200 là một instance của lớp Net::HTTPOK. Để biết chi tiết về các response, hãy xem phần HTTP Response Classes bên dưới.

Sử dụng case statement, bạn có thể xử lý được các loại response:

def fetch(uri_str, limit = 10)
  # You should choose a better exception.
  raise ArgumentError, 'too many HTTP redirects' if limit == 0

  response = Net::HTTP.get_response(URI(uri_str))

  case response
  when Net::HTTPSuccess then
    response
  when Net::HTTPRedirection then
    location = response['location']
    warn "redirected to #{location}"
    fetch(location, limit - 1)
  else
    response.value
  end
end

print fetch('http://www.ruby-lang.org')

POST

Một POST có thể được thực hiện bằng cách sử dụng lớp Net::HTTP::Post. Ví dụ tạo ra một body để post

uri = URI('http://www.example.com/todo.cgi')
req = Net::HTTP::Post.new(uri)
req.set_form_data('from' => '2005-01-01', 'to' => '2005-03-31')

res = Net::HTTP.start(uri.hostname, uri.port) do |http|
  http.request(req)
end

case res
when Net::HTTPSuccess, Net::HTTPRedirection
  # OK
else
  res.value
end

Tại thời điểm này, Net::HTTP không hỗ trợ multipart/form-data. Để gửi multipart/form-data sử dụng Net::HTTPGenericRequest#body= và Net::HTTPHeader#content_type=:

req = Net::HTTP::Post.new(uri)
req.body = multipart_data
req.content_type = 'multipart/form-data'

Những request khác có thể chứa một body giống như request PUT và cũng có thể tạo theo cùng một cách sử dụng lớp request tương ứng Net::HTTP::Put

Cài đặt Header

Ví dụ sau thực hiện một request GET sử dụng điều kiện If-Modified-Since ở header. Nếu như các file không được định nghĩa trong header thì sẽ không có Modified response được trả về.

uri = URI('http://example.com/cached_response')
file = File.stat 'cached_response'

req = Net::HTTP::Get.new(uri)
req['If-Modified-Since'] = file.mtime.rfc2822

res = Net::HTTP.start(uri.hostname, uri.port) {|http|
  http.request(req)
}

open 'cached_response', 'w' do |io|
  io.write res.body
end if res.is_a?(Net::HTTPSuccess)

Basic Authentication

Basic authentication được thực hiện theo như RFC2617

uri = URI('http://example.com/index.html?key=value')

req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'

res = Net::HTTP.start(uri.hostname, uri.port) {|http|
  http.request(req)
}
puts res.body

Streaming Response Bodies

Bởi theo mặc định Net::HTTP đọc toàn bộ response trả về vào bộ nhớ. Nếu bạn đang xử lý các tệp lớn bạn có thể truyền trực tiếp đến một IO

uri = URI('http://example.com/large_file')

Net::HTTP.start(uri.host, uri.port) do |http|
  request = Net::HTTP::Get.new uri

  http.request request do |response|
    open 'large_file', 'w' do |io|
      response.read_body do |chunk|
        io.write chunk
      end
    end
  end
end

HTTPS

HTTPS được bật cho kết nối HTTP bởi #use_ssl=.

uri = URI('https://secure.example.com/some_path?query=string')

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
  request = Net::HTTP::Get.new uri
  response = http.request request # Net::HTTPResponse object
end

Hoặc nếu bạn chỉ muốn thực hiện một request GET, bạn có thể truyền vào một đối tượng URI có HTTPS URL. Net::HTTP tự động bật TLS verification

uri = URI('https://example.com/')
Net::HTTP.get(uri) # => String

Trong những phiên bản trước của ruby, bạn cần phải require 'net/https' để sử dụng HTTPS. Nhưng bây giờ thì đã không cần thiết nữa.

Proxy

Net::HTTP sẽ tự động tạo ra một proxy từ biến môi trường http_proxy nếu nó tồn tại. Để vô hiệu hóa việc sử dụng http_proxy, bạn hãy truyền nil đến address proxy. Bạn cũng có thể tạo ra một custom proxy:

proxy_addr = 'your.proxy.host'
proxy_port = 8080

Net::HTTP.new('example.com', nil, proxy_addr, proxy_port).start { |http|
  # always proxy via your.proxy.addr:8080
}

Bài viết này mình dịch lại từ nguồn https://ruby-doc.org/stdlib-2.4.1/libdoc/net/http/rdoc/Net/HTTP.html rất mong nhận được đóng góp ý kiến của các bạn

0