scorn 0.4.1 → 0.6.0
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 +13 -0
- data/README.md +32 -0
- data/lib/scorn.rb +123 -6
- data/scorn.gemspec +0 -1
- metadata +1 -15
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5ba08d0daf842995b186b35c7617fb9f76e80789939cb17e2f42bf492e09aa4f
|
|
4
|
+
data.tar.gz: 36bbefc8c53658eed3aee3685088cf57884f52395fe9e3afc22ee33db841c427
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a7e169aa56ddb9acba9855a8c98ddaf9b6d43f9f2863726c5bb0c30a77702cbdfb61763912ee3661c0bd0435a4189f98efb6b48fe64c246efbcbdd13eb472da3
|
|
7
|
+
data.tar.gz: 1965a0ff5a7c74ba854609929ad38185fb7007e58a9a60fd39de17a774564010a71dae1ffa68eaa1f65a341ce4a4b10f34504add53952cbee6b885a786892f68
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
# CHANGELOG.md
|
|
3
3
|
|
|
4
4
|
|
|
5
|
+
## scorn 0.6.0 released 2026-10-15
|
|
6
|
+
|
|
7
|
+
* Use json:d to post JSON (body not form)
|
|
8
|
+
* Introduce Scorn::Debugger
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## scorn 0.5.0 released 2026-10-10
|
|
12
|
+
|
|
13
|
+
* Accept `x_foobar_header: 'hello'`
|
|
14
|
+
* `r._response._request._headers`
|
|
15
|
+
* Implement :etag/:if_none_match opt
|
|
16
|
+
|
|
17
|
+
|
|
5
18
|
## scorn 0.4.1 released 2026-09-02
|
|
6
19
|
|
|
7
20
|
* Tidy dependencies
|
data/README.md
CHANGED
|
@@ -9,6 +9,7 @@ A stupid HTTP client library.
|
|
|
9
9
|
```ruby
|
|
10
10
|
r = Scorn.get('https://example.com/data.json')
|
|
11
11
|
|
|
12
|
+
p r # => { "data" => [ "foo", "bar" ] }
|
|
12
13
|
p r._response._c # => 200
|
|
13
14
|
```
|
|
14
15
|
|
|
@@ -36,6 +37,37 @@ p r.class # => Hash
|
|
|
36
37
|
p r['form'] # => { 'n' => '-1', 'source' => 'src', 'target' => 'tgt' }
|
|
37
38
|
```
|
|
38
39
|
|
|
40
|
+
```ruby
|
|
41
|
+
r = Scorn.post(
|
|
42
|
+
'https://httpbin.org/post',
|
|
43
|
+
json: { who: 'Doomberg', what: 'buy gold', when: -1 },
|
|
44
|
+
debug: Scorn::Debugger.new)
|
|
45
|
+
|
|
46
|
+
p r['json'] # => { 'who' => 'Doomberg', 'what' => 'buy gold', 'when' => -1 }
|
|
47
|
+
|
|
48
|
+
p r._response._c # => 200
|
|
49
|
+
p r['url'] # => 'https://httpbin.org/post'
|
|
50
|
+
p r['headers']['Accept'] # => 'application/json'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Options:
|
|
54
|
+
|
|
55
|
+
* `accept:` for the `Accept` header
|
|
56
|
+
* `uauthorization:` or `auth:` for the `Authorization` header
|
|
57
|
+
* `content_type:` for the `Content-Type` header
|
|
58
|
+
* `etag:` or `if_none_match:` for the `If-None-Match` header
|
|
59
|
+
* `user_agent:` for the `Agent` header
|
|
60
|
+
* `ssl_verify: false`, `ssl_verify: :none`, `verify: false`, as expected
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
r = Scorn.get(
|
|
64
|
+
'https://httpbin.org/get',
|
|
65
|
+
auth: 'Bearer toto-nada-xplus',
|
|
66
|
+
json: true)
|
|
67
|
+
|
|
68
|
+
p r['headers']['Authorization'] # => 'Bearer toto-nada-xplus'
|
|
69
|
+
```
|
|
70
|
+
|
|
39
71
|
|
|
40
72
|
## LICENSE
|
|
41
73
|
|
data/lib/scorn.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
|
+
# scorn.rb
|
|
3
|
+
|
|
2
4
|
require 'json'
|
|
3
5
|
require 'time'
|
|
4
6
|
require 'base64'
|
|
5
|
-
require 'webrick' # for the http code to message mapping
|
|
6
7
|
require 'ostruct'
|
|
7
8
|
require 'openssl'
|
|
8
9
|
require 'net/http'
|
|
@@ -10,7 +11,7 @@ require 'net/http'
|
|
|
10
11
|
|
|
11
12
|
module Scorn
|
|
12
13
|
|
|
13
|
-
VERSION = '0.
|
|
14
|
+
VERSION = '0.6.0'.freeze
|
|
14
15
|
|
|
15
16
|
class << self
|
|
16
17
|
|
|
@@ -96,7 +97,22 @@ module Scorn
|
|
|
96
97
|
req = make_req(:post, uri, gather_headers(:post, opts))
|
|
97
98
|
|
|
98
99
|
data = opts[:data]
|
|
99
|
-
|
|
100
|
+
json = opts[:json]
|
|
101
|
+
|
|
102
|
+
if data
|
|
103
|
+
|
|
104
|
+
req.set_form_data(data)
|
|
105
|
+
|
|
106
|
+
elsif json.is_a?(Hash) || json.is_a?(Array)
|
|
107
|
+
|
|
108
|
+
req['Content-Type'] = 'application/json'
|
|
109
|
+
req.body = JSON.dump(json)
|
|
110
|
+
|
|
111
|
+
elsif json.is_a?(String)
|
|
112
|
+
|
|
113
|
+
req['Content-Type'] = 'application/json'
|
|
114
|
+
req.body = json
|
|
115
|
+
end
|
|
100
116
|
|
|
101
117
|
req
|
|
102
118
|
end
|
|
@@ -118,8 +134,13 @@ module Scorn
|
|
|
118
134
|
opts[:content_type] || 'application/x-www-form-urlencoded' \
|
|
119
135
|
if verb == :post
|
|
120
136
|
|
|
137
|
+
h['If-None-Match'] =
|
|
138
|
+
opts[:etag] || opts[:if_none_match] \
|
|
139
|
+
if verb == :get || verb == :head
|
|
140
|
+
|
|
121
141
|
opts.each do |k, v|
|
|
122
|
-
|
|
142
|
+
k = k.to_s.gsub('_', '-')
|
|
143
|
+
h[k] = v if k.start_with?(/x-/i)
|
|
123
144
|
end
|
|
124
145
|
|
|
125
146
|
h.compact!
|
|
@@ -142,6 +163,10 @@ module Scorn
|
|
|
142
163
|
|
|
143
164
|
headers.each { |k, v| req[k] = v }
|
|
144
165
|
|
|
166
|
+
class << req
|
|
167
|
+
def _headers; each_header.inject({}) { |h, (k, v)| h[k] = v; h }; end
|
|
168
|
+
end
|
|
169
|
+
|
|
145
170
|
req
|
|
146
171
|
end
|
|
147
172
|
|
|
@@ -163,7 +188,7 @@ module Scorn
|
|
|
163
188
|
res._uri = uri
|
|
164
189
|
res._request = req
|
|
165
190
|
res._c = res.code.to_i
|
|
166
|
-
res._sta =
|
|
191
|
+
res._sta = STATUS_CODES[res._c] || ''
|
|
167
192
|
res._elapsed = monow - t0
|
|
168
193
|
#res._proxy = detail_proxy(http)
|
|
169
194
|
|
|
@@ -203,11 +228,103 @@ module Scorn
|
|
|
203
228
|
else
|
|
204
229
|
s
|
|
205
230
|
end
|
|
206
|
-
class << r; attr_accessor :_response; end
|
|
231
|
+
class << r; attr_accessor :_response, :_debug; end
|
|
207
232
|
r._response = res
|
|
233
|
+
r._debug = @opts[:debug]
|
|
208
234
|
|
|
209
235
|
r
|
|
210
236
|
end
|
|
237
|
+
|
|
238
|
+
# https://www.iana.org/assignments/http-status-codes/http-status-codes-1.csv
|
|
239
|
+
#
|
|
240
|
+
STATUS_CODES = {
|
|
241
|
+
|
|
242
|
+
100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing',
|
|
243
|
+
|
|
244
|
+
200 => 'OK', 201 => 'Created', 202 => 'Accepted',
|
|
245
|
+
203 => 'Non-Authoritative Information',
|
|
246
|
+
204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
|
|
247
|
+
207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used',
|
|
248
|
+
|
|
249
|
+
300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found',
|
|
250
|
+
303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy',
|
|
251
|
+
307 => 'Temporary Redirect', 308 => 'Permanent Redirect',
|
|
252
|
+
|
|
253
|
+
400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required',
|
|
254
|
+
403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed',
|
|
255
|
+
406 => 'Not Acceptable', 407 => 'Proxy Authentication Required',
|
|
256
|
+
408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone',
|
|
257
|
+
411 => 'Length Required', 412 => 'Precondition Failed',
|
|
258
|
+
413 => 'Payload Too Large', 414 => 'URI Too Long',
|
|
259
|
+
415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable',
|
|
260
|
+
417 => 'Expectation Failed', 422 => 'Unprocessable Entity',
|
|
261
|
+
423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required',
|
|
262
|
+
428 => 'Precondition Required', 429 => 'Too Many Requests',
|
|
263
|
+
431 => 'Request Header Fields Too Large',
|
|
264
|
+
|
|
265
|
+
500 => 'Internal Server Error', 501 => 'Not Implemented',
|
|
266
|
+
502 => 'Bad Gateway', 503 => 'Service Unavailable',
|
|
267
|
+
504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported',
|
|
268
|
+
506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage',
|
|
269
|
+
508 => 'Loop Detected', 510 => 'Not Extended',
|
|
270
|
+
511 => 'Network Authentication Required'
|
|
271
|
+
|
|
272
|
+
}.freeze
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
class Debugger
|
|
276
|
+
|
|
277
|
+
attr_reader :a
|
|
278
|
+
|
|
279
|
+
def initialize; @a = []; end
|
|
280
|
+
|
|
281
|
+
def <<(l); @a << l; end
|
|
282
|
+
|
|
283
|
+
def to_s; @a.join(); end
|
|
284
|
+
|
|
285
|
+
def request_lines
|
|
286
|
+
|
|
287
|
+
@a.find { |s| s.match?(/\A"(GET|POST|HEAD|PUT|DELETE) /) }.split('\r\n')
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def request_headera
|
|
291
|
+
|
|
292
|
+
request_lines
|
|
293
|
+
.inject([]) { |a, l|
|
|
294
|
+
m = l.match(/\A([-a-zA-Z0-9]+): (.+)\z/)
|
|
295
|
+
a << [ m[1], m[2] ] if m
|
|
296
|
+
a }
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def response_header_lines
|
|
300
|
+
|
|
301
|
+
@a
|
|
302
|
+
.take_while { |l|
|
|
303
|
+
l != '-> "\\r\\n"\n' }
|
|
304
|
+
.inject([]) { |a, l|
|
|
305
|
+
m = l.match(/\A-> "(.+)\\r\\n"\n\z/)
|
|
306
|
+
a << m[1] if m
|
|
307
|
+
a }
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def response_headera
|
|
311
|
+
|
|
312
|
+
response_header_lines
|
|
313
|
+
.inject([]) { |a, l|
|
|
314
|
+
m = l.match(/\A([A-Z][-a-zA-Z0-9]*):\s*(.+)\z/)
|
|
315
|
+
a << [ m[1], m[2] ] if m
|
|
316
|
+
a }
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def request_headerh
|
|
320
|
+
|
|
321
|
+
request_headera.inject({}) { |h, (k, v)| h[k] = v; h }
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def response_headerh
|
|
325
|
+
|
|
326
|
+
response_headera.inject({}) { |h, (k, v)| h[k] = v; h }
|
|
327
|
+
end
|
|
211
328
|
end
|
|
212
329
|
end
|
|
213
330
|
|
data/scorn.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: scorn
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Mettraux
|
|
@@ -23,20 +23,6 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: webrick
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0'
|
|
33
|
-
type: :runtime
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - ">="
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0'
|
|
40
26
|
- !ruby/object:Gem::Dependency
|
|
41
27
|
name: ostruct
|
|
42
28
|
requirement: !ruby/object:Gem::Requirement
|