api_frame 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a8b59e5031b5fee64016e8be08239134686ba0532ea71cdbf8adbd263037b337
4
+ data.tar.gz: 210dbc213dfa4e0db91a7dd29c1364233a46a4ab00fd854a75c205d7b83003bb
5
+ SHA512:
6
+ metadata.gz: c599a3bc24d8042a985414f555c072887f58904ed4e67cfa3576c2897a9a2bd9fa602642c8de555afdcb8b65964e660420b88dde25699baa110e8a4d4ad5ec77
7
+ data.tar.gz: 380fdb32def48ba199a51cfd5af5ac85eca39cb05d77f75d65714654a7871d18473f4c6e2f2f384e37c11902301e04450225c0c1d07f20ce3a0659d629121b85
data/README.adoc ADDED
@@ -0,0 +1,13 @@
1
+ == ApiFrame
2
+
3
+ ApiFrame is a gem that aims to provide an easy-to-use way of implementing high-level and low-level interactions with APIs working over HTTP.
4
+
5
+ === Installation
6
+
7
+ Add the gem `api_frame` as a runtime dependency to your library’s `gemspec`.
8
+
9
+ === Development
10
+
11
+ After checking out the repository, run `bin/setup` to install dependencies.
12
+ For an interactive Pry session, run `bin/console`.
13
+ Run `rake spec` to run the tests.
@@ -0,0 +1,73 @@
1
+ require 'cgi'
2
+ require 'json'
3
+ require 'net/https'
4
+
5
+ require_relative 'no_success_error'
6
+ require_relative 'utils'
7
+
8
+ module ApiFrame
9
+ module EndpointMethods
10
+ def base_uri
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def default_headers
15
+ {}
16
+ end
17
+
18
+ def default_content_type
19
+ 'application/json'
20
+ end
21
+
22
+ def default_response_parser
23
+ proc do |response|
24
+ JSON.parse(response.body)
25
+ end
26
+ end
27
+
28
+ def perform_request(method, api_path, query: nil, body: nil, headers: nil)
29
+ uri = self.base_uri + api_path
30
+ uri.query = URI.encode_www_form(query) if query
31
+
32
+ Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
33
+ ApiFrame::Utils.request_type_from_method_argument(method).new(uri).tap do |request|
34
+ default_headers.merge(headers || {}).each do |name, value|
35
+ request[name] = value
36
+ end
37
+
38
+ if body
39
+ request['Content-Type'] = default_content_type
40
+ request.body = body
41
+ end
42
+ end.then do |request|
43
+ http.request(request)
44
+ end
45
+ end
46
+ end
47
+
48
+ def self.included(klass)
49
+ klass.extend(ClassMethods)
50
+ end
51
+
52
+ module ClassMethods
53
+ def define_endpoint(name, method:, endpoint:, body: nil)
54
+ define_method(name) do |*args, **kwargs|
55
+ uri = endpoint.respond_to?(:call) ? ApiFrame::Utils.call_proc_without_unknown_keywords(endpoint, *args, **kwargs) : endpoint
56
+ request_body = body .respond_to?(:call) ? ApiFrame::Utils.call_proc_without_unknown_keywords(body, *args, **kwargs) : body
57
+
58
+ perform_request(method, uri, body: request_body, query: kwargs.key?(:query) ? kwargs.fetch(:query) : nil, headers: kwargs.key?(:headers) ? kwargs.fetch(:headers) : nil).then do |response|
59
+ if !kwargs.key?(:plain_response) || !kwargs.fetch(:plain_response)
60
+ if response.is_a?(Net::HTTPSuccess)
61
+ default_response_parser.call(response)
62
+ else
63
+ raise ApiFrame::NoSuccessError, response
64
+ end
65
+ else
66
+ response
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,11 @@
1
+ module ApiFrame
2
+ class NoSuccessError < StandardError
3
+ attr_reader :response
4
+
5
+ def initialize(response)
6
+ super
7
+
8
+ @response = response
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ module ApiFrame
2
+ module Utils
3
+ def self.url_escape(string)
4
+ if !string.nil?
5
+ CGI.escape(string.to_s)
6
+ else
7
+ raise TypeError, 'cannot escape nil'
8
+ end
9
+ end
10
+
11
+ def self.call_proc_without_unknown_keywords(proc, *args, **kwargs, &block)
12
+ params = proc.parameters.group_by(&:first).transform_values! do |m|
13
+ m.map do |s|
14
+ s[1]
15
+ end
16
+ end
17
+
18
+ proc_keys =
19
+ if params.key?(:keyrest)
20
+ kwargs
21
+ else
22
+ kwargs.slice(*params.values_at(:key, :keyreq).compact.flatten)
23
+ end
24
+
25
+ proc.call(*args, **proc_keys, &block)
26
+ end
27
+
28
+ def self.request_type_from_method_argument(method)
29
+ if method.instance_of?(Class) && method.ancestors.include?(Net::HTTPRequest)
30
+ method
31
+ else
32
+ {
33
+ get: Net::HTTP::Get,
34
+ post: Net::HTTP::Post,
35
+ }.fetch(method)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module ApiFrame
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/lib/api_frame.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative 'api_frame/endpoint_methods'
2
+ require_relative 'api_frame/version'
3
+
4
+ module ApiFrame
5
+
6
+ end
metadata ADDED
@@ -0,0 +1,50 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: api_frame
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - expeehaa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - expeehaa@outlook.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - README.adoc
21
+ - lib/api_frame.rb
22
+ - lib/api_frame/endpoint_methods.rb
23
+ - lib/api_frame/no_success_error.rb
24
+ - lib/api_frame/utils.rb
25
+ - lib/api_frame/version.rb
26
+ homepage: https://github.com/expeehaa/api_frame
27
+ licenses: []
28
+ metadata:
29
+ allowed_push_host: https://rubygems.org
30
+ rubygems_mfa_required: 'true'
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: 2.6.0
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ requirements: []
46
+ rubygems_version: 3.4.1
47
+ signing_key:
48
+ specification_version: 4
49
+ summary: Small framework to define API clients in Ruby
50
+ test_files: []