ur 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08e517b90ad97d890764bc228d8836e7e48d7f8250ed7c3a4878368b77b2deb2'
4
- data.tar.gz: e87aedb3a622a5606bff0370cc1a06f43d98be53488389c1902e989226760cd1
3
+ metadata.gz: 1161e5f2e2219053fc4c54e541feb0d4c6efa1c1af930365e526a88bc0973e1b
4
+ data.tar.gz: b42e166ae62f0a651d5425147e64b1d200c09862869188b8f95e52454f7b8e97
5
5
  SHA512:
6
- metadata.gz: '069f50e6768b41beb13830308fd3a3d18845c32fc38f6e95755b8f929ba88e20efcfce8f84abf50ed393a93f9c2971bb7b280e5793d43098c06dc034f136487c'
7
- data.tar.gz: 42c005bf4853f4bb946a2bd143696c84fa84c6f933b71a6425505722aab150f290ab21265ac2b6e9fdaa313e0207becb46f5a14ff20a7cd2c18e4daa53d12084
6
+ metadata.gz: 17187f65ff16035e72fc7d7e0b9468bd970d337b1f8173fbc2dde15f420ad406aa33ecb440b4b65e0dffb921279660fdedb48b4bb320ce3e4e9a411eec3a21da
7
+ data.tar.gz: 8c8d0f0c86af8a97c18dc794e69b84634421607a7e6715120b90fd3d9f74bdd1848a5c422598dbc06fdb0ea7ce4ac474e76b761ec7e2243fdb87b2aa812af292
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # v0.2.1
2
+
3
+ - JSI v0.6.0
4
+
1
5
  # v0.2.0
2
6
 
3
7
  - Ur uses JSI schema modules instead of classes
@@ -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 /<subtype> construct should not be optional. however, we'll aim
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,44 +120,53 @@ module Ur
116
120
  freeze
117
121
  end
118
122
 
119
- # @return [String, nil] the media type of this content type.
120
- # e.g. "application/vnd.github+json" in content-type: application/vnd.github+json; charset="utf-8"
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
- # @return [String, nil] the 'type' portion of our media type.
124
- # e.g. "application" in content-type: application/vnd.github+json; charset="utf-8"
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
- # @return [String, nil] the 'subtype' portion of our media type.
128
- # e.g. "vnd.github+json" in content-type: application/vnd.github+json; charset="utf-8"
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
- # @return [String, nil] the 'facet' portion of our media type.
132
- # e.g. "vnd" in content-type: application/vnd.github+json; charset="utf-8"
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
- # @return [String, nil] the 'suffix' portion of our media type.
136
- # e.g. "json" in content-type: application/vnd.github+json; charset="utf-8"
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
- # @return [Hash<String, String>] parameters of this content type.
140
- # e.g. {"charset" => "utf-8"} in content-type: application/vnd.github+json; charset="utf-8"
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] is the 'type' portion of our media type equal (case-insensitive) to the given other_type
155
+ # @return [Boolean]
145
156
  def type?(other_type)
146
157
  type && type.casecmp?(other_type)
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] is the 'subtype' portion of our media type equal (case-insensitive) to the given other_subtype
162
+ # @return [Boolean]
151
163
  def subtype?(other_subtype)
152
164
  subtype && subtype.casecmp?(other_subtype)
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] is the 'suffix' portion of our media type equal (case-insensitive) to the given other_suffix
169
+ # @return [Boolean]
157
170
  def suffix?(other_suffix)
158
171
  suffix && suffix.casecmp?(other_suffix)
159
172
  end
@@ -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] does this content type appear to be binary?
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,52 +206,62 @@ module Ur
192
206
  return unknown
193
207
  end
194
208
 
195
- # @return [Boolean] is this a JSON content type?
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
- # @return [Boolean] is this an XML content type?
215
+ # is this an XML content type?
216
+ # @return [Boolean]
201
217
  def xml?
202
218
  suffix ? suffix.casecmp?('xml'): subtype ? subtype.casecmp?('xml') : false
203
219
  end
204
220
 
205
- # @return [Boolean] is this a x-www-form-urlencoded content type?
221
+ # is this a `x-www-form-urlencoded` content type?
222
+ # @return [Boolean]
206
223
  def form_urlencoded?
207
224
  suffix ? suffix.casecmp?('x-www-form-urlencoded'): subtype ? subtype.casecmp?('x-www-form-urlencoded') : false
208
225
  end
209
226
 
210
- # @return [Boolean] is the 'type' portion of our media type 'text'
227
+ # is the 'type' portion of our media type 'text'
228
+ # @return [Boolean]
211
229
  def type_text?
212
230
  type && type.casecmp?('text')
213
231
  end
214
232
 
