ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
# Ruby `HTTPClient`教程 > 原文: [https://zetcode.com/web/rubyhttpclient/](https://zetcode.com/web/rubyhttpclient/) 在本教程中,我们展示了如何使用 Ruby `HTTPClient`模块。 我们获取数据,发布数据,使用 cookie 并连接到安全的网页。 ZetCode 也有一个简洁的 [Ruby 教程](/lang/rubytutorial/)。 超文本传输​​协议(HTTP)是用于分布式协作超媒体信息系统的应用协议。 HTTP 是万维网数据通信的基础。 Ruby `HTTPClient`提供了用于通过 HTTP 访问 Web 资源的方法。 它提供了 Ruby 中的`libwww-perl`(LWP)的功能。 (有关 Perl LWP 的信息,请参见 ZetCode 的[文章](/articles/perllwp/)。)该宝石是由中村博史创建的。 ```ruby $ sudo gem install httpclient ``` 该模块通过`sudo gem install httpclient`命令安装。 ```ruby $ service nginx status * nginx is running ``` 我们在本地主机上运行 nginx Web 服务器。 我们的一些示例将连接到本地运行的 nginx 服务器上的 PHP 脚本。 ## 版本 第一个程序输出库和 Ruby 语言的版本。 `version.rb` ```ruby #!/usr/bin/ruby require 'httpclient' puts HTTPClient::LIB_NAME puts HTTPClient::RUBY_VERSION_STRING puts HTTPClient::VERSION ``` 这三个常数提供了库和 Ruby 版本号。 ```ruby $ ./version.rb (2.8.0, ruby 1.9.3 (2013-11-22)) ruby 1.9.3 (2013-11-22) 2.8.0 ``` 这是示例的示例输出。 ## ·get_content·函数 `get_content`是一种用于获取由给定 URL 标识的文档的高级方法。 `get_content.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new cont = client.get_content 'http://www.something.com' puts cont ``` 该脚本获取`www.something.com`网页的内容。 ```ruby cont = client.get_content 'http://www.something.com' ``` `get_content`方法将结果作为一个字符串返回。 ```ruby $ ./get_content.rb <html><head><title>Something.</title></head> <body>Something.</body> </html> ``` 这是`get_content.rb`脚本的输出。 以下程序获取一个小型网页,并剥离其 HTML 标签。 `strip_tags.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new client.get_content('http://www.something.com') do |chunk| puts chunk.gsub(%r{</?[^>]+?>}, '') end ``` 该脚本会剥离`www.something.com`网页的 HTML 标签。 ```ruby client.get_content('http://www.something.com') do |chunk| puts chunk.gsub(%r{</?[^>]+?>}, '') end ``` 一个简单的正则表达式用于剥离 HTML 标记。 在这种情况下,`get_content`方法以字符串块的形式返回内容。 ```ruby $ ./strip_tags.rb Something. Something. ``` 该脚本将打印网页的标题和内容。 ## 请求 HTTP 请求是从客户端发送到浏览器的消息,以检索某些信息或采取某些措施。 `HTTPClient`的`request`方法创建一个新请求。 请注意,`HTTPClient`类具有诸如`get`,`post`或`put`之类的方法,这些方法为我们节省了一些输入。 `create_request.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new method = 'GET' url = URI.parse 'http://www.something.com' res = client.request method, url puts res.body ``` 该示例创建一个 GET 请求并将其发送到`http://www.something.com`。 ```ruby method = 'GET' url = URI.parse 'http://www.something.com' ``` 我们创建一个请求方法和 URL。 ```ruby res = client.request method, url ``` 使用`request`方法发出请求。 ```ruby puts res.body ``` 消息响应的`body`属性包含消息的正文。 ```ruby $ ./create_request.rb <html><head><title>Something.</title></head> <body>Something.</body> </html> ``` 这是示例的输出。 ## 状态 `HTTP::Message`表示 HTTP 请求或响应。 其`status`方法返回响应的 HTTP 状态代码。 `status.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'http://www.something.com' puts res.status puts HTTP::Status::successful? res.status res = client.get 'http://www.something.com/news/' puts res.status puts HTTP::Status::successful? res.status res = client.get 'http://www.urbandicionary.com/define.php?term=Dog' puts res.status puts HTTP::Status::successful? res.status ``` 我们使用`get`方法执行三个 HTTP 请求,并检查返回的状态。 ```ruby puts HTTP::Status::successful? res.status ``` `HTTP::Status::successful?`方法指示状态代码是否成功。 ```ruby $ ./status.rb 200 true 404 false 302 false ``` 200 是对成功的 HTTP 请求的标准响应,404 指示找不到请求的资源,302 指示该资源已临时重定向。 ## `head`方法 `head`方法检索文档标题。 标头由字段组成,包括日期,服务器,内容类型或上次修改时间。 `head.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.head 'http://www.something.com' 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] ``` 该示例打印服务器,`www.something.com`网页的上次修改时间,内容类型和内容长度。 ```ruby $ ./head.rb Server: Apache/2.4.12 (FreeBSD) OpenSSL/1.0.1l-freebsd mod_fastcgi/mod_fastcgi-SNAP-0910052141 Last modified: Mon, 25 Oct 1999 15:36:02 GMT Content type: text/html Content length: 77 ``` 这是`head.rb`程序的输出。 ## `get`方法 `get`方法向服务器发出 GET 请求。 GET 方法请求指定资源的表示形式。 `greet.php` ```ruby <?php echo "Hello " . htmlspecialchars($_GET['name']); ?> ``` 在`/usr/share/nginx/html/`目录中,有此`greet.php`文件。 该脚本返回`name`变量的值,该值是从客户端检索到的。 `htmlspecialchars()`函数将特殊字符转换为 HTML 实体; 例如`&amp;`。 `mget.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'http://localhost/greet.php?name=Jan' puts res.body ``` 该脚本将带有值的变量发送到服务器上的 PHP 脚本。 该变量直接在 URL 中指定。 ```ruby $ ./mget.rb Hello Jan ``` This is the output of the example. ```ruby $ tail -1 /var/log/nginx/access.log 127.0.0.1 - - [08/May/2016:13:15:31 +0200] "GET /greet.php?name=Jan HTTP/1.1" 200 19 "-" "HTTPClient/1.0 (2.8.0, ruby 1.9.3 (2013-11-22))" ``` 我们检查了 nginx 访问日志。 `get`方法采用第二个参数,我们可以在其中指定查询参数。 `mget2.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new query = {'name' => 'Jan'} res = client.get 'http://localhost/greet.php', query puts res.body ``` 该示例与上一个示例基本相同。 ```ruby $ ./mget2.rb Hello Jan ``` This is the output of the example. ## 重定向 重定向是将一个 URL 转发到另一个 URL 的过程。 HTTP 响应状态代码 301“永久移动”用于永久 URL 重定向。 ```ruby location = /oldpage.html { return 301 /files/newpage.html; } ``` 将这些行添加到位于 Debian 上`/etc/nginx/sites-available/default`的 Nginx 配置文件中。 ```ruby $ sudo service nginx restart ``` 编辑完文件后,我们必须重新启动 nginx 才能应用更改。 `newpage.html` ```ruby <!DOCTYPE html> <html> <head> <title>New page</title> </head> <body> <p> This is a new page </p> </body> </html> ``` 这是位于 nginx 文档根目录中的`newpage.html`文件。 `redirect.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'http://localhost/oldpage.html', :follow_redirect => true puts res.body ``` 该脚本访问旧页面并遵循重定向。 ```ruby res = client.get 'http://localhost/oldpage.html', :follow_redirect => true ``` `:follow_redirect`选项用于遵循重定向。 ```ruby $ ./redirect.rb <!DOCTYPE html> <html> <head> <title>New page</title> </head> <body> <p> This is a new page </p> </body> </html> ``` This is the output of the example. ```ruby $ tail -2 /var/log/nginx/access.log 127.0.0.1 - - [09/May/2016:14:08:50 +0200] "GET /oldpage.html HTTP/1.1" 301 193 "-" "HTTPClient/1.0 (2.8.0, ruby 1.9.3 (2013-11-22))" 127.0.0.1 - - [09/May/2016:14:08:50 +0200] "GET /files/newpage.html HTTP/1.1" 200 113 "-" "HTTPClient/1.0 (2.8.0, ruby 1.9.3 (2013-11-22))" ``` 从`access.log`文件中可以看到,该请求已重定向到新的文件名。 通信包含两个 GET 消息。 ## 用户代理 在本节中,我们指定用户代理的名称。 `agent.php` ```ruby <?php echo $_SERVER['HTTP_USER_AGENT']; ?> ``` 在 nginx 文档根目录中,我们有这个简单的 PHP 文件。 它返回用户代理的名称。 `agent.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new default_header: {"User-Agent" => "Ruby script"} res = client.get 'http://localhost/agent.php' puts res.body ``` 该脚本为`agent.php`脚本创建一个简单的 GET 请求。 ```ruby client = HTTPClient.new default_header: {"User-Agent" => "Ruby script"} ``` 在`HTTPClient`的构造器中,我们指定用户代理。 ```ruby $ ./agent.rb Ruby script ``` 服务器使用我们随请求发送的代理名称进行了响应。 ## `post`方法 `post`方法在给定的 URL 上调度 POST 请求,为填写的表单内容提供键/值对。 `target.php` ```ruby <?php echo "Hello " . htmlspecialchars($_POST['name']); ?> ``` 在本地 Web 服务器上,我们有此`target.php`文件。 它只是将过帐的值打印回客户。 `post_value.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new query = {"name" => "Jan"} res = client.post 'http://localhost/target.php', query puts res.body ``` 脚本使用具有`Jan`值的`name`键发送请求。 POST 请求通过`post`方法发出。 ```ruby $ ./mpost.rb Hello Jan ``` 这是`mpost.rb`脚本的输出。 ```ruby $ tail -1 /var/log/nginx/access.log 127.0.0.1 - - [08/May/2016:13:38:57 +0200] "POST /target.php HTTP/1.1" 200 19 "-" "HTTPClient/1.0 (2.8.0, ruby 1.9.3 (2013-11-22))" ``` 使用 POST 方法时,不会在请求 URL 中发送该值。 ## 从字典中检索定义 在以下示例中,我们在 [www.dictionary.com](http://www.dictionary.com) 上找到术语的定义。 要解析 HTML,我们使用`nokogiri`。 可以使用`sudo gem install nokogiri`命令安装。 `get_term.rb` ```ruby #!/usr/bin/ruby require 'httpclient' require 'nokogiri' client = HTTPClient.new term = 'dog' res = client.get 'http://www.dictionary.com/browse/'+term doc = Nokogiri::HTML res.body doc.css("div.def-content").map do |node| puts node.text.strip!.gsub(/\s{3,}/, " ") end ``` 在此脚本中,我们在`www.dictionary.com`上找到了术语狗的定义。 `Nokogiri::HTML`用于解析 HTML 代码。 ```ruby res = client.get 'http://www.dictionary.com/browse/'+term ``` 为了执行搜索,我们在 URL 的末尾附加了该词。 ```ruby doc = Nokogiri::HTML res.body doc.css("div.def-content").map do |node| puts node.text.strip!.gsub(/\s{3,}/, " ") end ``` 我们使用`Nokogiri::HTML`类解析内容。 定义位于`<div class="def-content">`标签内。 我们通过删除过多的空白来改善格式。 ## cookie HTTP cookie 是从网站发送并在用户浏览时存储在用户的 Web 浏览器或程序数据子文件夹中的一小段数据。 当用户访问网页时,浏览器/程序会将 cookie 发送回服务器,以通知用户先前的活动。 Cookies 的有效期限为有效期。 接收到 HTTP 请求时,服务器可以发送带有响应的`Set-Cookie`标头。 之后,cookie 值将以 Cookie HTTP 标头的形式与对同一服务器的所有请求一起发送。 `cookies.php` ```ruby <?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 存储用户的主题。 `send_cookie.rb` ```ruby #!/usr/bin/ruby require 'httpclient' url = URI.parse "http://localhost/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`页面。 ```ruby cookie = WebAgent::Cookie.new cookie.name = "theme" cookie.value = "green-and-black" cookie.url = url ``` 使用`WebAgent::Cookie`类创建一个 cookie。 ```ruby client = HTTPClient.new client.cookie_manager.add cookie ``` cookie 被添加到 cookie 管理器中。 ```ruby $ ./send_cookie.rb Your theme is green-and-black ``` This is the output of the example. 接下来,我们将读取 cookie 并将其本地存储在文件中。 `read_cookie.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new res = client.get 'http://localhost/cookies.php' client.set_cookie_store 'cookie.dat' p res.header["Set-Cookie"] client.save_cookie_store ``` 该脚本从 PHP 文件读取 cookie,并将其本地存储在`cookie.dat`文件中。 最后,我们读取存储的 cookie,并将其发送到同一 PHP 文件。 `send_cookie2.rb` ```ruby #!/usr/bin/ruby require 'httpclient' client = HTTPClient.new cm = HTTPClient::CookieManager.new 'cookie.dat' cm.load_cookies client.cookie_manager = cm res = client.get 'http://localhost/cookies.php' p res.body ``` `HTTPClient::CookieManager`用于读取 cookie。 ```ruby $ ./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" ``` 我们运行脚本。 作者认为,警告消息[应忽略](https://github.com/nahi/httpclient/issues/242)。 ## 证书 客户端的`set_auth`方法设置用于领域的名称和密码。 安全领域是一种用于保护 Web 应用资源的机制。 ```ruby $ 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 认证的用户名和密码。 ```ruby location /secure { auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; } ``` 在 nginx `/etc/nginx/sites-available/default`配置文件中,我们创建一个安全页面。 领域的名称是`"Restricted Area"`。 `index.html` ```ruby <!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html> ``` 在`/usr/share/nginx/html/secure`目录中,我们有这个 HTML 文件。 `credentials.rb` ```ruby #!/usr/bin/ruby require 'httpclient' user = 'user7' passwd = '7user' client = HTTPClient.new client.set_auth 'http://localhost/secure/', user, passwd cont = client.get_content 'http://localhost/secure/' puts cont ``` 该脚本连接到安全网页; 它提供访问该页面所需的用户名和密码。 ```ruby $ ./credentials.rb <!DOCTYPE html> <html lang="en"> <head> <title>Secure page</title> </head> <body> <p> This is a secure page. </p> </body> </html> ``` 使用正确的凭据,`credentials.rb`脚本返回受保护的页面。 在本教程中,我们使用了 Ruby `HTTPClient`模块。 在 ZetCode 上有类似的 [Ruby Faraday 教程](/web/rubyfaraday/)和 [Ruby `Net::HTTP`教程](/web/rubynethttp/)。