ur 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +2 -2
- data/lib/ur/content_type.rb +65 -41
- data/lib/ur/middleware.rb +2 -2
- data/lib/ur/request_and_response.rb +8 -4
- data/lib/ur/sub_ur.rb +1 -1
- data/lib/ur/version.rb +1 -1
- data/lib/ur/weblink.rb +125 -0
- data/lib/ur.rb +10 -9
- data/resources/ur.schema.yml +1 -0
- data/ur.gemspec +12 -15
- metadata +11 -152
- data/.simplecov +0 -1
- data/Rakefile.rb +0 -9
- data/resources/icons/LGPL-3.0.png +0 -0
- data/test/content_type_test.rb +0 -342
- data/test/test_helper.rb +0 -33
- data/test/ur_faraday_test.rb +0 -79
- data/test/ur_metadata_test.rb +0 -11
- data/test/ur_rack_test.rb +0 -25
- data/test/ur_test.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a39ab1a17905dc8a0fb40eb22896580951abec8cfe78a11c4a1fd558ca6c6917
|
4
|
+
data.tar.gz: 5915b4da516b30c6ee291eb7f5a5bb5a8f974d30da327d5660a9b1a0549068a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e59ca34e85e21e8c659a10e57cffad39d3fa718389bed6ccb6e4327cb33b237569517bb8d5c2eb93272a0c20634966697823a7142f1d861ba58c933dad5342c6
|
7
|
+
data.tar.gz: 3ab8ad92c6e70fc3dd87928a200a500e8bd5d27440fd9c2b3e35d46d3778aed80122cefda50875cb0bb6f84dcba75fbc24bdc194d88d4f345439b97f98f7b9b6
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -61,6 +61,6 @@ end
|
|
61
61
|
|
62
62
|
## License
|
63
63
|
|
64
|
-
[<img align="right" src="https://
|
64
|
+
[<img align="right" src="https://www.gnu.org/graphics/lgplv3-147x51.png">](https://www.gnu.org/licenses/lgpl-3.0.html)
|
65
65
|
|
66
|
-
Ur is
|
66
|
+
Ur is licensed under the terms of the [GNU Lesser General Public License version 3](https://www.gnu.org/licenses/lgpl-3.0.html).
|
data/lib/ur/content_type.rb
CHANGED
@@ -21,12 +21,15 @@ module Ur
|
|
21
21
|
# https://tools.ietf.org/html/rfc2045#section-5.1
|
22
22
|
# - Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types
|
23
23
|
# https://tools.ietf.org/html/rfc2046
|
24
|
+
# - Additional Media Type Structured Syntax Suffixes
|
25
|
+
# https://tools.ietf.org/html/rfc6839
|
24
26
|
class ContentType < String
|
25
27
|
# the character ranges in this SHOULD be significantly more restrictive,
|
26
|
-
# and the
|
28
|
+
# and the `/<subtype>` construct should not be optional. however, we'll aim
|
27
29
|
# to match whatever media type we are given.
|
28
30
|
#
|
29
31
|
# example:
|
32
|
+
#
|
30
33
|
# MEDIA_TYPE_REGEXP.match('application/vnd.github+json').named_captures
|
31
34
|
# =>
|
32
35
|
# {
|
@@ -38,6 +41,7 @@ module Ur
|
|
38
41
|
# }
|
39
42
|
#
|
40
43
|
# example of being more permissive than the spec allows:
|
44
|
+
#
|
41
45
|
# MEDIA_TYPE_REGEXP.match('where the %$*! am I').named_captures
|
42
46
|
# =>
|
43
47
|
# {
|
@@ -116,46 +120,55 @@ module Ur
|
|
116
120
|
freeze
|
117
121
|
end
|
118
122
|
|
119
|
-
#
|
120
|
-
#
|
123
|
+
# the media type of this content type.
|
124
|
+
# e.g. `"application/vnd.github+json"` in `content-type: application/vnd.github+json; charset="utf-8"`
|
125
|
+
# @return [String, nil]
|
121
126
|
attr_reader :media_type
|
122
127
|
|
123
|
-
#
|
124
|
-
#
|
128
|
+
# the 'type' portion of our media type.
|
129
|
+
# e.g. `"application"` in `content-type: application/vnd.github+json; charset="utf-8"`
|
130
|
+
# @return [String, nil]
|
125
131
|
attr_reader :type
|
126
132
|
|
127
|
-
#
|
128
|
-
#
|
133
|
+
# the 'subtype' portion of our media type.
|
134
|
+
# e.g. `"vnd.github+json"` in `content-type: application/vnd.github+json; charset="utf-8"`
|
135
|
+
# @return [String, nil]
|
129
136
|
attr_reader :subtype
|
130
137
|
|
131
|
-
#
|
132
|
-
#
|
138
|
+
# the 'facet' portion of our media type.
|
139
|
+
# e.g. `"vnd"` in `content-type: application/vnd.github+json; charset="utf-8"`
|
140
|
+
# @return [String, nil]
|
133
141
|
attr_reader :facet
|
134
142
|
|
135
|
-
#
|
136
|
-
#
|
143
|
+
# the 'suffix' portion of our media type.
|
144
|
+
# e.g. `"json"` in `content-type: application/vnd.github+json; charset="utf-8"`
|
145
|
+
# @return [String, nil]
|
137
146
|
attr_reader :suffix
|
138
147
|
|
139
|
-
#
|
140
|
-
#
|
148
|
+
# parameters of this content type.
|
149
|
+
# e.g. `{"charset" => "utf-8"}` in `content-type: application/vnd.github+json; charset="utf-8"`
|
150
|
+
# @return [Hash<String, String>]
|
141
151
|
attr_reader :parameters
|
142
152
|
|
153
|
+
# is the 'type' portion of our media type equal (case-insensitive) to the given other_type
|
143
154
|
# @param other_type
|
144
|
-
# @return [Boolean]
|
155
|
+
# @return [Boolean]
|
145
156
|
def type?(other_type)
|
146
|
-
type
|
157
|
+
type ? type.casecmp?(other_type) : false
|
147
158
|
end
|
148
159
|
|
160
|
+
# is the 'subtype' portion of our media type equal (case-insensitive) to the given other_subtype
|
149
161
|
# @param other_subtype
|
150
|
-
# @return [Boolean]
|
162
|
+
# @return [Boolean]
|
151
163
|
def subtype?(other_subtype)
|
152
|
-
subtype
|
164
|
+
subtype ? subtype.casecmp?(other_subtype) : false
|
153
165
|
end
|
154
166
|
|
167
|
+
# is the 'suffix' portion of our media type equal (case-insensitive) to the given other_suffix
|
155
168
|
# @param other_suffix
|
156
|
-
# @return [Boolean]
|
169
|
+
# @return [Boolean]
|
157
170
|
def suffix?(other_suffix)
|
158
|
-
suffix
|
171
|
+
suffix ? suffix.casecmp?(other_suffix) : false
|
159
172
|
end
|
160
173
|
|
161
174
|
SOME_TEXT_SUBTYPES = %w(
|
@@ -173,11 +186,12 @@ module Ur
|
|
173
186
|
ecmascript
|
174
187
|
).map(&:freeze).freeze
|
175
188
|
|
189
|
+
# does this content type appear to be binary?
|
190
|
+
# this library makes its best guess based on a very incomplete knowledge
|
191
|
+
# of which media types indicate binary or text.
|
176
192
|
# @param unknown [Boolean] return this value when we have no idea whether
|
177
193
|
# our media type is binary or text.
|
178
|
-
# @return [Boolean]
|
179
|
-
# this library makes its best guess based on a very incomplete knowledge
|
180
|
-
# of which media types indicate binary or text.
|
194
|
+
# @return [Boolean]
|
181
195
|
def binary?(unknown: true)
|
182
196
|
return false if type_text?
|
183
197
|
|
@@ -192,54 +206,64 @@ module Ur
|
|
192
206
|
return unknown
|
193
207
|
end
|
194
208
|
|
195
|
-
#
|
209
|
+
# is this a JSON content type?
|
210
|
+
# @return [Boolean]
|
196
211
|
def json?
|
197
212
|
suffix ? suffix.casecmp?('json') : subtype ? subtype.casecmp?('json') : false
|
198
213
|
end
|
199
214
|
|
200
|
-
#
|
215
|
+
# is this an XML content type?
|
216
|
+
# @return [Boolean]
|
201
217
|
def xml?
|
202
|
-
suffix ? suffix.casecmp?('xml'): subtype ? subtype.casecmp?('xml') : false
|
218
|
+
suffix ? suffix.casecmp?('xml') : subtype ? subtype.casecmp?('xml') : false
|
203
219
|
end
|
204
220
|
|
205
|
-
#
|
221
|
+
# is this a `x-www-form-urlencoded` content type?
|
222
|
+
# @return [Boolean]
|
206
223
|
def form_urlencoded?
|
207
|
-
suffix ? suffix.casecmp?('x-www-form-urlencoded'): subtype ? subtype.casecmp?('x-www-form-urlencoded') : false
|
224
|
+
suffix ? suffix.casecmp?('x-www-form-urlencoded') : subtype ? subtype.casecmp?('x-www-form-urlencoded') : false
|
208
225
|
end
|
209
226
|
|
210
|
-
#
|
227
|
+
# is the 'type' portion of our media type 'text'
|
228
|
+
# @return [Boolean]
|
211
229
|
def type_text?
|
212
|
-
type
|
230
|
+
type ? type.casecmp?('text') : false
|
213
231
|
end
|
214
232
|
|
215
|
-
#
|
233
|
+
# is the 'type' portion of our media type 'image'
|
234
|
+
# @return [Boolean]
|
216
235
|
def type_image?
|
217
|
-
type
|
236
|
+
type ? type.casecmp?('image') : false
|
218
237
|
end
|
219
238
|
|
220
|
-
#
|
239
|
+
# is the 'type' portion of our media type 'audio'
|
240
|
+
# @return [Boolean]
|
221
241
|
def type_audio?
|
222
|
-
type
|
242
|
+
type ? type.casecmp?('audio') : false
|
223
243
|
end
|
224
244
|
|
225
|
-
#
|
245
|
+
# is the 'type' portion of our media type 'video'
|
246
|
+
# @return [Boolean]
|
226
247
|
def type_video?
|
227
|
-
type
|
248
|
+
type ? type.casecmp?('video') : false
|
228
249
|
end
|
229
250
|
|
230
|
-
#
|
251
|
+
# is the 'type' portion of our media type 'application'
|
252
|
+
# @return [Boolean]
|
231
253
|
def type_application?
|
232
|
-
type
|
254
|
+
type ? type.casecmp?('application') : false
|
233
255
|
end
|
234
256
|
|
235
|
-
#
|
257
|
+
# is the 'type' portion of our media type 'message'
|
258
|
+
# @return [Boolean]
|
236
259
|
def type_message?
|
237
|
-
type
|
260
|
+
type ? type.casecmp?('message') : false
|
238
261
|
end
|
239
262
|
|
240
|
-
#
|
263
|
+
# is the 'type' portion of our media type 'multipart'
|
264
|
+
# @return [Boolean]
|
241
265
|
def type_multipart?
|
242
|
-
type
|
266
|
+
type ? type.casecmp?('multipart') : false
|
243
267
|
end
|
244
268
|
end
|
245
269
|
end
|
data/lib/ur/middleware.rb
CHANGED
@@ -30,7 +30,7 @@ module Ur
|
|
30
30
|
class FaradayMiddleware < ::Faraday::Middleware
|
31
31
|
include Ur::Middleware
|
32
32
|
def call(request_env)
|
33
|
-
ur = Ur.from_faraday_request(request_env,
|
33
|
+
ur = Ur.from_faraday_request(request_env, **@options.select { |k, _| [:schemas].include?(k) })
|
34
34
|
invoke_callback(:before_request, ur)
|
35
35
|
begin_request(ur)
|
36
36
|
ur.faraday_on_complete(@app, request_env) do |response_env|
|
@@ -43,7 +43,7 @@ module Ur
|
|
43
43
|
class RackMiddleware
|
44
44
|
include Ur::Middleware
|
45
45
|
def call(env)
|
46
|
-
ur = Ur.from_rack_request(env,
|
46
|
+
ur = Ur.from_rack_request(env, **@options.select { |k, _| [:schemas].include?(k) })
|
47
47
|
invoke_callback(:before_request, ur)
|
48
48
|
begin_request(ur)
|
49
49
|
ur.with_rack_response(@app, env) do
|
@@ -25,9 +25,10 @@ module Ur
|
|
25
25
|
end
|
26
26
|
include FaradayEntity
|
27
27
|
|
28
|
-
#
|
28
|
+
# the string value of the content type header. returns an
|
29
29
|
# {Ur::ContentType}, a subclass of String which additionally parses the Content-Type
|
30
30
|
# according to relevant RFCs.
|
31
|
+
# @return [Ur::ContentType]
|
31
32
|
def content_type
|
32
33
|
headers.each do |k, v|
|
33
34
|
return ContentType.new(v) if k =~ /\Acontent[-_]type\z/i
|
@@ -40,17 +41,20 @@ module Ur
|
|
40
41
|
content_type ? content_type.media_type : nil
|
41
42
|
end
|
42
43
|
|
43
|
-
#
|
44
|
+
# is our content type JSON?
|
45
|
+
# @return [Boolean]
|
44
46
|
def json?
|
45
47
|
content_type && content_type.json?
|
46
48
|
end
|
47
49
|
|
48
|
-
#
|
50
|
+
# is our content type XML?
|
51
|
+
# @return [Boolean]
|
49
52
|
def xml?
|
50
53
|
content_type && content_type.xml?
|
51
54
|
end
|
52
55
|
|
53
|
-
#
|
56
|
+
# is our content type `x-www-form-urlencoded`?
|
57
|
+
# @return [Boolean]
|
54
58
|
def form_urlencoded?
|
55
59
|
content_type && content_type.form_urlencoded?
|
56
60
|
end
|
data/lib/ur/sub_ur.rb
CHANGED
data/lib/ur/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
UR_VERSION = "0.2.
|
1
|
+
UR_VERSION = "0.2.2".freeze
|
data/lib/ur/weblink.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ur' unless Object.const_defined?(:Ur)
|
4
|
+
|
5
|
+
module Ur
|
6
|
+
# a RFC5988 Web Link
|
7
|
+
#
|
8
|
+
# https://tools.ietf.org/html/rfc5988
|
9
|
+
class Weblink
|
10
|
+
# Weblink::Error, base class for all errors of the Weblink class
|
11
|
+
class Error < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
# error parsing a Weblink
|
15
|
+
class ParseError < Error
|
16
|
+
end
|
17
|
+
|
18
|
+
# error when attempting an operation that requires a context URI which was not provided
|
19
|
+
class NoContextError < Error
|
20
|
+
end
|
21
|
+
|
22
|
+
# parses an array of Web Links from the value an HTTP Link header, as described in
|
23
|
+
# https://tools.ietf.org/html/rfc5988#section-5
|
24
|
+
#
|
25
|
+
# returns an Array of Weblink objects
|
26
|
+
def self.parse_link_value(link_value, context_uri=nil)
|
27
|
+
links = []
|
28
|
+
|
29
|
+
return links unless link_value
|
30
|
+
|
31
|
+
attr_char = /[a-zA-Z0-9!#\$&+\-.^_`|~]/ # defined in https://tools.ietf.org/html/rfc5987#section-3.2.1
|
32
|
+
ptoken = %r([a-zA-Z0-9!#\$%&'()*+\-./:<=>?@\[\]^_`{|}~])
|
33
|
+
quoted_string = /"([^"]*)"/
|
34
|
+
|
35
|
+
require 'strscan'
|
36
|
+
ss = StringScanner.new(link_value)
|
37
|
+
parse_fail = proc do
|
38
|
+
raise ParseError, "Unable to parse link value: #{link_value} " +
|
39
|
+
"around character #{ss.pos}: #{ss.peek(link_value.length - ss.pos)}"
|
40
|
+
end
|
41
|
+
|
42
|
+
while !ss.eos?
|
43
|
+
# get the target_uri, within some angle brackets
|
44
|
+
ss.scan(/\s*<([^>]+)>/) || parse_fail.call
|
45
|
+
target_uri = ss[1]
|
46
|
+
attributes = {}
|
47
|
+
# get the attributes: semicolon, some attr_chars, an optional asterisk, equals, and a quoted
|
48
|
+
# string or series of unquoted ptokens
|
49
|
+
while ss.scan(/\s*;\s*(#{attr_char.source}+\*?)\s*=\s*(?:#{quoted_string.source}|(#{ptoken.source}+))\s*/)
|
50
|
+
attributes[ss[1]] = ss[2] || ss[3]
|
51
|
+
end
|
52
|
+
links << new(target_uri, attributes, context_uri)
|
53
|
+
unless ss.eos?
|
54
|
+
# either the string ends or has a comma followed by another link
|
55
|
+
ss.scan(/\s*,\s*/) || parse_fail.call
|
56
|
+
end
|
57
|
+
end
|
58
|
+
links
|
59
|
+
end
|
60
|
+
|
61
|
+
def initialize(target_uri, attributes, context_uri=nil)
|
62
|
+
@target_uri = to_addressable_uri(target_uri)
|
63
|
+
@attributes = attributes
|
64
|
+
@context_uri = to_addressable_uri(context_uri)
|
65
|
+
end
|
66
|
+
|
67
|
+
# the context uri of the link, as an Addressable URI. this URI must be absolute, and the target_uri
|
68
|
+
# may be resolved against it. this is most typically the request URI of a request to a service
|
69
|
+
attr_reader :context_uri
|
70
|
+
|
71
|
+
# RFC 5988 calls it IRI, but nobody else does. we'll throw in an alias.
|
72
|
+
alias_method :context_iri, :context_uri
|
73
|
+
|
74
|
+
# returns the target URI as an Addressable::URI
|
75
|
+
attr_reader :target_uri
|
76
|
+
|
77
|
+
# RFC 5988 calls it IRI, but nobody else does. we'll throw in an alias.
|
78
|
+
alias_method :target_iri, :target_uri
|
79
|
+
|
80
|
+
# attempts to make target_uri absolute, using context_uri if available. raises if
|
81
|
+
# there is not information available to make an absolute target URI
|
82
|
+
def absolute_target_uri
|
83
|
+
if target_uri.absolute?
|
84
|
+
target_uri
|
85
|
+
elsif context_uri
|
86
|
+
context_uri + target_uri
|
87
|
+
else
|
88
|
+
raise NoContextError, "Target URI is relative but no Context URI given - cannot determine absolute target URI"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# link attributes
|
93
|
+
attr_reader :attributes
|
94
|
+
|
95
|
+
# subscript returns an attribute of this Link, if defined, otherwise nil
|
96
|
+
def [](attribute_key)
|
97
|
+
@attributes[attribute_key]
|
98
|
+
end
|
99
|
+
|
100
|
+
# link rel attribute
|
101
|
+
def rel
|
102
|
+
self['rel']
|
103
|
+
end
|
104
|
+
|
105
|
+
alias_method :relation_type, :rel
|
106
|
+
|
107
|
+
# compares relation types in a case-insensitive manner as mandated in
|
108
|
+
# https://tools.ietf.org/html/rfc5988#section-4.1
|
109
|
+
def rel?(other_rel)
|
110
|
+
rel && other_rel && rel.downcase == other_rel.downcase
|
111
|
+
end
|
112
|
+
|
113
|
+
# a string of this weblink, appropriate for adding to a Link header
|
114
|
+
def to_s
|
115
|
+
"<#{target_uri}>" + attributes.map { |k,v| %Q(; #{k}="#{v}") }.join('')
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
# if uri is nil, returns nil; otherwise, tries to return a Addressable::URI
|
121
|
+
def to_addressable_uri(uri)
|
122
|
+
uri.nil? || uri.is_a?(Addressable::URI) ? uri : Addressable::URI.parse(uri)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/ur.rb
CHANGED
@@ -6,9 +6,10 @@ require 'jsi'
|
|
6
6
|
require 'time'
|
7
7
|
require 'addressable/uri'
|
8
8
|
require 'pathname'
|
9
|
+
require 'yaml'
|
9
10
|
|
10
11
|
UR_ROOT = Pathname.new(__FILE__).dirname.parent.expand_path
|
11
|
-
Ur = JSI
|
12
|
+
Ur = JSI.new_schema_module(YAML.load_file(UR_ROOT.join('resources/ur.schema.yml')))
|
12
13
|
module Ur
|
13
14
|
VERSION = UR_VERSION
|
14
15
|
|
@@ -18,10 +19,11 @@ module Ur
|
|
18
19
|
autoload :FaradayMiddleware, 'ur/middleware'
|
19
20
|
autoload :RackMiddleware, 'ur/middleware'
|
20
21
|
autoload :Faraday, 'ur/faraday'
|
22
|
+
autoload :Weblink, 'ur/weblink'
|
21
23
|
|
22
|
-
Request = self.
|
23
|
-
Response = self.
|
24
|
-
Metadata = self.
|
24
|
+
Request = self.properties['request']
|
25
|
+
Response = self.properties['response']
|
26
|
+
Metadata = self.properties['metadata']
|
25
27
|
require 'ur/request'
|
26
28
|
require 'ur/response'
|
27
29
|
require 'ur/metadata'
|
@@ -34,8 +36,7 @@ module Ur
|
|
34
36
|
raise(TypeError, "expected hash for ur instance. got: #{instance.pretty_inspect.chomp}")
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
ur_class.new(instance, options).tap do |ur|
|
39
|
+
JSI::SchemaSet[schema, *schemas].new_jsi(instance, **options).tap do |ur|
|
39
40
|
ur.request = {} if ur.request.nil?
|
40
41
|
ur.response = {} if ur.response.nil?
|
41
42
|
ur.metadata = {} if ur.metadata.nil?
|
@@ -51,7 +52,7 @@ module Ur
|
|
51
52
|
env = request_env
|
52
53
|
end
|
53
54
|
|
54
|
-
new({'bound' => 'inbound'}, options).tap do |ur|
|
55
|
+
new({'bound' => 'inbound'}, **options).tap do |ur|
|
55
56
|
ur.request['method'] = rack_request.request_method
|
56
57
|
|
57
58
|
ur.request.addressable_uri = Addressable::URI.new(
|
@@ -82,7 +83,7 @@ module Ur
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def from_faraday_request(request_env, **options)
|
85
|
-
new({'bound' => 'outbound'}, options).tap do |ur|
|
86
|
+
new({'bound' => 'outbound'}, **options).tap do |ur|
|
86
87
|
ur.request['method'] = request_env[:method].to_s
|
87
88
|
ur.request.uri = request_env[:url].normalize.to_s
|
88
89
|
ur.request.headers = request_env[:request_headers]
|
@@ -114,7 +115,7 @@ module Ur
|
|
114
115
|
[status, response_headers, response_body_proxy]
|
115
116
|
end
|
116
117
|
|
117
|
-
def faraday_on_complete(app, request_env
|
118
|
+
def faraday_on_complete(app, request_env)
|
118
119
|
app.call(request_env).on_complete do |response_env|
|
119
120
|
response.status = response_env[:status]
|
120
121
|
response.headers = response_env[:response_headers]
|
data/resources/ur.schema.yml
CHANGED
data/ur.gemspec
CHANGED
@@ -6,28 +6,25 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "ur"
|
7
7
|
spec.version = UR_VERSION
|
8
8
|
spec.authors = ["Ethan"]
|
9
|
-
spec.email = ["ethan@unth"]
|
9
|
+
spec.email = ["ethan.ur@unth.net"]
|
10
10
|
|
11
11
|
spec.summary = 'ur: unified request representation'
|
12
12
|
spec.description = 'ur provides a unified representation of a request and response. it can be interpreted from rack, faraday, or potentially other sources, and provides a consistent interface to access the attributes inherent to the request and additional useful parsers and computation from the request.'
|
13
13
|
spec.homepage = "https://github.com/notEthan/ur"
|
14
14
|
spec.license = "LGPL-3.0"
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
spec.files = [
|
17
|
+
'LICENSE.md',
|
18
|
+
'CHANGELOG.md',
|
19
|
+
'README.md',
|
20
|
+
'.yardopts',
|
21
|
+
'resources/ur.schema.yml',
|
22
|
+
'ur.gemspec',
|
23
|
+
*Dir['lib/**/*'],
|
24
|
+
].reject { |f| File.lstat(f).ftype == 'directory' }
|
25
|
+
|
20
26
|
spec.require_paths = ["lib"]
|
21
27
|
|
22
|
-
spec.add_dependency "jsi", "~> 0.
|
28
|
+
spec.add_dependency "jsi", "~> 0.6"
|
23
29
|
spec.add_dependency "addressable", "~> 2.0"
|
24
|
-
spec.add_development_dependency "rack"
|
25
|
-
spec.add_development_dependency "rack-test"
|
26
|
-
spec.add_development_dependency "faraday"
|
27
|
-
spec.add_development_dependency "faraday_middleware"
|
28
|
-
spec.add_development_dependency "activesupport"
|
29
|
-
spec.add_development_dependency "rake"
|
30
|
-
spec.add_development_dependency "minitest"
|
31
|
-
spec.add_development_dependency "minitest-reporters"
|
32
|
-
spec.add_development_dependency "simplecov"
|
33
30
|
end
|