215
- # @return [Boolean] is the 'type' portion of our media type 'image'
233
+ # is the 'type' portion of our media type 'image'
234
+ # @return [Boolean]
216
235
  def type_image?
217
236
  type && type.casecmp?('image')
218
237
  end
219
238
 
220
- # @return [Boolean] is the 'type' portion of our media type 'audio'
239
+ # is the 'type' portion of our media type 'audio'
240
+ # @return [Boolean]
221
241
  def type_audio?
222
242
  type && type.casecmp?('audio')
223
243
  end
224
244
 
225
- # @return [Boolean] is the 'type' portion of our media type 'video'
245
+ # is the 'type' portion of our media type 'video'
246
+ # @return [Boolean]
226
247
  def type_video?
227
248
  type && type.casecmp?('video')
228
249
  end
229
250
 
230
- # @return [Boolean] is the 'type' portion of our media type 'application'
251
+ # is the 'type' portion of our media type 'application'
252
+ # @return [Boolean]
231
253
  def type_application?
232
254
  type && type.casecmp?('application')
233
255
  end
234
256
 
235
- # @return [Boolean] is the 'type' portion of our media type 'message'
257
+ # is the 'type' portion of our media type 'message'
258
+ # @return [Boolean]
236
259
  def type_message?
237
260
  type && type.casecmp?('message')
238
261
  end
239
262
 
240
- # @return [Boolean] is the 'type' portion of our media type 'multipart'
263
+ # is the 'type' portion of our media type 'multipart'
264
+ # @return [Boolean]
241
265
  def type_multipart?
242
266
  type && type.casecmp?('multipart')
243
267
  end
@@ -25,9 +25,10 @@ module Ur
25
25
  end
26
26
  include FaradayEntity
27
27
 
28
- # @return [Ur::ContentType] the string value of the content type header. returns an
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
- # @return [Boolean] is our content type JSON?
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
- # @return [Boolean] is our content type XML?
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
- # @return [Boolean] is our content type x-www-form-urlencoded?
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
@@ -5,7 +5,7 @@ require 'ur' unless Object.const_defined?(:Ur)
5
5
  module Ur
6
6
  module SubUr
7
7
  def ur
8
- parent_jsis.detect { |p| p.is_a?(::Ur) }
8
+ jsi_parent_nodes.detect { |p| p.is_a?(::Ur) }
9
9
  end
10
10
  end
11
11
  end
data/lib/ur/version.rb CHANGED
@@ -1 +1 @@
1
- UR_VERSION = "0.2.0".freeze
1
+ UR_VERSION = "0.2.1".freeze
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::Schema.new(YAML.load_file(UR_ROOT.join('resources/ur.schema.yml'))).jsi_schema_module
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
 
@@ -19,9 +20,9 @@ module Ur
19
20
  autoload :RackMiddleware, 'ur/middleware'
20
21
  autoload :Faraday, 'ur/faraday'
21
22
 
22
- Request = self.schema.properties['request'].jsi_schema_module
23
- Response = self.schema.properties['response'].jsi_schema_module
24
- Metadata = self.schema.properties['metadata'].jsi_schema_module
23
+ Request = self.properties['request']
24
+ Response = self.properties['response']
25
+ Metadata = self.properties['metadata']
25
26
  require 'ur/request'
26
27
  require 'ur/response'
27
28
  require 'ur/metadata'
@@ -34,8 +35,7 @@ module Ur
34
35
  raise(TypeError, "expected hash for ur instance. got: #{instance.pretty_inspect.chomp}")
35
36
  end
36
37
 
37
- ur_class = JSI.class_for_schemas(Set[schema] + schemas)
38
- ur_class.new(instance, options).tap do |ur|
38
+ JSI::SchemaSet[schema, *schemas].new_jsi(instance, **options).tap do |ur|
39
39
  ur.request = {} if ur.request.nil?
40
40
  ur.response = {} if ur.response.nil?
41
41
  ur.metadata = {} if ur.metadata.nil?
@@ -1,3 +1,4 @@
1
+ $schema: http://json-schema.org/draft-07/schema
1
2
  $id: https://schemas.ur.unth.net/ur
2
3
  type: object
3
4
  properties:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ur
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-06 00:00:00.000000000 Z
11
+ date: 2022-01-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jsi
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.4'
19
+ version: 0.6.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.4'
26
+ version: 0.6.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: addressable
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,148 +38,19 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rack
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: rack-test
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: faraday
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: faraday_middleware
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: activesupport
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rake
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: minitest
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: minitest-reporters
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: simplecov
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
41
  description: ur provides a unified representation of a request and response. it can
168
42
  be interpreted from rack, faraday, or potentially other sources, and provides a
169
43
  consistent interface to access the attributes inherent to the request and additional
170
44
  useful parsers and computation from the request.
171
45
  email:
