Ruby HTTPClient
最后修改于 2023 年 10 月 18 日
在本文中,我们将介绍如何使用 Ruby HTTPClient 模块。我们将获取数据、发送数据、处理 Cookie 以及连接到安全的网页。ZetCode 还有一个简洁的Ruby 教程。
超文本传输协议 (HTTP) 是一种用于分布式、协作式、超媒体信息系统的应用协议。HTTP 是万维网数据通信的基础。
Ruby HTTPClient
提供了通过 HTTP 访问 Web 资源的各种方法。该 gem 由 Hiroshi NAKAMURA 创建。
$ sudo gem install httpclient
可以使用 sudo gem install httpclient
命令安装该模块。
Ruby HTTPClient 版本
第一个程序打印出库和 Ruby 语言的版本。
#!/usr/bin/ruby require 'httpclient' puts HTTPClient::LIB_NAME puts HTTPClient::RUBY_VERSION_STRING puts HTTPClient::VERSION
这三个常量提供了库和 Ruby 的版本号。
$ ./version.rb (2.8.3, ruby 2.7.2 (2020-10-01)) ruby 2.7.2 (2020-10-01) 2.8.3
这是该示例的示例输出。
Ruby HTTPClient get_content 函数
get_content
是一个高级方法,用于获取由给定 URL 标识的文档。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new cont = client.get_content 'http://webcode.me' puts cont
该脚本抓取 webcode.me
网页的内容。
cont = client.get_content 'http://webcode.me'
get_content
方法将结果作为一个字符串返回。
$ ./get_content.rb <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My html page</title> </head> <body> <p> Today is a beautiful day. We go swimming and fishing. </p> <p> Hello there. How are you? </p> </body> </html>
这是 get_content.rb
脚本的输出。
以下程序获取一个小型网页并去除其 HTML 标签。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new client.get_content('http://webcode.me') do |chunk| puts chunk.gsub(%r{</?[^>]+?>}, '') end
该脚本会剥离 webcode.me
网页的 HTML 标签。
client.get_content('http://webcode.me') do |chunk| puts chunk.gsub(%r{</?[^>]+?>}, '') end
使用一个简单的正则表达式来剥离 HTML 标签。在此上下文中,get_content
方法以字符串块的形式返回内容。
Ruby HTTPClient 请求
HTTP 请求(HTTP request)是从客户端发送到浏览器以检索信息或执行某些操作的消息。
HTTPClient
的 request
方法创建一个新请求。请注意,HTTPClient
类具有 get
、post
或 put
等方法,这些方法可以为我们节省一些输入。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new method = 'GET' url = URI.parse 'http://webcode.me' res = client.request method, url puts res.body
该示例创建了一个 GET 请求并将其发送到 http://webcode.me
。
method = 'GET' url = URI.parse 'http://webcode.me'
我们创建了一个请求方法和 URL。
res = client.request method, url
使用 request
方法进行请求。
puts res.body
响应消息的 body
属性包含消息正文。
Ruby HTTPClient 状态
HTTP::Message
表示一个 HTTP 请求或响应。它的 status
方法返回响应的 HTTP 状态码。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'http://webcode.me' puts res.status puts HTTP::Status::successful? res.status res = client.get 'http://webcode.me/news/' puts res.status puts HTTP::Status::successful? res.status
我们使用 get
方法执行三个 HTTP 请求并检查返回的状态。
puts HTTP::Status::successful? res.status
HTTP::Status::successful?
方法用于判断状态码是否表示成功。
$ ./status.rb 200 true 404 false
200 是成功的 HTTP 请求的标准响应,404 表示找不到请求的资源。
head 方法
head
方法检索文档头信息。头信息由字段组成,包括日期、服务器、内容类型或最后修改时间。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.head 'http://webcode.me' puts "Server: " + res.header['Server'][0] puts "Last modified: " + res.header['Last-Modified'][0] puts "Content type: " + res.header['Content-Type'][0] puts "Content length: " + res.header['Content-Length'][0]
该示例打印出 http://webcode.me
网页的服务器、最后修改时间、内容类型和内容长度。
$ ./head.rb Server: nginx/1.6.2 Last modified: Sat, 20 Jul 2019 11:49:25 GMT Content type: text/html Content length: 348
这是 head.rb
程序的输出。
get 方法
get
方法向服务器发出 GET 请求。GET 方法请求指定资源的表示形式。
<?php echo "Hello " . htmlspecialchars($_GET['name']);
greet.php
返回从客户端获取的 name
变量的值。htmlspecialchars
函数将特殊字符转换为 HTML 实体;例如,& 转换为 &。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'https://:8000/greet.php?name=Jan' puts res.body
该脚本将一个带有值的变量发送到服务器上的 PHP 脚本。变量直接在 URL 中指定。
$ php -S localhost:8000 -t public
我们启动内置的 Web 服务器。
$ ./mget.rb Hello Jan
这是示例的输出。
get
方法接受第二个参数,我们可以在其中指定查询参数。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new query = {'name' => 'Jan'} res = client.get 'https://:8000/greet.php', query puts res.body
该示例与上一个基本相同。
$ ./mget2.rb Hello Jan
这是示例的输出。
Ruby HTTPClient 重定向
重定向(Redirection)是将一个 URL 转发到另一个 URL 的过程。HTTP 响应状态码 301 Moved Permanently 用于永久 URL 重定向。
在下面的示例中,我们使用了 nginx
Web 服务器。
location = /oldpage.html { return 301 /newpage.html; }
将这些行添加到 nginx 配置文件中,该文件在 Debian 上位于 /etc/nginx/sites-available/default
。
$ sudo service nginx restart
编辑完文件后,我们必须重新启动 nginx 才能应用更改。
<!DOCTYPE html> <html> <head> <title>New page</title> </head> <body> <p> This is a new page </p> </body> </html>
这是位于 nginx 文档根目录下的 newpage.html
文件。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'https:///oldpage.html', :follow_redirect => true puts res.body
此脚本访问旧页面并跟随重定向。
res = client.get 'https:///oldpage.html', :follow_redirect => true
使用 :follow_redirect
选项来跟随重定向。
$ ./redirect.rb <!DOCTYPE html> <html> <head> <title>New page</title> </head> <body> <p> This is a new page </p> </body> </html>
这是示例的输出。
$ sudo tail -2 /var/log/nginx/access.log ::1 - - [16/Nov/2020:14:45:28 +0100] "GET /oldpage.html HTTP/1.1" 301 169 "-" "HTTPClient/1.0 (2.8.3, ruby 2.7.2 (2020-10-01))" ::1 - - [16/Nov/2020:14:45:28 +0100] "GET /newpage.html HTTP/1.1" 200 122 "-" "HTTPClient/1.0 (2.8.3, ruby 2.7.2 (2020-10-01))"
从 access.log
文件中可以看到,请求被重定向到了一个新的文件名。通信由两个 GET 消息组成。
Ruby HTTPClient 用户代理
在本节中,我们指定了用户代理的名称。
<?php echo $_SERVER['HTTP_USER_AGENT'];
在 nginx 文档根目录下,我们有这个简单的 PHP 文件。它返回用户代理的名称。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new default_header: {"User-Agent" => "Ruby script"} res = client.get 'https://:8000/user_agent.php' puts res.body
此脚本向 agent.php
脚本创建一个简单的 GET 请求。
client = HTTPClient.new default_header: {"User-Agent" => "Ruby script"}
在 HTTPClient
的构造函数中,我们指定了用户代理。
$ ./agent.rb Ruby script
服务器响应了我们随请求发送的代理名称。
Ruby HTTPClient post 值
post
方法在给定的 URL 上分派一个 POST 请求,为表单填写内容提供键/值对。
<?php echo "Hello " . htmlspecialchars($_POST['name']);
在我们的本地 Web 服务器上,我们有这个 target.php
文件。它只是将发布的 قيمة(posted value)打印回客户端。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new query = {"name" => "Jan"} res = client.post 'https://:8000/target.php', query puts res.body
该脚本发送一个具有 name
键和 Jan
值的请求。POST 请求是通过 post
方法发出的。
$ ./post_value.rb Hello Jan
这是输出。
$ sudo tail -1 /var/log/nginx/access.log ::1 - - [16/Nov/2020:14:45:28 +0100] "GET /newpage.html HTTP/1.1" 200 122 "-" "HTTPClient/1.0 (2.8.3, ruby 2.7.2 (2020-10-01))"
使用 POST 方法时,值不会发送在请求 URL 中。
Ruby HTTPClient Cookie
HTTP Cookie(HTTP cookie)是从网站发送的一小块数据,在用户浏览时存储在用户的 Web 浏览器或程序数据子文件夹中。当用户访问网页时,浏览器/程序会将 Cookie 发回服务器,以通知服务器用户的先前活动。Cookie 有有效期。
在收到 HTTP 请求时,服务器可以在响应中发送一个 Set-Cookie
标头。之后,Cookie 值会以 Cookie HTTP 标头形式与发送给同一服务器的每个请求一起发送。
<?php $theme = $_COOKIE['theme']; if (isset($theme)) { echo "Your theme is $theme"; } else { echo "You are using default theme"; setcookie('theme', 'black-and-white', time() + (86400 * 7)); }
这个 PHP 文件读取一个 Cookie。如果 Cookie 不存在,则会创建它。该 Cookie 存储用户的偏好主题。
#!/usr/bin/ruby require 'httpclient' url = URI.parse "https://:8000/cookies.php" cookie = WebAgent::Cookie.new cookie.name = "theme" cookie.value = "green-and-black" cookie.url = url client = HTTPClient.new client.cookie_manager.add cookie res = client.get url puts res.body
我们创建一个自定义 Cookie 并将其发送到 cookies.php
页面。
cookie = WebAgent::Cookie.new cookie.name = "theme" cookie.value = "green-and-black" cookie.url = url
使用 WebAgent::Cookie
类创建 Cookie。
client = HTTPClient.new client.cookie_manager.add cookie
将 Cookie 添加到 Cookie 管理器。
$ ./send_cookie.rb Your theme is green-and-black
这是示例的输出。
接下来,我们将读取一个 Cookie 并将其本地存储在一个文件中。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'https://:8000/cookies.php' client.set_cookie_store 'cookie.dat' p res.header["Set-Cookie"] client.save_cookie_store
此脚本从 PHP 文件读取一个 Cookie 并将其本地存储在 cookie.dat
文件中。
最后,我们读取存储的 Cookie 并将其发送到同一个 PHP 文件。
#!/usr/bin/ruby require 'httpclient' client = HTTPClient.new cm = HTTPClient::CookieManager.new 'cookie.dat' cm.load_cookies client.cookie_manager = cm res = client.get 'https:///cookies.php' p res.body
使用 HTTPClient::CookieManager
来读取 Cookie。
$ ./send_cookie.rb Unknown key: Max-Age = 604800 "You are using default theme" $ ./read_cookie.rb Unknown key: Max-Age = 604800 ["theme=black-and-white; expires=Sun, 15-May-2016 16:00:08 GMT; Max-Age=604800"] $ ./send_cookie.rb "Your theme is black-and-white"
我们运行脚本。根据作者的说法,警告消息可以忽略。
Ruby HTTPClient 凭证
客户端的 set_auth
方法设置用于区域(realm)的用户名和密码。安全区域(security realm)是一种用于保护 Web 应用程序资源的机制。
$ sudo apt-get install apache2-utils $ sudo htpasswd -c /etc/nginx/.htpasswd user7 New password: Re-type new password: Adding password for user user7
我们使用 htpasswd
工具为基本 HTTP 身份验证创建一个用户名和密码。
location /secure { auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; }
在 nginx 的 /etc/nginx/sites-available/default
配置文件中,我们创建一个受保护的页面。该领域的名称是“Restricted Area”。
<!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html>
在 /var/www/html/secure/
目录中,我们有这个 HTML 文件。
#!/usr/bin/ruby require 'httpclient' user = 'user7' passwd = '7user' client = HTTPClient.new client.set_auth 'https:///secure/', user, passwd cont = client.get_content 'https:///secure/' puts cont
该脚本连接到受保护的网页;它提供访问该页面所需的用户名和密码。
$ ./credentials.rb <!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html>
使用正确的凭证,我们获取了受保护的页面。
在本文中,我们使用了 Ruby HTTPClient 模块。