使用 Ruby 发送自定义 HTTP headers
Sending custom HTTP headers with Ruby
我想连同 HTTP 请求一起发送自定义 header。
我根据 ruby-doc, Net::HTTP, Setting Headers 中的示例创建了以下内容,但我的版本因 "Connection reset by peer":
而失败
#!/usr/bin/env ruby -w
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html' # Added
FileUtils.touch(cached_response) unless File.exist?(cached_response) # Added
uri = URI("https://www.apple.com/#{cached_response}") # Changed
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)
但是,不使用自定义 header 发送也能正常工作:
#!/usr/bin/env ruby -w
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html'
uri = URI("https://www.apple.com/#{cached_response}")
FileUtils.touch(cached_response) unless File.exist?(cached_response)
file = File.stat cached_response
req = Net::HTTP::Get.new(uri) # Ignored
req['If-Modified-Since'] = file.mtime.rfc2822 # Ignored
res = Net::HTTP.get_response(uri) # Changed
open cached_response, 'w' do |io|
io.write res.body
end if res.is_a?(Net::HTTPSuccess)
有人可以解释为什么我的示例 Ruby 代码的实现不起作用吗?
我在几个 Sinatra 路由中添加了类似的代码:
get '/test1' do
uri = URI('https://www.apple.com/index.html')
req = Net::HTTP::Get.new(uri)
req['Accept'] = request.env['HTTP_ACCEPT']
res = Net::HTTP.start(uri.hostname, uri.port) { |h| h.request(req) }
headers = res.to_hash
headers.delete('transfer-encoding')
[res.code.to_i, headers, res.body]
end
然后
get '/test2' do
uri = URI('https://www.apple.com/index.html')
res = Net::HTTP.get_response(uri)
headers = res.to_hash
headers.delete('transfer-encoding')
[res.code.to_i, headers, res.body]
end
使用 /test1,我得到
curl -iv 'http://localhost:9292/test1'
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> GET /test1 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
HTTP/1.1 500 Internal Server Error
< Content-Type: text/plain
Content-Type: text/plain
< Content-Length: 5582
Content-Length: 5582
< Server: WEBrick/1.4.2 (Ruby/2.5.0/2018-12-06)
Server: WEBrick/1.4.2 (Ruby/2.5.0/2018-12-06)
< Date: Sat, 22 Dec 2018 16:51:03 GMT
Date: Sat, 22 Dec 2018 16:51:03 GMT
< Connection: Keep-Alive
Connection: Keep-Alive
<
EOFError: end of file reached
...
* Connection #0 to host localhost left intact
使用 /test2,我得到
curl -iv 'http://localhost:9292/test2'
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> GET /test2 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
...
<etc. HTML written to console>
看起来请求 header 是相同的。相同的四行。
如果我将 Accept header 添加到 curl 命令,请求 Accept header 将按预期更改,并且两者 return 的结果与以前相同 (/test1: 500;/test2:200)
curl -iv -H 'Accept: application/json' 'http://localhost:9292/test2'
...
> GET /test2 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: application/json
终于想通了。设置 HTTP 请求时,使用 'https' 方案不会自动启用 TLS/SSL。您必须在请求开始之前明确地执行此操作。这是我的更新版本:
#!/usr/bin/env ruby -w
# frozen_string_literal: true
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html' # Added
FileUtils.touch cached_response unless File.exist? cached_response # Added
uri = URI("https://www.apple.com/#{cached_response}") # Changed
file = File.stat cached_response
req = Net::HTTP::Get.new(uri)
req['If-Modified-Since'] = file.mtime.rfc2822
http = Net::HTTP.new(uri.hostname, uri.port) # Added
http.use_ssl = uri.scheme == 'https' # Added
res = http.start { |h| h.request(req) } # Changed
if res.is_a?(Net::HTTPSuccess)
File.open cached_response, 'w' do |io|
io.write res.body
end
end
我想连同 HTTP 请求一起发送自定义 header。 我根据 ruby-doc, Net::HTTP, Setting Headers 中的示例创建了以下内容,但我的版本因 "Connection reset by peer":
而失败#!/usr/bin/env ruby -w
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html' # Added
FileUtils.touch(cached_response) unless File.exist?(cached_response) # Added
uri = URI("https://www.apple.com/#{cached_response}") # Changed
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)
但是,不使用自定义 header 发送也能正常工作:
#!/usr/bin/env ruby -w
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html'
uri = URI("https://www.apple.com/#{cached_response}")
FileUtils.touch(cached_response) unless File.exist?(cached_response)
file = File.stat cached_response
req = Net::HTTP::Get.new(uri) # Ignored
req['If-Modified-Since'] = file.mtime.rfc2822 # Ignored
res = Net::HTTP.get_response(uri) # Changed
open cached_response, 'w' do |io|
io.write res.body
end if res.is_a?(Net::HTTPSuccess)
有人可以解释为什么我的示例 Ruby 代码的实现不起作用吗?
我在几个 Sinatra 路由中添加了类似的代码:
get '/test1' do
uri = URI('https://www.apple.com/index.html')
req = Net::HTTP::Get.new(uri)
req['Accept'] = request.env['HTTP_ACCEPT']
res = Net::HTTP.start(uri.hostname, uri.port) { |h| h.request(req) }
headers = res.to_hash
headers.delete('transfer-encoding')
[res.code.to_i, headers, res.body]
end
然后
get '/test2' do
uri = URI('https://www.apple.com/index.html')
res = Net::HTTP.get_response(uri)
headers = res.to_hash
headers.delete('transfer-encoding')
[res.code.to_i, headers, res.body]
end
使用 /test1,我得到
curl -iv 'http://localhost:9292/test1'
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> GET /test1 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
HTTP/1.1 500 Internal Server Error
< Content-Type: text/plain
Content-Type: text/plain
< Content-Length: 5582
Content-Length: 5582
< Server: WEBrick/1.4.2 (Ruby/2.5.0/2018-12-06)
Server: WEBrick/1.4.2 (Ruby/2.5.0/2018-12-06)
< Date: Sat, 22 Dec 2018 16:51:03 GMT
Date: Sat, 22 Dec 2018 16:51:03 GMT
< Connection: Keep-Alive
Connection: Keep-Alive
<
EOFError: end of file reached
...
* Connection #0 to host localhost left intact
使用 /test2,我得到
curl -iv 'http://localhost:9292/test2'
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> GET /test2 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
...
<etc. HTML written to console>
看起来请求 header 是相同的。相同的四行。
如果我将 Accept header 添加到 curl 命令,请求 Accept header 将按预期更改,并且两者 return 的结果与以前相同 (/test1: 500;/test2:200)
curl -iv -H 'Accept: application/json' 'http://localhost:9292/test2'
...
> GET /test2 HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.54.0
> Accept: application/json
终于想通了。设置 HTTP 请求时,使用 'https' 方案不会自动启用 TLS/SSL。您必须在请求开始之前明确地执行此操作。这是我的更新版本:
#!/usr/bin/env ruby -w
# frozen_string_literal: true
require 'fileutils'
require 'net/http'
require 'time'
cached_response = 'index.html' # Added
FileUtils.touch cached_response unless File.exist? cached_response # Added
uri = URI("https://www.apple.com/#{cached_response}") # Changed
file = File.stat cached_response
req = Net::HTTP::Get.new(uri)
req['If-Modified-Since'] = file.mtime.rfc2822
http = Net::HTTP.new(uri.hostname, uri.port) # Added
http.use_ssl = uri.scheme == 'https' # Added
res = http.start { |h| h.request(req) } # Changed
if res.is_a?(Net::HTTPSuccess)
File.open cached_response, 'w' do |io|
io.write res.body
end
end