Sử dụng Net :: HTTP.get cho url https


84

Tôi đang cố gắng sử dụng Net::HTTP.get()cho một URL https:

@data = Net::HTTP.get(uri, Net::HTTP.https_default_port())

Tuy nhiên, tôi nhận được kết quả sau khi tôi cố gắng in kết quả:

không thể chuyển đổi URI :: HTTPS thành Chuỗi

Thỏa thuận là gì? Tôi đang sử dụng Ruby 1.8.7 (OS X)


Chỉ là FYI, chúng tôi đang tạm thời kết nối với máy chủ của bên thứ 3 có vấn đề về chứng chỉ nên chúng tôi phải sử dụng IO.copy_stream( open( url, { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE } ), download_path )để vô hiệu hóa xác minh SSL. Trong trường hợp của chúng tôi, bảo mật không phải là vấn đề, máy chủ nằm ngoài tầm kiểm soát của chúng tôi và đó là giải pháp tạm thời.
Joshua Pinter

Câu trả lời:


156

Câu trả lời ban đầu:

uri = URI.parse("https://example.com/some/path")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
@data = http.get(uri.request_uri)

Như đã chỉ ra trong các bình luận, điều này là thanh lịch hơn:

require "open-uri"
@data = URI.parse("https://example.com/some/path").read

7
Tôi sẽ cho đây là câu trả lời vì đó là câu trả lời cho những gì tôi đã hỏi, nhưng câu trả lời thực sự là chỉ ra rằng tôi đang tiếp cận điều này một cách sai lầm. Sử dụng URI.parse(uri_string).readthay thế, hoạt động như vậy, rất đẹp.
Tony Stark

2
Không gì VERIFY_NONEcó nghĩa? Có thể nên làm gì để thay thế?
Jonathan Allard

1
đó là một cờ có nghĩa là tính xác thực của chứng chỉ bị bỏ qua, nhưng điều này đã xảy ra cách đây một thời gian nên tôi không chắc tại sao bạn cần đặt nó.
stef

2
@frabcus, bạn cần .read require 'open-uri'hoạt động.
Josh D

1
Câu hỏi của OP không có gì ngụ ý rằng xác minh SSL không được mong muốn, vậy tại sao bạn lại đề xuất VERIFY_NONE?
Alex

35

EDIT: tác phẩm Biện pháp của tôi, nhưng @ jason-yeo của phương pháp là xa dễ dàng hơn.

Có vẻ như 2.1.2 , phương pháp được lập thành văn bản được ưu tiên như sau (trích dẫn trực tiếp tài liệu ):

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

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

Net::HTTP.start(uri.host, uri.port,   
  :use_ssl => uri.scheme == 'https') do |http|
  request = Net::HTTP::Get.new uri

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

Trong các phiên bản trước của Ruby, bạn cần yêu cầu 'net / https' để sử dụng HTTPS. Điều này không còn đúng nữa.


6
Đây không phải là sự thật. Kể từ Ruby 2.0.0, Net::HTTP.getlà đủ để thực hiện một yêu cầu nhận HTTPS nếu đối tượng URI được chuyển qua một httpsurl. Xem câu trả lời của tôi: stackoverflow.com/a/36543895/382740 .
Jason Yeo

19

Trong Ruby 2.0.0 trở lên, chỉ cần truyền một đối tượng uri với httpsurl là đủ để thực hiện yêu cầu HTTPS.

uri = URI('https://encrypted.google.com')
Net::HTTP.get(uri)

Bạn có thể xác minh điều này bằng cách thực hiện yêu cầu nhận trên miền có chứng chỉ hết hạn.

uri = URI('https://expired.badssl.com/')
Net::HTTP.get(uri)
# OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed

Nó được giới thiệu bởi cam kết này trong Ruby 2.0.0.

Các get_responsephương pháp, mà được gọi bởi Net::HTTP.getphương pháp, đặt :use_ssl là true khi uri.schemelà "https".

Tuyên bố từ chối trách nhiệm: Tôi hiểu rằng câu hỏi dành cho Ruby 1.8.7, nhưng vì đây là một trong số ít kết quả tìm kiếm hàng đầu khi một người tìm kiếm "https ruby", nên tôi vẫn quyết định trả lời.


4
Về điểm dữ liệu, tôi thấy điều này không đúng trong ruby ​​2.2.10. Nó đã mở kết nối trên cổng 443, nhưng không sử dụng SSL. Tất nhiên, máy chủ nước ngoài sẽ không có gì để làm với nó, và đóng kết nối mà không có phản hồi, khiến tôi phải nghiến răng nghiến lợi. Tôi đã phải gọi http.use_ssl = trueđể buộc nó thực sự sử dụng ssl, và sau đó mọi thứ đã trôi đi.
David Hempy

4

cái này sẽ trông như sau:

uri.port = Net::HTTP.https_default_port()
@data = Net::HTTP.get(uri)

mà làm việc, nhưng bây giờ API bên ngoài được phàn nàn rằng tôi đã gửi một yêu cầu HTTP đơn giản để một HTTPS cổng ...
Tony Stark

haha, đúng không;) xem dưới đây giải pháp Stef cung cấp, nó cũng làm việc
Vlad Khomich

nó không, tôi nhận được một lỗi nói rằng "phương pháp xác định 'use_ssl ='"
Tony Stark

2
cố gắng cũng yêu cầu 'net / https'
Vlad Khomich
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.