ruby中argv
代表性状态转移(REST)是基于Web的通信的体系结构样式,它允许客户端以独特的方式与服务器进行通信。 特别是,REST将给定服务器内的资源表示为统一资源标识符(URI),从而简化了超文本传输协议(HTTP)上REST体系结构的实现。 让我们首先介绍REST和HTTP背后的思想。 然后,我们将探索数据表示形式,然后以Ruby语言实现一个简单的REST客户端。
HTTP快速入门
让我们从HTTP的快速介绍开始,因为了解单个REST事务很重要。 尽管HTTP是将Web浏览器连接到服务器的基础通信协议,但是HTTP是用于传输HTML以外的多种类型数据的有用协议。
HTTP是一种请求和响应协议,即客户端发出请求,而服务器通过响应来满足这些请求。 HTTP的实际协议对于人类来说是很容易理解的,并且为了演示HTTP,我使用telnet向Web服务器发出请求。
清单1提供了一个HTTP请求和来自Web服务器的部分响应。 我通过指定Web服务器域名和端口(80是典型的HTTP端口)来使用telnet发起请求。 Telnet首先以域名的域名系统解析响应IP地址,然后指示我已连接到Web服务器。 然后,我指定一个请求行(包含我的HTTP GET
方法,Web服务器上资源的路径以及我使用的协议(在本例中为HTTP版本1.1))。 接下来,我提供了一组请求标头(可能很大,但是由于要输入,所以我只指定了Host
request标头,它指示了我正在发出请求的主机和可选端口)。 我的请求后跟一个空白行,该行告诉Web服务器我的请求已完成。 然后,Web服务器提供一个响应,指示所使用的协议,并提供一个状态码(在这种情况下为200 OK
,指示请求正确)和其他响应头。 然后出现空白行,后跟响应的1944个字符。 这是资源的表示形式,在本例中是HTML文档。
清单1.用telnet执行HTTP事务
$ telnet mtjones.com 80
Trying 198.145.43.103...
Connected to mtjones.com.
Escape character is '^]'.
GET /index.html HTTP/1.1Host: example.org
HTTP/1.1 200 OK
Date: Sun, 25 Mar 2012 05:33:07 GMT
Server: Apache
Last-Modified: Sat, 26 Sep 2009 20:22:36 GMT
ETag: "2c984bf-798-d3451b00"
Accept-Ranges: bytes
Content-Length: 1944
Vary: Accept-Encoding
Content-Type: text/html
<DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" ...
此示例说明了一个简单的事务,但是实际上在HTTP中实现了几种方法。 GET
方法用于从Web服务器检索资源,其中HEAD
仅用于获取有关资源的元信息(而不是实际内容)。 POST
方法用于向Web服务器提供新内容,而PUT
方法用于在Web服务器上放置现有资源的数据。 表1提供了HTTP方法的完整列表。
表1.常见的HTTP 1.1请求方法
方法 | 幂等 | 描述 |
---|---|---|
OPTIONS | 是 | 请求有关通讯选项的信息 |
GET | 是 | 检索URI的表示形式 |
HEAD | 是 | 检索URI的元信息 |
PUT | 是 | 用制图表达创建或替换资源 |
POST | 没有 | 用表示法扩展现有资源 |
DELETE | 是 | 删除URI指定的资源 |
从对HTTP的简短探索中需要注意的重要一点是,它是一种支持对资源进行基本操作的协议。 尽管HTTP现在在服务器和客户端之间通常用于传输Web内容,但它也是用于分布式系统交互和用于允许异构系统进行通信和共享数据的应用程序编程接口(API)开发的协议。
现在,让我们爬上协议栈以探索REST层。
什么是REST?
REST更像是一种建筑风格,而不是特定的设计或实现。 RESTful体系结构由一组简单的约束定义, 如图1所示 。 RESTful体系结构的核心是一组资源。 这些资源由URI(例如统一资源定位符[URL])和内部表示形式(通常是一种自我描述数据的形式,稍后将介绍)来标识。 最后,有一组操作可用来操纵资源。
图1. RESTful架构的高级视图
更具体地说,这些资源可以使用多种类型来表示数据对象(例如JavaScript Object Notation [JSON])。 您可以使用一组标准操作(HTTP GET
, POST
, DELETE
等)通过URL(例如http://www.mtjones.com
)寻址资源。 使用HTTP作为传输方式,极大地简化了RESTful体系结构的开发,因为它们使用了众所周知的稳定基础协议。 HTTP也广泛可用,不需要使用任何新配置,包括网关,代理,安全实施实体和HTTP缓存服务等Internet服务。 为了使REST服务器具有高度可伸缩性,您可以利用其他有用的功能,例如负载平衡。
RESTful架构的特征
尽管RESTful体系结构在实现上有很大的自由度,但是一组特征很重要。
REST定义了客户端-服务器体系结构,其中客户端可以通过服务器导出的表示形式访问服务器资源。 客户端不直接访问资源,而是通过统一的界面表示资源。 与许多客户端-服务器体系结构一样,REST被实现为分层体系结构,从而使其能够利用较低层(HTTP负载平衡等)提供的各种功能。
但是RESTful架构的一个关键方面是它们是无状态的。 服务器无法在事务之间维护任何客户端上下文,并且每个事务必须包含满足特定请求所需的所有信息。 这种特性倾向于使RESTful体系结构更可靠,也有助于扩展其可伸缩性。
样本REST接口
查看一个示例REST实现,以说明RESTful体系结构的一些特征。 回想一下,REST依赖于客户端-服务器交互(请参见图2 )。 客户端应用程序发出的请求将转换为RESTful HTTP请求。 就像从客户端到服务器的任何其他HTTP事务一样,将发起此请求。 服务器处理请求并作出适当响应。
图2. RESTful交互的分层架构
可以用来构建简单客户端的REST API的一个有趣示例是CrunchBase。 CrunchBase是有关技术的公司,人员和投资者的免费数据库。 除了提供传统的Web前端之外,CrunchBase还通过HTTP提供基于REST / JSON的接口。
CrunchBase通过其API实现三个操作:
- 显示(以检索有关特定实体的信息)
- 搜索(以检索与给定搜索条件匹配的实体的列表)
- 列表(检索给定名称空间内的所有实体)
CrunchBase还导出五个用于其数据的名称空间( 见图3)以及用于CrunchBase REST交互的URL形式。 (名称空间是公司,人员,产品,财务组织和服务提供者。)请注意, /v/1
表示API的版本,当前为1。还请注意永久链接字段,该字段表示实体的名称。他们数据库中的唯一名称。
图3. CrunchBase API中的命名空间
如果要获取有关IBM的最新信息,可以使用公司名称空间构造URL(在浏览器中尝试):
http://api.crunchbase.com/v/1/company/ibm.js
您可以在浏览器中键入此URL,浏览器将为您呈现文本(基于JSON)响应(同时使用HTTP标头)。 在探索JSON格式的CrunchBase的数据表示形式时,请更详细地看一下。
自我描述数据简介
异构系统之间的通信引入了一些有趣的问题,其中之一是用于传输的数据序列化。 机器以不同的方式表示数据(从不同的浮点表示形式到标准字节顺序冲突)。 早期的实现包括抽象语法符号(ASN.1)格式和外部数据表示(XDR)协议(在网络文件系统中使用)。 其他方法包括XML,该XML对ASCII格式的文档中的数据进行编码。
在过去的六年中,JSON格式变得越来越流行。 顾名思义,JSON是从JavaScript语言派生的,用于表示自描述数据结构,如关联数组。 尽管有其名称,JSON是一种常见的数据交换格式,并且受多种语言支持。 阅读也很简单。
现在来看一个JSON示例,尤其是一个通过CrunchBase REST接口的示例。 本示例使用交互式Ruby Shell( irb
),它使您可以实时试验Ruby。
如清单2所示,您首先执行交互式Ruby Shell。 您可以通过加载一些模块(尤其是JSON和HTTP组件)来准备环境,并定义URI。 请注意,URI是完整的CrunchBase请求(在公司名称空间中,永久链接为ibm
)。 您可以将其提供给Net::HTTP
的get_response
方法,这是对指定URI(通过URI.parse
方法解析为其各个组件)执行GET
请求的快捷方式。 如果发出resp.body
,则可以看到返回的JSON数据。 这包括一组名称/值对(例如“名称”和“ IBM”)。 您可以使用JSON.parse
方法将响应解析为Ruby对象结构。 最后,通过指定特定名称提取特定值。
清单2.使用Ruby与CrunchBase进行交互
$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'json'
=> true
irb(main):003:0> require 'net/http'
=> true
irb(main):004:0> uri = "http://api.crunchbase.com/v/1/company/ibm.js"
=> "http://api.crunchbase.com/v/1/company/ibm.js"
irb(main):005:0> resp = Net::HTTP.get_response(URI.parse(uri))
=> #<Net::HTTPOK 200 OK readbody=true>
irb(main):006:0> puts resp.body
{"name": "IBM",
"permalink": "ibm",
"crunchbase_url": "http://www.crunchbase.com/company/ibm",
"homepage_url": "http://www.ibm.com",
"blog_url": "",
"blog_feed_url": "",
"twitter_username": "",
"category_code": "software",
"number_of_employees": 388000,
...
=> nil
irb(main):007:0> parsedresp = JSON.parse(resp.body)
=> {"updated_at"=>"Wed Feb 01 03:10:14 UTC 2012", "alias_list"=>nil,
...
irb(main):008:0>
irb(main):009:0* puts parsedresp['founded_year']
1896
=> nil
irb(main):010:0>
从清单2中 ,您可以看到从JSON响应(七行)中快速提取数据的原型是多么容易。 现在,请更进一步,并建立一个简单,可重用的API与CrunchBase进行交互。
构建一个简单的REST客户端
在构建REST客户端之前,您必须安装一些东西。 如果您没有安装Ruby,请安装它。 因为我使用Ubuntu,所以我将使用Advanced Packaging Tool来满足大多数这些安装要求(以及其他的Ruby gem程序包管理器)。
使用以下方法获取Ruby包:
$ sudo apt-get install ruby
(可选)获取Interactive Ruby Shell( irb
),这是尝试Ruby语言的有用方法:
$ sudo apt-get install irb
最后,您需要Ruby的JSON gem。 以下代码显示了如何同时获取gem前端和JSON gem。
$ sudo apt-get install rubygems1.8
$ sudo apt-get install ruby-dev
$ sudo gem install json
准备好环境后,开始使用Ruby构建简单的REST客户端API。 在清单1中,您看到了如何在Ruby中与HTTP服务器通信以及如何从JSON对象解析简单名称。 利用一组实现简单API的Ruby类,以此知识为基础。
首先,查看与CrunchBase REST服务器交互的两个示例类。 首先关注公司名称空间; 第二个重点是人员名称空间。 请注意,两者都扩展了最小限度的方法集,但很容易扩展为其他数据元素。
清单3提供了与公司名称空间进行交互的API。 此类扩展了构造函数方法( initialize
)和四个方法,这些方法用于从基于JSON的公司记录中提取数据。 该类的操作理论是用户创建对象的实例,并提供公司(永久链接)名称。 作为构造函数的一部分,CrunchBase被征询用于公司记录。 您可以动态构造URL,并添加作为new
方法的一部分传递的公司名称。 使用get_response
方法检索响应,并将解析的结果(哈希对象)加载到实例变量( @record
)中。
有了可用的已解析记录,每种方法在被调用时都将简单地提取所需的数据并将其返回给用户。 鉴于清单1中的讨论, founded_year
, num_employees
和company_type
很简单。 people
方法需要更多的解释。
来自CrunchBase的JSON响应由包含一定数量键的哈希表示。 请注意,在前三种方法中,您指定了返回值的键。 people
方法遍历由键relationships
标识的哈希值。 每个记录包含一个is_past
键(用于标识此人是否不再在特定公司中), title
键和一个人键,其中包含first_name
, last_name
和permalink
。 迭代器只是简单地遍历每个迭代器,并且当键is_past
为false时,提取人员和标题并从该信息中创建新的哈希。 如果找不到其他密钥,则返回此哈希。 请注意,您可以通过简单地发出JSON.parse
-ed响应来查看IRB中的整个哈希。
清单3.用于公司名称空间(company.rb)的Ruby CrunchBase API
require 'rubygems'
require 'json'
require 'net/http'
class Crunchbase_Company
@record = nil
def initialize( company )
base_url = "http://api.crunchbase.com"
url = "#{base_url}/v/1/company/#{company}.js"
resp = Net::HTTP.get_response(URI.parse(url))
@record = JSON.parse(resp.body)
end
def founded_year
return @record['founded_year']
end
def num_employees
return @record['number_of_employees']
end
def company_type
return @record['category_code']
end
def people
employees = Hash.new
relationships = @record['relationships']
if !relationships.nil?
relationships.each do | person |
if person['is_past'] == false then
permalink = person['person']['permalink']
title = person['title']
employees[permalink] = title
end
end
end
return employees
end
end
清单4提供了与清单3中讨论的Company
类类似的功能。 initialize
构造函数的操作方式相同,并且您有两种简单的方法(从其永久链接中)提取给定人员的姓名。 companies
方法迭代relationships
键的哈希值,并返回该特定人员过去与之关联的公司(公司)。 在这种情况下,关联的公司以简单的Ruby数组(固定链接)返回。
清单4.用于人员名称空间的Ruby CrunchBase API(person.rb)
require 'rubygems'
require 'json'
require 'net/http'
class Crunchbase_Person
@record = nil
def initialize( person )
base_url = "http://api.crunchbase.com"
url = "#{base_url}/v/1/person/#{person}.js"
resp = Net::HTTP.get_response(URI.parse(url))
@record = JSON.parse(resp.body)
end
def fname
return @record['first_name']
end
def lname
return @record['last_name']
end
def companies
firms = Array.new
@record['relationships'].each do | firm |
firms << firm['firm']['permalink']
end
return firms
end
end
请注意,在这两个简单的类中,Ruby在Net::HTTP
类中隐藏了处理HTTP服务器的复杂性。 通过JSON gem完全简化了解析JSON响应的复杂性。 现在,让我们看一下这些API的几个应用程序,以说明它们的用法。
构建一些简单的应用程序
从类的演示开始。 在第一个示例(请参见清单5 )中,您想要标识与给定公司关联的人员(基于公司的永久链接)。 从公司名称空间检索的记录包含与公司关联的人的永久链接列表。 您迭代人员哈希并根据该永久链接检索个人的记录。 该记录为您提供了个人的名字和姓氏,并且他或她的头衔是公司记录的一部分(作为名称-标题哈希的一部分返回)。
清单5.识别与公司关联的人(people.rb)
#!/usr/bin/ruby
load "company.rb"
load "person.rb"
# Get argument (company permalink)
input = ARGV[0]
company = Crunchbase_Company.new(input)
people = company.people
# Iterate the people hash
people.each do |name, title|
# Get the person record
person = Crunchbase_Person.new( name )
# Emit the name and title
print "#{person.fname} #{person.lname} | #{title}\n"
end
people = nil
company = nil
您如清单6所示执行清单5中的脚本。 使用脚本,您可以提供公司的永久链接,结果是个人的名字和姓氏和头衔。
清单6.测试people.rb脚本
$ ./people.rb emulex
Jim McCluney | President and CEO
Michael J. Rockenbach | Executive Vice President and CFO
Jeff Benck | Executive Vice President & COO
$
现在,看一个更复杂的例子。 本示例使用给定的公司,然后确定执行人员。 然后,确定那些高管过去曾工作过的公司。 清单7提供了名为influence.rb的脚本。 如图所示,您接受公司名称作为参数,检索公司记录,然后检索该公司当前人员的哈希(通过people方法)。 然后,您遍历这些人,并通过他们的头衔来确定首领(鉴于CrunchBase中头衔的可变性,因此并不完全准确)。 对于任何确定的负责人,您将散发出那些人曾工作过的公司(通过从人事记录中检索一系列公司)。
清单7.行政关系和影响力(influence.rb)
#!/usr/bin/ruby
load "crunchbase.rb"
input = ARGV[0]
puts "Executive Relationships to " + input
company = Crunchbase_Company.new(input)
people = company.people
# Iterate through everyone associated with this company
people.each do |name, title|
# Search for only certain titles
if title.upcase.include?("CEO") or
title.upcase.include?("COO") or
title.upcase.include?("CFO") or
title.upcase.include?("CHIEF") or
title.upcase.include?("CTO") then
person = Crunchbase_Person.new( name )
companies = person.companies
companies.each do | firm |
if input != firm
puts " " + firm
end
end
end
end
清单8为大数据公司Cloudera演示了此脚本。 从清单7可以看到,Ruby及其宝石隐藏了许多细节,使您可以专注于手头的任务。
清单8.测试影响力的Ruby脚本
$ ./influence.rb cloudera
Executive Relationships to cloudera
accel-partners
bittorrent
mochimedia
yume
lookout
scalextreme
vivasmart
yahoo
facebook
rock-health
$
使用其他REST HTTP方法
在此处显示的简单示例中,您仅使用GET
方法从CrunchBase数据库提取数据。 其他站点可能会扩展接口以检索数据并将数据发送到其特定的REST服务器。 清单9提供了其他Net::HTTP
方法的介绍。
清单9.用于其他RESTful交互的HTTP方法
http = Net::HTTP.new("site url")
# Delete a resource
transaction = Net::HTTP::Delete.new("resource")
response = http.request(transaction)
# Post a resource
resp, data = Net::HTTP.post_form( url, post_arguments )
# Put a resource
transaction = Net::HTTP::Put.new("resource")
transaction.set_form_data( "form data..." )
response = http.request(transaction)
为了进一步简化REST客户端的开发,可以使用其他Ruby gem,例如rest-client
(请参阅参考资料 )。 这个gem在HTTP上提供了一个REST层,提供了诸如get
, post
和delete
。
向前走
我希望这个关于Ruby的REST原理的快速介绍可以说明基于Web的体系结构的强大功能,以及为什么Ruby是我最喜欢的语言之一。 REST是用于计算和存储云的最受欢迎的API架构之一,因此值得花时间来理解和探索。 在参考资料中 ,您可以找到有关本文以及developerWorks其他REST文章中使用的技术的其他信息的链接。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-understand-rest-ruby/index.html
ruby中argv