172
- - ethan@unth
46
+ - ethan.ur@unth.net
173
47
  executables: []
174
48
  extensions: []
175
49
  extra_rdoc_files: []
176
50
  files:
177
- - ".simplecov"
178
- - ".yardopts"
179
51
  - CHANGELOG.md
180
52
  - LICENSE.md
181
53
  - README.md
182
- - Rakefile.rb
183
54
  - lib/ur.rb
184
55
  - lib/ur/content_type.rb
185
56
  - lib/ur/faraday.rb
@@ -191,15 +62,7 @@ files:
191
62
  - lib/ur/response.rb
192
63
  - lib/ur/sub_ur.rb
193
64
  - lib/ur/version.rb
194
- - resources/icons/LGPL-3.0.png
195
65
  - resources/ur.schema.yml
196
- - test/content_type_test.rb
197
- - test/test_helper.rb
198
- - test/ur_faraday_test.rb
199
- - test/ur_metadata_test.rb
200
- - test/ur_rack_test.rb
201
- - test/ur_test.rb
202
- - ur.gemspec
203
66
  homepage: https://github.com/notEthan/ur
204
67
  licenses:
205
68
  - LGPL-3.0
@@ -219,15 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
219
82
  - !ruby/object:Gem::Version
220
83
  version: '0'
221
84
  requirements: []
222
- rubygems_version: 3.0.6
85
+ rubygems_version: 3.1.2
223
86
  signing_key:
224
87
  specification_version: 4
225
88
  summary: 'ur: unified request representation'
