web_api 0.3.191208 → 2.0.221220
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/README.md +43 -33
- data/lib/web_api/web_api.rb +55 -50
- data/lib/web_api/web_api_method.rb +81 -77
- data/lib/web_api.rb +4 -8
- metadata +15 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45268acfd02c273b2cdc3287a654dbd673b6e1851d101ae35ec2cf50d8f24a55
|
4
|
+
data.tar.gz: 48566e13c223421ededbcfcc8433daa76e9f59b180c2cbd77069d0f63b71e9cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5401701566ec8629ddf63a4bdd046b086505ad196ce5f7cf0766db9f281b5c49a430d84b14f4f7fffc1877d966287d281381b25a843724d57852df0f7f9649fd
|
7
|
+
data.tar.gz: 332efd0ad4edfa7d7c7734686c7b728831e655f0bc75fcb9e5255cf360c23c6f12ec4d70f599bf286e5c1f50d74e2b22567a090cb654d71ed170680cffab9797
|
data/README.md
CHANGED
@@ -1,44 +1,52 @@
|
|
1
|
-
#
|
1
|
+
# WebApi
|
2
2
|
|
3
|
+
* [VERSION 2.0.221220](https://www.github.com/carlosjhr64/web_api)
|
3
4
|
* [github](https://www.github.com/carlosjhr64/web_api)
|
4
5
|
* [rubygems](https://rubygems.org/gems/web_api)
|
5
6
|
|
6
7
|
## DESCRIPTION:
|
7
8
|
|
8
|
-
Ruby library for web
|
9
|
+
Ruby library for web API's.
|
9
10
|
|
10
11
|
## SYNOPSIS:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
12
|
+
```ruby
|
13
|
+
require 'web_api'
|
14
|
+
webapi = WebApi.new "https://api.site.org/path-to-base/",
|
15
|
+
header: {Authorization: "Bearer ABC123XYZ"}
|
16
|
+
# for a post to https://api.site.org/path-to-base/resource...
|
17
|
+
webapi.add(:resource, type: :post)
|
18
|
+
# You can pass the post's (or query's) key value pairs in a hash.
|
19
|
+
body = webapi.resource(data: {key: "value"})
|
20
|
+
```
|
19
21
|
## INSTALL:
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
```console
|
23
|
+
$ gem install web_api
|
24
|
+
```
|
23
25
|
## MORE:
|
24
26
|
|
25
27
|
There's not that much code here...
|
26
|
-
|
28
|
+
Under 200 lines in `lib/**.rb` at the time of this writing.
|
27
29
|
Take a look at the examples given at [github](https://github.com/carlosjhr64/web_api/tree/master/examples)
|
28
30
|
for use cases.
|
29
31
|
|
30
32
|
The model is that at each step...
|
31
33
|
|
32
|
-
1. instantiation of a WebApi object
|
33
|
-
2. addition of a WebApi method
|
34
|
-
3. call to a WebApi method
|
34
|
+
1. instantiation of a `WebApi` object
|
35
|
+
2. addition of a `WebApi` method
|
36
|
+
3. call to a `WebApi` method
|
35
37
|
|
36
|
-
...one builds up the
|
37
|
-
The WebApi methods `#new`, `#add`, and `#<method>`
|
38
|
+
...one builds up the URL, type, data, and header of the HTTP request.
|
39
|
+
The `WebApi` methods `#new`, `#add`, and `#<method>`
|
40
|
+
all have the same argument signature:
|
38
41
|
|
39
|
-
extension String,
|
42
|
+
extension String,
|
43
|
+
type: Symbol,
|
44
|
+
data: Hash,
|
45
|
+
header: Hash,
|
46
|
+
dumper: Proc,
|
47
|
+
Parser: Proc|Hash(String, Proc)
|
40
48
|
|
41
|
-
The extension builds up the url by
|
49
|
+
The extension builds up the url by concatenation.
|
42
50
|
The data and headers hashes are built up with merge.
|
43
51
|
The type, dumper, and parser can be changed at each step.
|
44
52
|
|
@@ -46,28 +54,30 @@ One can read the code to check the minor nuances of each method's signature,
|
|
46
54
|
such as default values.
|
47
55
|
|
48
56
|
Note that `#add` will assume extension is the same as the name of the method if
|
49
|
-
no
|
57
|
+
no extension is given.
|
50
58
|
|
51
|
-
Note that `#<method>` will assume the user meant to pass data if
|
52
|
-
|
59
|
+
Note that `#<method>` will assume the user meant to pass data if
|
60
|
+
it only gets a hash:
|
53
61
|
|
54
|
-
#<method>({"a"=>"ABC","x"=>"XYZ"})
|
62
|
+
#<method>({"a"=>"ABC","x"=>"XYZ"})
|
63
|
+
#=> #<method>('', data: {"a"=>"ABC","x"=>"XYZ"})
|
55
64
|
|
56
|
-
The dumper to dump the data in a post request is JSON.dump by default
|
65
|
+
The dumper to dump the data in a post request is `JSON.dump` by default
|
66
|
+
if `JSON` is available.
|
57
67
|
|
58
|
-
The parser to parse the body of an
|
59
|
-
|
68
|
+
The parser to parse the body of an `application/json` type content is
|
69
|
+
`JSON.parse` by default if available.
|
60
70
|
|
61
|
-
If one does not want to parse the
|
71
|
+
If one does not want to parse the response's body,
|
62
72
|
one can set `parser: :none`. For example:
|
63
|
-
|
64
|
-
|
65
|
-
|
73
|
+
```ruby
|
74
|
+
body = webapi.resourse(data: {key: "value"}, parser: :none)
|
75
|
+
```
|
66
76
|
## LICENSE:
|
67
77
|
|
68
78
|
(The MIT License)
|
69
79
|
|
70
|
-
Copyright (c)
|
80
|
+
Copyright (c) 2022 CarlosJHR64
|
71
81
|
|
72
82
|
Permission is hereby granted, free of charge, to any person obtaining
|
73
83
|
a copy of this software and associated documentation files (the
|
data/lib/web_api/web_api.rb
CHANGED
@@ -1,58 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
class WebApi
|
2
|
+
def WebApi.get_dumper
|
3
|
+
(defined? JSON)? JSON.method(:dump) : :none
|
4
|
+
end
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def WebApi.get_parsers
|
7
|
+
parsers = Hash.new :none
|
8
|
+
parsers['application/json'] = JSON.method(:parse) if defined? JSON
|
9
|
+
parsers['text/csv'] = CSV.method(:parse) if defined? CSV
|
10
|
+
parsers['text/html'] = Nokogiri::HTML.method(:parse) if defined? Nokogiri
|
11
|
+
return parsers
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
def initialize(base = '',
|
15
|
+
type: :get,
|
16
|
+
data: {},
|
17
|
+
header: {},
|
18
|
+
dumper: WebApi.get_dumper,
|
19
|
+
parser: WebApi.get_parsers,
|
20
|
+
&block)
|
21
|
+
@base, @type, @data, @header, @dumper, @parser, @block =
|
22
|
+
base, type, data, header, dumper, parser, block
|
23
|
+
@strict = false
|
24
|
+
@webmethods = {}
|
25
|
+
end
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
27
|
+
def strict!(t = true)
|
28
|
+
@strict = t
|
29
|
+
end
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
def add(method, target = method.to_s,
|
32
|
+
type: @type,
|
33
|
+
data: {},
|
34
|
+
header: {},
|
35
|
+
dumper: @dumper,
|
36
|
+
parser: @parser,
|
37
|
+
&block)
|
38
|
+
@webmethods[method] = WebApiMethod.new(@base+target,
|
39
|
+
type,
|
40
|
+
@data.merge(data),
|
41
|
+
@header.merge(header),
|
42
|
+
dumper,
|
43
|
+
parser,
|
44
|
+
&(block || @block))
|
45
|
+
end
|
42
46
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
extension, data = '', extension unless extension.is_a? String # user passed data as first argument
|
55
|
-
@webmethods[symbol].run(extension, type, data, header, dumper, parser, &block)
|
47
|
+
def method_missing(symbol , extension = '',
|
48
|
+
type: nil,
|
49
|
+
data: {},
|
50
|
+
header: {},
|
51
|
+
dumper: nil,
|
52
|
+
parser: nil,
|
53
|
+
&block)
|
54
|
+
unless @webmethods.has_key? symbol
|
55
|
+
super if @strict
|
56
|
+
add symbol
|
56
57
|
end
|
58
|
+
# user passed data as first argument?
|
59
|
+
extension, data = '', extension unless extension.is_a? String
|
60
|
+
@webmethods[symbol].run(extension, type, data, header, dumper, parser,
|
61
|
+
&block)
|
57
62
|
end
|
58
63
|
end
|
@@ -1,99 +1,103 @@
|
|
1
|
-
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
end
|
1
|
+
class WebApiMethod
|
2
|
+
class ResponseError < ::RuntimeError
|
3
|
+
end
|
4
|
+
class UnsupportedMethodError < ::RuntimeError
|
5
|
+
end
|
7
6
|
|
8
|
-
|
7
|
+
OK = 200..299
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
# Escapes value's string representation for query string use.
|
10
|
+
def escape(s)
|
11
|
+
# Contraction of ERB#url_encode method
|
12
|
+
s.to_s.b.gsub(/[^\w\-.~]/n){sprintf("%%%02X",_1.unpack1("C"))}
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
.join('&')
|
25
|
-
else
|
26
|
-
ah.to_s
|
27
|
-
end
|
15
|
+
def query_string(ah)
|
16
|
+
case ah
|
17
|
+
when Array
|
18
|
+
ah.select{!_1.empty?}.map{query_string _1}.join('&')
|
19
|
+
when Hash
|
20
|
+
ah.map{"#{_1}=#{escape _2}"}.join('&')
|
21
|
+
else
|
22
|
+
ah.to_s
|
28
23
|
end
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
26
|
+
def initialize(target, type, data, header, dumper, parser, &block)
|
27
|
+
@target, @type, @data, @header, @dumper, @parser, @block =
|
28
|
+
target, type, data, header, dumper, parser, block
|
29
|
+
end
|
34
30
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
31
|
+
# uri_parse(request: CRStruct) -> N/A
|
32
|
+
# Expects request to have url, data, type, and dumper.
|
33
|
+
# Sets the request's scheme, host, port, uri, and payload
|
34
|
+
def uri_parse(request)
|
35
|
+
uri = URI.parse(request.url)
|
36
|
+
request_uri = uri.request_uri
|
37
|
+
payload = ''
|
38
|
+
unless request.data.empty?
|
39
|
+
if request.type == :post
|
40
|
+
if dumper=request.dumper and (dumper!=:none)
|
41
|
+
payload = dumper.call(request.data)
|
46
42
|
else
|
47
43
|
payload = query_string(request.data)
|
48
|
-
request_uri += (uri.query ? '&' : '?') + payload
|
49
44
|
end
|
45
|
+
else
|
46
|
+
payload = query_string(request.data)
|
47
|
+
request_uri += (uri.query ? '&' : '?') + payload
|
50
48
|
end
|
51
|
-
request.scheme, request.host, request.port, request.uri, request.payload =
|
52
|
-
uri.scheme, uri.host, uri.port, request_uri, payload
|
53
49
|
end
|
50
|
+
request.scheme, request.host, request.port, request.uri, request.payload =
|
51
|
+
uri.scheme, uri.host, uri.port, request_uri, payload
|
52
|
+
end
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
54
|
+
def run(extension, type, data, header, dumper, parser, &block)
|
55
|
+
request = CRStruct::Open.new
|
56
|
+
request.url = @target+extension
|
57
|
+
request.type = type || @type
|
58
|
+
request.data = @data.merge(data)
|
59
|
+
request.header = @header.merge(header)
|
60
|
+
request.dumper = dumper || @dumper
|
62
61
|
|
63
|
-
|
64
|
-
|
62
|
+
parser ||= @parser
|
63
|
+
block ||= @block
|
65
64
|
|
66
|
-
|
67
|
-
|
65
|
+
uri_parse(request)
|
66
|
+
block.call(request) if block
|
68
67
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
body, content = http_response_body(request)
|
69
|
+
parser = parser[content] if parser.is_a? Hash
|
70
|
+
body = parser.call(body) if parser and parser!=:none
|
71
|
+
return body
|
72
|
+
end
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
74
|
+
def http_response_body(request)
|
75
|
+
response = http_response(request)
|
76
|
+
unless OK === response.code.to_i
|
77
|
+
$stderr.puts response.code
|
78
|
+
$stderr.puts response.body
|
79
|
+
raise ResponseError, response.message
|
79
80
|
end
|
81
|
+
return response.body, response['content-type'].sub(/;.*$/,'')
|
82
|
+
end
|
80
83
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
84
|
+
def http_response(request)
|
85
|
+
http = net_http(request)
|
86
|
+
case request.type
|
87
|
+
when :get, :delete, :head, :copy, :move, :options, :trace
|
88
|
+
http.method(request.type).call request.uri, request.header
|
89
|
+
when :post, :patch, :lock, :unlock, :mkcol, :propfind, :proppatch
|
90
|
+
http.method(request.type)
|
91
|
+
.call request.uri, request.payload, request.header
|
92
|
+
else
|
93
|
+
raise UnsupportedMethodError,
|
94
|
+
"Method type #{type}(#{type.class}) not supported by WebApi."
|
91
95
|
end
|
96
|
+
end
|
92
97
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
+
def net_http(request)
|
99
|
+
http = Net::HTTP.new(request.host, request.port)
|
100
|
+
http.use_ssl = request.scheme=='https'
|
101
|
+
return http
|
98
102
|
end
|
99
103
|
end
|
data/lib/web_api.rb
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
# Standard Libraries
|
2
2
|
require 'net/http'
|
3
|
-
require 'cgi'
|
4
|
-
|
5
3
|
# External Gems
|
6
4
|
require 'crstruct'
|
7
|
-
|
8
5
|
# This Gem
|
9
|
-
|
10
|
-
VERSION = '0.
|
11
|
-
|
12
|
-
|
6
|
+
class WebApi
|
7
|
+
VERSION = '2.0.221220'
|
8
|
+
require_relative 'web_api/web_api_method.rb'
|
9
|
+
require_relative 'web_api/web_api.rb'
|
13
10
|
end
|
14
|
-
|
15
11
|
# Requires:
|
16
12
|
#`ruby`
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.221220
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- CarlosJHR64
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: crstruct
|
@@ -16,15 +16,21 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '1.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.221218
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
|
29
|
+
version: '1.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.221218
|
33
|
+
description: 'Ruby library for web API''s.
|
28
34
|
|
29
35
|
'
|
30
36
|
email: carlosjhr64@gmail.com
|
@@ -55,9 +61,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
61
|
- !ruby/object:Gem::Version
|
56
62
|
version: '0'
|
57
63
|
requirements:
|
58
|
-
- 'ruby: ruby
|
59
|
-
rubygems_version: 3.
|
64
|
+
- 'ruby: ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [aarch64-linux]'
|
65
|
+
rubygems_version: 3.3.7
|
60
66
|
signing_key:
|
61
67
|
specification_version: 4
|
62
|
-
summary: Ruby library for web
|
68
|
+
summary: Ruby library for web API's.
|
63
69
|
test_files: []
|