Net::HTTP
Bài đăng này đã không được cập nhật trong 7 năm
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
Một vài ví dụ đơn giản
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
}
Kết luận
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
All rights reserved