226
- test_files:
227
- - test/content_type_test.rb
228
- - test/test_helper.rb
229
- - test/ur_faraday_test.rb
230
- - test/ur_metadata_test.rb
231
- - test/ur_rack_test.rb
232
- - test/ur_test.rb
233
- - ".simplecov"
89
+ test_files: []
data/.simplecov DELETED
@@ -1 +0,0 @@
1
- SimpleCov.start
data/.yardopts DELETED
@@ -1 +0,0 @@
1
- --main README.md --markup=markdown {lib}/**/*.rb
data/Rakefile.rb DELETED
@@ -1,9 +0,0 @@
1
- require "rake/testtask"
2
-
3
- Rake::TestTask.new(:test) do |t|
4
- t.libs << "test"
5
- t.libs << "lib"
6
- t.test_files = FileList["test/**/*_test.rb"]
7
- end
8
-
9
- task :default => :test
Binary file
@@ -1,342 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe 'Ur::ContentType' do
4
- let(:content_type) { Ur::ContentType.new(content_type_str) }
5
- describe 'application/vnd.github+json; charset="utf-8"' do
6
- let(:content_type_str) { 'application/vnd.github+json; charset="utf-8"' }
7
- it 'parses' do
8
- assert_equal(content_type, content_type_str)
9
-
10
- assert_equal('application/vnd.github+json', content_type.media_type)
11
-
12
- assert_equal('application', content_type.type)
13
- assert(content_type.type?('Application'))
14
- assert(content_type.type_application?)
15
-
16
- assert_equal('vnd.github+json', content_type.subtype)
17
- assert_equal('vnd', content_type.facet)
18
- assert_equal('json', content_type.suffix)
19
-
20
- assert_equal({'charset' => 'utf-8'}, content_type.parameters)
21
- assert_equal('utf-8', content_type.parameters['CharSet'])
22
- end
23
- end
24
- describe 'no subtype' do
25
- let(:content_type_str) { 'application; charset="utf-8"' }
26
- it 'will allow it' do
27
- assert_equal(content_type, content_type_str)
28
-
29
- assert_equal('application', content_type.media_type)
30
-
31
- assert_equal('application', content_type.type)
32
- assert(content_type.type?('Application'))
33
-
34
- assert_equal(nil, content_type.subtype)
35
- assert_equal(nil, content_type.facet)
36
- assert_equal(nil, content_type.suffix)
37
-
38
- assert_equal({'charset' => 'utf-8'}, content_type.parameters)
39
- assert_equal('utf-8', content_type.parameters['CharSet'])
40
- end
41
- end
42
- describe 'no facet' do
43
- let(:content_type_str) { 'application/github+json; charset="utf-8"' }
44
- it 'parses' do
45
- assert_equal(content_type, content_type_str)
46
-
47
- assert_equal('application/github+json', content_type.media_type)
48
-
49
- assert_equal('application', content_type.type)
50
- assert(content_type.type?('Application'))
51
-
52
- assert_equal('github+json', content_type.subtype)
53
- assert_equal(nil, content_type.facet)
54
- assert_equal('json', content_type.suffix)
55
-
56
- assert_equal({'charset' => 'utf-8'}, content_type.parameters)
57
- assert_equal('utf-8', content_type.parameters['CharSet'])
58
- end
59
- end
60
- describe 'no suffix' do
61
- let(:content_type_str) { 'application/vnd.github.json; charset="utf-8"' }
62
- it 'parses' do
63
- assert_equal(content_type, content_type_str)
64
-
65
- assert_equal('application/vnd.github.json', content_type.media_type)
66
-
67
- assert_equal('application', content_type.type)
68
- assert(content_type.type?('Application'))
69
-
70
- assert_equal('vnd.github.json', content_type.subtype)
71
- assert_equal('vnd', content_type.facet)
72
- assert_equal(nil, content_type.suffix)
73
-
74
- assert_equal({'charset' => 'utf-8'}, content_type.parameters)
75
- assert_equal('utf-8', content_type.parameters['CharSet'])
76
- end
77
- describe('[invalid] quote in type') do
78
- let(:content_type_str) { 'applic"ation/foo; foo=bar' }
79
- it('gives up') do
80
- assert_equal('applic', content_type.type)
81
- assert_equal(nil, content_type.subtype)
82
- end
83
- end
84
- describe('[invalid] backslash in type') do
85
- let(:content_type_str) { 'applicati\on/foo; foo=bar' }
86
- it('parses') do
87
- assert_equal('applicati\\on', content_type.type)
88
- assert_equal('foo', content_type.subtype)
89
- end
90
- end
91
- describe('[invalid] quote in subtype') do
92
- let(:content_type_str) { 'application/f"oo; foo=bar' }
93
- it('gives up') do
94
- assert_equal('application', content_type.type)
95
- assert_equal('f', content_type.subtype)
96
- end
97
- end
98
- describe('[invalid] backslash in subtype') do
99
- let(:content_type_str) { 'application/fo\\o; foo=bar' }
100
- it('parses') do
101
- assert_equal('application', content_type.type)
102
- assert_equal('fo\\o', content_type.subtype)
103
- end
104
- end
105
- end
106
- describe 'parameters' do
107
- describe 'basic usage' do
108
- let(:content_type_str) { 'application/foo; charset="utf-8"; foo=bar' }
109
- it('parses') do
110
- assert_equal({'charset' => 'utf-8', 'foo' => 'bar'}, content_type.parameters)
111
- end
112
- end
113
- describe 'params with capitalization' do
114
- let(:content_type_str) { 'application/foo; Charset="utf-8"; FOO=bar' }
115
- it('parses') do
116
- assert_equal({'charset' => 'utf-8', 'foo' => 'bar'}, content_type.parameters)
117
- assert_equal('utf-8', content_type.parameters['CharSet'])
118
- assert_equal('utf-8', content_type.parameters['Charset'])
119
- assert_equal('bar', content_type.parameters['foo'])
120
- assert_equal('bar', content_type.parameters['FOO'])
121
- end
122
- end
123
- describe 'repeated params' do
124
- let(:content_type_str) { 'application/foo; foo="first"; foo=second' }
125
- it('will just overwrite') do
126
- assert_equal({'foo' => 'second'}, content_type.parameters)
127
- end
128
- end
129
- describe 'repeated params, different capitalization' do
130
- let(:content_type_str) { 'application/foo; FOO=first; Foo=second' }
131
- it('will just overwrite') do
132
- assert_equal({'foo' => 'second'}, content_type.parameters)
133
- end
134
- end
135
- describe 'empty strings' do
136
- let(:content_type_str) { 'application/foo; empty1=; empty2=""' }
137
- it('parses') do
138
- assert_equal({'empty1' => '', 'empty2' => ''}, content_type.parameters)
139
- end
140
- end
141
- describe 'empty strings with whitespace' do
142
- let(:content_type_str) { 'application/foo; empty1= ; empty2="" ' }
143
- it('parses') do
144
- assert_equal({'empty1' => '', 'empty2' => ''}, content_type.parameters)
145
- end
146
- end
147
- describe('[invalid] opening quote only') do
148
- let(:content_type_str) { 'application/foo; foo=1; bar="' }
149
- it('parses') do
150
- assert_equal({'foo' => '1', 'bar' => ''}, content_type.parameters)
151
- end
152
- end
153
- describe('[invalid] backlash with no character') do
154
- let(:content_type_str) { 'application/foo; foo=1; bar="\\' }
155
- it('parses') do
156
- assert_equal({'foo' => '1', 'bar' => ''}, content_type.parameters)
157
- end
158
- end
159
- describe('[invalid] extra following quoted string') do
160
- let(:content_type_str) { 'application/foo; foo="1" 2; bar=3' }
161
- it('sorta parses') do
162
- assert_equal({'foo' => '1 2', 'bar' => '3'}, content_type.parameters)
163
- end
164
- end
165
- describe('[invalid] quotes silliness') do
166
- let(:content_type_str) { 'application/foo; foo="1" 2 "3 4" "5 " ; bar=3' }
167
- it('sorta parses') do
168
- assert_equal({'foo' => '1 2 3 4 5 ', 'bar' => '3'}, content_type.parameters)
169
- end
170
- end
171
- describe('[invalid] backlash quote') do
172
- let(:content_type_str) { 'application/foo; foo=1; bar="\\"' }
173
- it('parses') do
174
- assert_equal({'foo' => '1', 'bar' => '"'}, content_type.parameters)
175
- end
176
- end
177
- describe('[invalid] trailing ;') do
178
- let(:content_type_str) { 'application/foo; foo=bar;' }
179
- it('parses') do
180
- assert_equal({'foo' => 'bar'}, content_type.parameters)
181
- end
182
- end
183
- describe('[invalid] extra ; inline') do
184
- let(:content_type_str) { 'application/foo; ; ; foo=bar' }
185
- it('parses') do
186
- assert_equal({'foo' => 'bar'}, content_type.parameters)
187
- end
188
- end
189
- describe('[invalid] whitespace around the =') do
190
- let(:content_type_str) { 'application/foo; foo = bar; baz = qux' }
191
- it('parses') do
192
- assert_equal({'foo ' => ' bar', 'baz ' => ' qux'}, content_type.parameters)
193
- end
194
- end
195
- describe('whitespace before the ;') do
196
- let(:content_type_str) { 'application/foo; foo=bar ; baz=qux' }
197
- it('parses') do
198
- assert_equal({'foo' => 'bar', 'baz' => 'qux'}, content_type.parameters)
199
- end
200
- end
201
- describe('no media_type') do
202
- let(:content_type_str) { '; foo=bar' }
203
- it('parses') do
204
- assert_equal({'foo' => 'bar'}, content_type.parameters)
205
- end
206
- end
207
- describe('[invalid] quote in parameter name') do
208
- let(:content_type_str) { 'application/foo; fo"o=bar' }
209
- it('gives up') do
210
- assert_equal({}, content_type.parameters)
211
- end
212
- end
213
- describe('[invalid] backslash in parameter name') do
214
- let(:content_type_str) { 'application/foo; fo\\o=bar' }
215
- it('parses') do
216
- assert_equal({'fo\\o' => 'bar'}, content_type.parameters)
217
- end
218
- end
219
- end
220
- describe 'binary?' do
221
- binary_content_type_strs = [
222
- 'audio/ogg',
223
- 'Audio/OGG; foo=bar',
224
- 'VIDEO/foo+bar',
225
- ]
226
- binary_content_type_strs.each do |binary_content_type_str|
227
- describe(binary_content_type_str) do
228
- let(:content_type_str) { binary_content_type_str }
229
- it 'is binary' do
230
- assert(content_type.binary?(unknown: false))
231
- end
232
- end
233
- end
234
- not_binary_content_type_strs = [
235
- 'text/anything',
236
- 'TEXT/plain; charset=foo',
237
- 'application/JSON',
238
- 'media/foo+Json; foo="bar"',
239
- ]
240
- not_binary_content_type_strs.each do |not_binary_content_type_str|
241
- describe(not_binary_content_type_str) do
242
- let(:content_type_str) { not_binary_content_type_str }
243
- it 'is not binary' do
244
- assert(!content_type.binary?(unknown: true))
245
- end
246
- end
247
- end
248
- unknown_content_type_strs = [
249
- 'foo',
250
- 'foo/bar; note="not application/json"',
251
- 'application/jsonisnotthis',
252
- 'application/octet-stream',
253
- ]
254
- unknown_content_type_strs.each do |unknown_content_type_str|
255
- describe(unknown_content_type_str) do
256
- let(:content_type_str) { unknown_content_type_str }
257
- it 'is unknown' do
258
- assert(content_type.binary?(unknown: true))
259
- assert(!content_type.binary?(unknown: false))
260
- end
261
- end
262
- end
263
- end
264
- describe 'json?' do
265
- json_content_type_strs = [
266
- 'application/json',
267
- 'Application/Json; charset=EBCDIC',
268
- 'Text/json',
269
- 'MEDIA/JSON',
270
- 'media/foo.bar+json',
271
- 'media/foo.bar+json; foo=',
272
- ]
273
- json_content_type_strs.each do |json_content_type_str|
274
- describe(json_content_type_str) do
275
- let(:content_type_str) { json_content_type_str }
276
- it 'is json' do
277
- assert(content_type.json?)
278
- end
279
- end
280
- end
281
- not_json_content_type_strs = [
282
- 'json',
283
- 'foo/bar; note="not application/json"',
284
- 'application/jsonisnotthis',
285
- 'text/json+xml', # I don't even know what I'm trying for here
286
- ]
287
- not_json_content_type_strs.each do |not_json_content_type_str|
288
- describe(not_json_content_type_str) do
289
- let(:content_type_str) { not_json_content_type_str }
290
- it 'is not json' do
291
- assert(!content_type.json?)
292
- end
293
- end
294
- end
295
- end
296
- describe 'xml?' do
297
- xml_content_type_strs = [
298
- 'application/xml',
299
- 'Application/Xml; charset=EBCDIC',
300
- 'Text/xml',
301
- 'MEDIA/XML',
302
- 'media/foo.bar+xml',
303
- 'media/foo.bar+xml; foo=',
304
- ]
305
- xml_content_type_strs.each do |xml_content_type_str|
306
- describe(xml_content_type_str) do
307
- let(:content_type_str) { xml_content_type_str }
308
- it 'is xml' do
309
- assert(content_type.xml?)
310
- end
311
- end
312
- end
313
- not_xml_content_type_strs = [
314
- 'xml',
315
- 'foo/bar; note="not application/xml"',
316
- 'application/xmlisnotthis',
317
- 'text/xml+json', # I don't even know what I'm trying for here
318
- ]
319
- not_xml_content_type_strs.each do |not_xml_content_type_str|
320
- describe(not_xml_content_type_str) do
321
- let(:content_type_str) { not_xml_content_type_str }
322
- it 'is not xml' do
323
- assert(!content_type.xml?)
324
- end
325
- end
326
- end
327
- end
328
- describe 'form_urlencoded?' do
329
- describe('application/x-www-form-urlencoded') do
330
- let(:content_type_str) { 'application/x-www-form-urlencoded' }
331
- it 'is form_urlencoded' do
332
- assert(content_type.form_urlencoded?)
333
- end
334
- end
335
- describe('application/foo') do
336
- let(:content_type_str) { 'application/foo' }
337
- it 'is not form_urlencoded' do
338
- assert(!content_type.form_urlencoded?)
339
- end
340
- end
341
- end
342
- end
data/test/test_helper.rb DELETED
@@ -1,33 +0,0 @@
1
- proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('../lib', File.dirname(__FILE__)))
2
-
3
- require 'simplecov'
4
- require 'byebug'
5
-
6
- # NO EXPECTATIONS
7
- ENV["MT_NO_EXPECTATIONS"] = ''
8
-
9
- require 'minitest/autorun'
10
- require 'minitest/reporters'
11
- Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
12
-
13
- class UrSpec < Minitest::Spec
14
- if ENV['UR_TEST_ALPHA']
15
- # :nocov:
16
- define_singleton_method(:test_order) { :alpha }
17
- # :nocov:
18
- end
19
-
20
- def assert_json_equal(exp, act, *a)
21
- assert_equal(JSI::Typelike.as_json(exp), JSI::Typelike.as_json(act), *a)
22
- end
23
-
24
- def assert_equal exp, act, msg = nil
25
- msg = message(msg, E) { diff exp, act }
26
- assert exp == act, msg
27
- end
28
- end
29
-
30
- # register this to be the base class for specs instead of Minitest::Spec
31
- Minitest::Spec.register_spec_type(//, UrSpec)
32
-
33
- require 'ur'
@@ -1,79 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'faraday'
3
- require 'faraday_middleware'
4
-
5
- describe 'Ur faraday integration' do
6
- it 'integrates, basic usage' do
7
- ur = nil
8
- faraday_conn = ::Faraday.new('https://ur.unth.net/') do |builder|
9
- builder.use(Ur::FaradayMiddleware,
10
- after_response: -> (ur_) { ur = ur_ },
11
- )
12
- builder.adapter(:rack, -> (env) { [200, {'Content-Type' => 'text/plain'}, ['ᚒ']] })
13
- end
14
- res = faraday_conn.get('/')
15
- assert_equal('ᚒ', res.body)
16
- assert_kind_of(Ur, ur)
17
- assert_equal('get', ur.request['method'])
18
- assert_equal('text/plain', ur.response.headers['Content-Type'])
19
- assert_equal('ᚒ', ur.response.body)
20
- assert(ur.validate)
21
- end
22
- it 'integrates, IO body' do
23
- ur = nil
24
- faraday_conn = ::Faraday.new('https://ur.unth.net/') do |builder|
25
- builder.use(Ur::FaradayMiddleware,
26
- after_response: -> (ur_) { ur = ur_ },
27
- )
28
- builder.adapter(:rack, -> (env) { [200, {'Content-Type' => 'text/plain'}, ['☺']] })
29
- end
30
- res = faraday_conn.post('/', StringIO.new('hello!'))
31
- assert_equal('☺', res.body)
32
- assert_kind_of(Ur, ur)
33
- assert_equal('post', ur.request['method'])
34
- assert_equal('hello!', ur.request.body)
35
- assert_equal('text/plain', ur.response.headers['Content-Type'])
36
- assert_equal('☺', ur.response.body)
37
- assert(ur.validate)
38
- end
39
- it 'integrates, faraday middleware munges the json bodies but uses preserve_raw' do
40
- ur = nil
41
- faraday_conn = ::Faraday.new('https://ur.unth.net/') do |builder|
42
- builder.request :json
43
- builder.use(Ur::FaradayMiddleware,
44
- after_response: -> (ur_) { ur = ur_ },
45
- )
46
- builder.response :json, preserve_raw: true
47
- builder.adapter(:rack, -> (env) { [200, {'Content-Type' => 'application/json'}, ['{}']] })
48
- end
49
- res = faraday_conn.post('/', {'a' => 'b'})
50
- assert_equal({}, res.body)
51
- assert_kind_of(Ur, ur)
52
- assert_equal('post', ur.request['method'])
53
- assert_equal('{"a":"b"}', ur.request.body)
54
- assert_equal('application/json', ur.response.headers['Content-Type'])
55
- assert_equal('{}', ur.response.body)
56
- assert(ur.validate)
57
- end
58
- it 'integrates, faraday middleware munges the json bodies and does not preserve_raw' do
59
- ur = nil
60
- faraday_conn = ::Faraday.new('https://ur.unth.net/') do |builder|
61
- builder.use(Ur::FaradayMiddleware,
62
- after_response: -> (ur_) { ur = ur_ },
63
- )
64
- builder.request :json
65
- builder.response :json
66
- builder.adapter(:rack, -> (env) { [200, {'Content-Type' => 'application/json'}, ['{}']] })
67
- end
68
- res = faraday_conn.post('/', {'a' => 'b'})
69
- assert_equal({}, res.body)
70
- assert_kind_of(Ur, ur)
71
- assert_equal('post', ur.request['method'])
72
- assert_nil(ur.request.body) # no good
73
- assert_json_equal({"a" => "b"}, ur.request['body_parsed']) # best we get here
74
- assert_equal('application/json', ur.response.headers['Content-Type'])
75
- assert_nil(ur.response.body) # no good
76
- assert_json_equal({}, ur.response['body_parsed']) # best we get here
77
- assert(ur.validate)
78
- end
79
- end
@@ -1,11 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- describe 'Ur metadata' do
4
- it 'sets duration from began_at' do
5
- ur = Ur.new
6
- ur.metadata.began_at = Time.now
7
- ur.metadata.finish!
8
- assert_instance_of(Float, ur.metadata.duration)
9
- assert_operator(ur.metadata.duration, :>, 0)
10
- end
11
- end
data/test/ur_rack_test.rb DELETED
@@ -1,25 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'rack'
3
-
4
- describe 'Ur rack integration' do
5
- it 'builds from a rack env' do
6
- env = Rack::MockRequest.env_for('https://ur.unth.net/', {'HTTP_FOO' => 'bar'})
7
- ur = Ur.from_rack_request(env)
8
- assert_equal('inbound', ur.bound)
9
- assert_equal('GET', ur.request['method'])
10
- assert_equal('bar', ur.request.headers['foo'])
11
- assert_equal('https://ur.unth.net/', ur.request.uri)
12
- assert(ur.response.empty?)
13
- assert(ur.validate)
14
- end
15
- it 'builds from a rack request' do
16
- env = Rack::Request.new(Rack::MockRequest.env_for('https://ur.unth.net/', {'HTTP_FOO' => 'bar'}))
17
- ur = Ur.from_rack_request(env)
18
- assert_equal('inbound', ur.bound)
19
- assert_equal('GET', ur.request['method'])
20
- assert_equal('bar', ur.request.headers['foo'])
21
- assert_equal('https://ur.unth.net/', ur.request.uri)
22
- assert(ur.response.empty?)
23
- assert(ur.validate)
24
- end
25
- end
data/test/ur_test.rb DELETED
@@ -1,105 +0,0 @@
1
- require_relative 'test_helper'
2
- require 'faraday'
3
- require 'active_support/tagged_logging'
4
-
5
- describe 'Ur' do
6
- it 'has a valid schema' do
7
- Ur.schema.validate_schema!
8
- end
9
-
10
- it 'initializes' do
11
- Ur.new_jsi({})
12
- end
13
-
14
- it 'would prefer not to initialize' do
15
- assert_raises(TypeError) { Ur.new("hello!") }
16
- end
17
-
18
- it 'integrates with rack and faraday middlewares' do
19
- rack_app = proc do |env|
20
- [200, {'Content-Type' => 'text/plain'}, ['ᚒ']]
21
- end
22
- client_logger = ActiveSupport::TaggedLogging.new(Logger.new(StringIO.new))
23
- server_logger = ActiveSupport::TaggedLogging.new(Logger.new(StringIO.new))
24
- called_rack_before_request = false
25
- called_rack_after_response = false
26
- called_faraday_before_request = false
27
- called_faraday_after_response = false
28
- rack_app = Ur::RackMiddleware.new(rack_app, logger: server_logger,
29
- before_request: -> (ur) do
30
- called_rack_before_request = true
31
-
32
- server_logger.push_tags 'ur_test_rack'
33
-
34
- assert_equal('inbound', ur.bound)
35
- assert_equal('GET', ur.request['method'])
36
- assert_equal('ur.unth.net', ur.request.headers['host'])
37
- assert_equal('bar', ur.request.headers['foo'])
38
- assert_equal('https://ur.unth.net/', ur.request.uri)
39
- assert(ur.response.empty?)
40
- assert_nil(ur.metadata.began_at)
41
- assert_nil(ur.metadata.duration)
42
- assert(ur.validate)
43
- end,
44
- after_response: -> (ur) do
45
- called_rack_after_response = true
46
-
47
- server_logger.pop_tags
48
-
49
- assert_equal('inbound', ur.bound)
50
- assert_equal('GET', ur.request['method'])
51
- assert_equal(200, ur.response.status)
52
- assert_equal('text/plain', ur.response.headers['Content-Type'])
53
- assert_equal('ᚒ', ur.response.body)
54
- assert_instance_of(Time, ur.metadata.began_at)
55
- assert_instance_of(Float, ur.metadata.duration)
56
- assert_operator(ur.metadata.duration, :>, 0)
57
- assert_equal(['ur_test_rack'], ur.metadata.tags.to_a)
58
- assert(ur.validate)
59
- end,
60
- )
61
- faraday_conn = ::Faraday.new('https://ur.unth.net/') do |builder|
62
- builder.use(Ur::FaradayMiddleware, logger: client_logger,
63
- before_request: -> (ur) do
64
- called_faraday_before_request = true
65
-
66
- client_logger.push_tags 'ur_test_faraday'
67
-
68
- assert_equal('outbound', ur.bound)
69
- assert_equal('get', ur.request['method'])
70
- assert_equal('bar', ur.request.headers['foo'])
71
- assert_equal('https://ur.unth.net/', ur.request.uri)
72
- assert_equal(Addressable::URI.parse('https://ur.unth.net/'), ur.request.addressable_uri)
73
- assert(ur.response.empty?)
74
- assert_nil(ur.metadata.began_at)
75
- assert_nil(ur.metadata.duration)
76
- assert(ur.validate)
77
- end,
78
- after_response: -> (ur) do
79
- called_faraday_after_response = true
80
-
81
- client_logger.pop_tags
82
-
83
- assert_equal('outbound', ur.bound)
84
- assert_equal('get', ur.request['method'])
85
- assert_equal(200, ur.response.status)
86
- assert_equal('text/plain', ur.response.headers['Content-Type'])
87
- assert_equal('ᚒ', ur.response.body)
88
- assert_instance_of(Time, ur.metadata.began_at)
89
- assert_instance_of(Float, ur.metadata.duration)
90
- assert_operator(ur.metadata.duration, :>, 0)
91
- assert_equal(['ur_test_faraday'], ur.metadata.tags.to_a)
92
- assert(ur.validate)
93
- end,
94
- )
95
- builder.adapter(:rack, rack_app)
96
- end
97
- res = faraday_conn.get('/', nil, {'Foo' => 'bar'})
98
- assert(called_rack_before_request)
99
- assert(called_rack_after_response)
100
- assert(called_faraday_before_request)
101
- assert(called_faraday_after_response)
102
- assert_equal(200, res.status)
103
- assert_equal('ᚒ', res.body)
104
- end
105
- end
data/ur.gemspec DELETED
@@ -1,33 +0,0 @@
1
- lib = File.expand_path("../lib", __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require "ur/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "ur"
7
- spec.version = UR_VERSION
8
- spec.authors = ["Ethan"]
9
- spec.email = ["ethan@unth"]
10
-
11
- spec.summary = 'ur: unified request representation'
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
- spec.homepage = "https://github.com/notEthan/ur"
14
- spec.license = "LGPL-3.0"
15
-
16
- ignore_files = %w(.gitignore .travis.yml Gemfile test)
17
- ignore_files_re = %r{\A(#{ignore_files.map { |f| Regexp.escape(f) }.join('|')})(/|\z)}
18
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(ignore_files_re) }
19
- spec.test_files = `git ls-files -z test`.split("\x0") + ['.simplecov']
20
- spec.require_paths = ["lib"]
21
-
22
- spec.add_dependency "jsi", "~> 0.4"
23
- 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
- end