req_wrap 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2c16aacc0cd7adc9fec16b8e873d7110100e24b3272da1646aab602d2980f08b
4
+ data.tar.gz: 4a2483c368629ec17bcda1d659359c343b7f8b4a417ed46e11015b45b0b4813b
5
+ SHA512:
6
+ metadata.gz: 83d5b9bc43d7f2e1ae19ed3a569eef39ea5d0a0ee8765e51f4cf8eecb33ab8b7e0dc89fb3094b3d3a017320a303f5400569b7705f5961d71446ef48f1a53cf1e
7
+ data.tar.gz: 3d01b7721624c66c4f3cf6cb0cdb116a45968bcd5429dda41df3ad5c7b46d6158644b0a01ea390953ff87c6f6280feae2dd415d7fd3a5596f39d107dc0883cff
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.0
3
+
4
+ Style/StringLiterals:
5
+ EnforcedStyle: single_quotes
6
+
7
+ Style/StringLiteralsInInterpolation:
8
+ EnforcedStyle: double_quotes
9
+
10
+ Style/Documentation:
11
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2025-06-10
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 vxd7
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # ReqWrap
2
+
3
+ Plain Ruby API client for testing and prototyping with simple environment
4
+ management. Supports encrypted environment definitions. Features optional
5
+ commandline interface and code generation.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace
10
+ `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your
11
+ gem name right after releasing it to RubyGems.org. Please do not do it earlier
12
+ due to security reasons. Alternatively, replace this section with instructions
13
+ to install your gem from git if you don't plan to release to RubyGems.org.
14
+
15
+ Install the gem and add to the application's Gemfile by executing:
16
+
17
+ ```bash
18
+ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
19
+ ```
20
+
21
+ If bundler is not being used to manage dependencies, install the gem by executing:
22
+
23
+ ```bash
24
+ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ Simply subclass `ReqWrap::Req` to use the `HTTP` capabilities of the gem.
30
+
31
+ ### Generate new request template
32
+
33
+ Simply execute after installing the gem: `req_wrap g my_request`
34
+
35
+ This will generate the `my_request.rb` file in the current folder with the
36
+ following request template:
37
+
38
+ ```ruby
39
+ # frozen_string_literal: true
40
+
41
+ require 'req_wrap'
42
+
43
+ class MyRequest < ReqWrap::Req
44
+ def call
45
+ http.get('https://httpbin.org/ip')
46
+ end
47
+ end
48
+
49
+ if __FILE__ == $PROGRAM_NAME
50
+ my_request = MyRequest.new(logger: nil)
51
+
52
+ my_request.load_env
53
+ puts my_request.call
54
+ end
55
+ ```
56
+
57
+ Simply change the definition of the `#call` method and the request can be
58
+ executed like any `Ruby` file: `ruby my_request.rb` which will make the actual
59
+ request and print the results.
60
+
61
+ The gem provides several quality of life methods which can be used to simplify
62
+ working with requests and responses. Some of these are:
63
+
64
+ - `#load_env` -- load the request environment
65
+ - `#response` -- reference to the latest `HTTP` response
66
+ - `#executed_request` -- reference to the latest executed `HTTP` request
67
+ - `#responses` -- `Ruby` array with the list of all `HTTP` responses
68
+ - `#save_response` -- save given (or last by default) response to current directory
69
+
70
+ Additionally, see the `ReqWrap::Req` file definition.
71
+
72
+ ## Development
73
+
74
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
75
+ `rake test` to run the tests. You can also run `bin/console` for an interactive
76
+ prompt that will allow you to experiment.
77
+
78
+ To install this gem onto your local machine, run `bundle exec rake install`. To
79
+ release a new version, update the version number in `version.rb`, and then run
80
+ `bundle exec rake release`, which will create a git tag for the version, push
81
+ git commits and the created tag, and push the `.gem` file to
82
+ [rubygems.org](https://rubygems.org).
83
+
84
+ ## Contributing
85
+
86
+ Bug reports and pull requests are welcome on GitHub at https://github.com/vxd7/req_wrap
87
+
88
+ ## License
89
+
90
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "minitest/test_task"
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
data/exe/req_wrap ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'req_wrap/cli'
4
+
5
+ ReqWrap::Cli.new.call(ARGV)
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ require 'req_wrap/environment'
6
+
7
+ module ReqWrap
8
+ class Cli
9
+ class Environment
10
+ DEFAULT_EDITOR = 'vi'
11
+
12
+ def initialize
13
+ @options = {
14
+ delete_original: false
15
+ }
16
+ end
17
+
18
+ def call(args) # rubocop:disable Metrics/MethodLength
19
+ parser = OptionParser.new(banner) do |p|
20
+ add_gen_pass_option(p)
21
+ add_enc_option(p)
22
+ add_change_option(p)
23
+ add_delete_original_option(p)
24
+ add_decrypt_option(p)
25
+
26
+ p.separator('')
27
+ p.separator(examples)
28
+ end
29
+
30
+ return parser.parse!(args) unless args.empty?
31
+
32
+ puts parser
33
+ exit(1)
34
+ end
35
+
36
+ private
37
+
38
+ def banner
39
+ <<~BANNER
40
+ Usage: req_wrap e [options...]
41
+
42
+ Manage environment files used by request scripts
43
+ BANNER
44
+ end
45
+
46
+ def examples
47
+ <<~EXAMPLES
48
+ Examples of invocation:
49
+ - req_wrap e --gen-pass # Generate encryption password
50
+ - req_wrap e --enc env_file.env # Encrypt environment file env_file.env using generated password
51
+ - E=env_file.env req_wrap e --enc # Encrypt environment file env_file.env using generated password
52
+ - EDITOR=vim req_wrap e --edit env_file.enc # Decrypt environment file, open editor and re-encrypt
53
+ EXAMPLES
54
+ end
55
+
56
+ def add_gen_pass_option(parser)
57
+ parser.on('--gen-pass', "Generate password file ('#{ReqWrap::Environment::PASSWORD_FILE}')") do
58
+ ReqWrap::Environment.generate_password_file
59
+ end
60
+ end
61
+
62
+ def add_enc_option(parser)
63
+ desc = 'Encrypt environment file and write the result to env_file.enc file'
64
+
65
+ parser.on('--enc [env_file]', desc) do |env_file|
66
+ ReqWrap::Environment.new(env_file).encrypt(
67
+ delete_original: @options[:delete_original]
68
+ )
69
+ end
70
+ end
71
+
72
+ def add_change_option(parser)
73
+ desc = 'Edit encrypted environment using supplied text editor'
74
+
75
+ parser.on('--change [enc_file]', desc) do |env_file|
76
+ ReqWrap::Environment.new(env_file).change(ENV.fetch('EDITOR', DEFAULT_EDITOR))
77
+ end
78
+ end
79
+
80
+ def add_delete_original_option(parser)
81
+ desc = 'Delete original environment file after encryption'
82
+
83
+ parser.on('--delete-original', desc) do
84
+ @options[:delete_original] = true
85
+ end
86
+ end
87
+
88
+ def add_decrypt_option(parser)
89
+ parser.on('--decrypt [env_file]', 'Decrypt env file and print it to stdout') do |env_file|
90
+ puts ReqWrap::Environment.new(env_file).read
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ require 'req_wrap/generator/req'
6
+
7
+ module ReqWrap
8
+ class Cli
9
+ class Generate
10
+ def initialize
11
+ @options = {}
12
+ end
13
+
14
+ def call(args)
15
+ parser = OptionParser.new(banner) do |p|
16
+ add_desc_option(p)
17
+
18
+ p.separator('')
19
+ p.separator(examples)
20
+ end
21
+
22
+ parser.parse!(args)
23
+ return generate_request!(args) unless args.empty?
24
+
25
+ puts parser
26
+ exit(1)
27
+ end
28
+
29
+ private
30
+
31
+ def generate_request!(args)
32
+ request_file = args.shift.strip
33
+ raise ArgumentError, 'request_file argument cannot be empty' if request_file.empty?
34
+
35
+ Generator::Req.new(request_file, @options).call
36
+ end
37
+
38
+ def banner
39
+ <<~BANNER
40
+ Usage: req_wrap g [options...] <request_file>
41
+
42
+ <request_file> can be either absolute path to filename or relative path.
43
+ Ruby extension (.rb) is optional.
44
+
45
+ BANNER
46
+ end
47
+
48
+ def examples
49
+ <<~EXAMPLES
50
+ Examples of invocation:
51
+ - req_wrap g sample_req # Create './sample_req.rb' request file
52
+ - req_wrap g sample_req.rb # Create './sample_req.rb' request file
53
+ - req_wrap g requests/sample_req.rb # Create './requests/sample_req.rb' request file
54
+ EXAMPLES
55
+ end
56
+
57
+ def add_desc_option(parser)
58
+ option_desc = 'Add optional description to the generated request definition'
59
+
60
+ parser.on('-d', '--desc [description]', option_desc) do |request_description|
61
+ @options[:request_description] = request_description.strip
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'optparse'
4
+
5
+ require 'req_wrap/cli/environment'
6
+ require 'req_wrap/cli/generate'
7
+
8
+ module ReqWrap
9
+ class Cli
10
+ COMMAND_ALIASES = {
11
+ 'generate' => %w[g gen],
12
+ 'environment' => %w[e env]
13
+ }.freeze
14
+
15
+ def call(args)
16
+ arguments = args.dup
17
+ user_command = arguments.shift
18
+
19
+ command = find_command(user_command)
20
+ return send(command, arguments) if command
21
+
22
+ puts common_options
23
+ exit(1)
24
+ end
25
+
26
+ private
27
+
28
+ def common_options
29
+ OptionParser.new do |parser|
30
+ parser.on('-h', '--help', 'Show this help message') do
31
+ puts parser
32
+ exit
33
+ end
34
+
35
+ parser.separator('')
36
+ parser.separator(commands_help)
37
+ parser.separator('')
38
+ parser.separator(usage_help)
39
+ end
40
+ end
41
+
42
+ def commands_help
43
+ commands = COMMAND_ALIASES.map do |command, aliases|
44
+ aliases_str = aliases.map { |name| "'#{name}'" }.join(', ')
45
+
46
+ "- '#{command}' (also aliased as #{aliases_str})"
47
+ end
48
+
49
+ "Available commands:\n#{commands.join("\n")}"
50
+ end
51
+
52
+ def usage_help
53
+ commands = COMMAND_ALIASES.keys.map do |key|
54
+ "- req_wrap #{key} --help"
55
+ end
56
+
57
+ "Examples of usage:\n#{commands.join("\n")}"
58
+ end
59
+
60
+ def environment(args)
61
+ ReqWrap::Cli::Environment.new.call(args)
62
+ end
63
+
64
+ def generate(args)
65
+ ReqWrap::Cli::Generate.new.call(args)
66
+ end
67
+
68
+ def find_command(user_command)
69
+ COMMAND_ALIASES.detect do |command_name, command_aliases|
70
+ user_command == command_name || command_aliases.include?(user_command)
71
+ end&.first
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dotenv'
4
+ require 'tempfile'
5
+
6
+ require 'active_support'
7
+ require 'active_support/encrypted_file'
8
+
9
+ module ReqWrap
10
+ # Request environment
11
+ #
12
+ class Environment
13
+ PASSWORD_FILE = '.reqwrap_password'
14
+ ENCRYPTED_ENV_FILE_EXT = '.enc'
15
+
16
+ def self.generate_password_file
17
+ path = File.expand_path("./#{PASSWORD_FILE}")
18
+ raise ArgumentError, 'Password file already exists' if File.exist?(path)
19
+
20
+ File.write(path, ActiveSupport::EncryptedFile.generate_key)
21
+ path
22
+ end
23
+
24
+ def initialize(env_file = nil)
25
+ @env_file = env_file || default_env_file
26
+ end
27
+
28
+ def encrypted?
29
+ @env_file.end_with?(ENCRYPTED_ENV_FILE_EXT)
30
+ end
31
+
32
+ def load
33
+ return unless validate
34
+
35
+ load_str_environment(read)
36
+ end
37
+
38
+ def read
39
+ return decrypt if encrypted?
40
+
41
+ File.read(@env_file, mode: 'rb:BOM|utf-8')
42
+ end
43
+
44
+ def write(content)
45
+ return encrypted_file_for(@env_file).write(content) if encrypted?
46
+
47
+ File.write(@env_file, content)
48
+ end
49
+
50
+ def delete
51
+ File.delete(@env_file) if File.exist?(@env_file)
52
+ end
53
+
54
+ def encrypt(delete_original: false)
55
+ validate(raise_error: true)
56
+
57
+ Environment.new("#{@env_file}#{ENCRYPTED_ENV_FILE_EXT}").write(read)
58
+ delete if delete_original
59
+ end
60
+
61
+ def change(editor)
62
+ return change_encrypted_environment(editor) if encrypted?
63
+
64
+ Tempfile.create(['', "-#{@env_file}"]) do |tmp_file|
65
+ original_content = read
66
+ tmp_file.write(original_content)
67
+ tmp_file.flush
68
+
69
+ launch_external_editor(editor, tmp_file.path)
70
+
71
+ tmp_file.rewind
72
+ new_content = tmp_file.read
73
+ write(new_content) if original_content != new_content
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def change_encrypted_environment(editor)
80
+ encrypted_file_for(@env_file).change do |decrypted_file_path|
81
+ launch_external_editor(editor, decrypted_file_path)
82
+ end
83
+ end
84
+
85
+ def decrypt
86
+ validate(raise_error: true)
87
+ encrypted_file_for(@env_file).read
88
+ end
89
+
90
+ # Default env file is given by 'E' environment variable
91
+ # and will be used by different scripts and classes of this gem;
92
+ #
93
+ def default_env_file
94
+ ENV['E']
95
+ end
96
+
97
+ # Update current environment from supplied
98
+ # unparsed str
99
+ #
100
+ def load_str_environment(environment_str)
101
+ Dotenv.update(Dotenv::Parser.new(environment_str).call)
102
+ end
103
+
104
+ def encrypted_file_for(content_path)
105
+ ActiveSupport::EncryptedFile.new(
106
+ content_path: content_path,
107
+ key_path: PASSWORD_FILE,
108
+ env_key: 'REQWRAP_PASSWORD',
109
+ raise_if_missing_key: true
110
+ )
111
+ end
112
+
113
+ def validate(raise_error: false)
114
+ unless @env_file
115
+ return false unless raise_error
116
+
117
+ raise ArgumentError, 'Env file not supplied'
118
+ end
119
+
120
+ unless File.exist?(@env_file)
121
+ return false unless raise_error
122
+
123
+ raise ArgumentError, 'Env file does not exist'
124
+ end
125
+
126
+ true
127
+ end
128
+
129
+ def launch_external_editor(editor, file_path)
130
+ system(editor, file_path.to_s, exception: true)
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'req_wrap'
4
+
5
+ <% if request_description -%>
6
+ <%= request_description %>
7
+ <% end -%>
8
+ class <%= request_class_name %> < ReqWrap::Req
9
+ def call
10
+ http.get('https://httpbin.org/ip')
11
+ end
12
+ end
13
+
14
+ if __FILE__ == $PROGRAM_NAME
15
+ <%= request_name %> = <%= request_class_name %>.new(logger: nil)
16
+
17
+ <%= request_name %>.load_env
18
+ puts <%= request_name %>.call
19
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ require 'active_support'
6
+ require 'active_support/inflector/methods'
7
+ require 'req_wrap/generator/string_wrapper'
8
+
9
+ module ReqWrap
10
+ module Generator
11
+ class Req
12
+ TEMPLATE = "#{File.dirname(__FILE__)}/req.erb".freeze
13
+ RUBY_EXT = '.rb'
14
+
15
+ def initialize(request_file, options = {})
16
+ @request_file = ensure_extension(request_file, RUBY_EXT)
17
+ @request_name = File.basename(@request_file, RUBY_EXT)
18
+
19
+ @options = options
20
+ end
21
+
22
+ def call
23
+ File.write(
24
+ @request_file,
25
+ template.result_with_hash(template_options)
26
+ )
27
+ end
28
+
29
+ private
30
+
31
+ def template_options
32
+ @template_options ||= {
33
+ request_class_name: ActiveSupport::Inflector.camelize(@request_name),
34
+ request_name: @request_name,
35
+ request_description: prepare_request_description
36
+ }
37
+ end
38
+
39
+ def ensure_extension(file_name, extension)
40
+ return file_name if file_name.end_with?(extension)
41
+
42
+ "#{file_name}#{extension}"
43
+ end
44
+
45
+ def template
46
+ @template ||= ERB.new(File.read(TEMPLATE), trim_mode: '-').tap do |erb|
47
+ erb.location = [TEMPLATE, 0]
48
+ end
49
+ end
50
+
51
+ def prepare_request_description
52
+ request_description = @options[:request_description]
53
+ return unless request_description
54
+ return if request_description.empty?
55
+
56
+ lines = StringWrapper.wrap_string(request_description, to: 79)
57
+ lines << ''
58
+ lines.map { |line| "# #{line}" }.join("\n")
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReqWrap
4
+ module Generator
5
+ module StringWrapper
6
+ def self.wrap_string(str, to:)
7
+ wrap_words(str.split(' '), [], to).map { |words| words.join(' ') }
8
+ end
9
+
10
+ def self.wrap_words(words, result, to)
11
+ # Partitioning is finished if there is nothing more to
12
+ # partition;
13
+ #
14
+ return result if words.empty?
15
+
16
+ current_size = 0
17
+ line, rest = words.partition do |word|
18
+ current_size += word.size + 1
19
+ current_size - 1 <= to
20
+ end
21
+
22
+ # Use the next word if wrapping cannot be performed;
23
+ #
24
+ # This means that the word length is larger than the 'to'
25
+ # argument
26
+ #
27
+ line << rest.shift if line.empty?
28
+
29
+ result << line
30
+
31
+ # Continue partitioning the rest of words
32
+ #
33
+ wrap_words(rest, result, to)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'http'
4
+
5
+ module ReqWrap
6
+ module HttpFeatures
7
+ class ResponseStore < ::HTTP::Feature
8
+ def initialize(store:)
9
+ super()
10
+
11
+ raise ArgumentError, 'Provide data structure to store responses' unless store
12
+
13
+ @store = store
14
+ end
15
+
16
+ def wrap_response(response)
17
+ @store.append(response)
18
+
19
+ response
20
+ end
21
+
22
+ ::HTTP::Options.register_feature(:response_store, self)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+ require 'http'
5
+
6
+ require 'active_support'
7
+ require 'active_support/inflector/methods'
8
+
9
+ require 'req_wrap/environment'
10
+ require 'req_wrap/http_features/response_store'
11
+
12
+ module ReqWrap
13
+ DEFAULT_LOGGER = Logger.new($stdout)
14
+
15
+ class Req
16
+ attr_reader :responses
17
+
18
+ def initialize(timeout: 10, logger: DEFAULT_LOGGER, response_store: [])
19
+ @timeout = timeout
20
+ @logger = logger
21
+ @responses = response_store
22
+ end
23
+
24
+ def load_env
25
+ Environment.new.load
26
+ end
27
+
28
+ def save_response(response_to_save = response, name: nil)
29
+ req_class = ActiveSupport::Inflector.underscore(
30
+ ActiveSupport::Inflector.demodulize(self.class.name)
31
+ )
32
+
33
+ time = Time.now.utc.iso8601(4)
34
+ filename = [req_class, time, name, 'response.txt'].join('_')
35
+
36
+ File.write(filename, response_to_save)
37
+
38
+ filename
39
+ end
40
+
41
+ def response
42
+ @responses.last
43
+ end
44
+
45
+ def executed_request
46
+ response&.request
47
+ end
48
+
49
+ def to_s
50
+ response.is_a?(HTTP::Response) ? response.parse : response
51
+ end
52
+
53
+ private
54
+
55
+ def e(name)
56
+ ENV.fetch(name.to_s.upcase)
57
+ end
58
+
59
+ def without_ssl(client)
60
+ ctx = OpenSSL::SSL::SSLContext.new
61
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
62
+
63
+ client.default_options = client.default_options.with_ssl_context(ctx)
64
+ client
65
+ end
66
+
67
+ def http_json
68
+ http.headers(content_type: 'application/json')
69
+ end
70
+
71
+ def http
72
+ client = HTTP.timeout(@timeout).use(:auto_inflate)
73
+ client = client.use(logging: { logger: @logger }) if @logger
74
+ client = client.use(response_store: { store: @responses }) if @responses
75
+
76
+ client
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ReqWrap
4
+ VERSION = '0.1.0'
5
+ end
data/lib/req_wrap.rb ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'req_wrap/version'
4
+ require 'req_wrap/req'
5
+
6
+ module ReqWrap
7
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: req_wrap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - vxd7
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 7.1.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 7.1.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: dotenv
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 5.3.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 5.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.5.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.5.0
69
+ description: |
70
+ Plain Ruby API client for testing and prototyping with simple environment management.
71
+ Supports encrypted environment definitions. Features optional commandline interface and
72
+ code generation.
73
+ email:
74
+ - vxd732@protonmail.com
75
+ executables:
76
+ - req_wrap
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - ".rubocop.yml"
81
+ - CHANGELOG.md
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - exe/req_wrap
86
+ - lib/req_wrap.rb
87
+ - lib/req_wrap/cli.rb
88
+ - lib/req_wrap/cli/environment.rb
89
+ - lib/req_wrap/cli/generate.rb
90
+ - lib/req_wrap/environment.rb
91
+ - lib/req_wrap/generator/req.erb
92
+ - lib/req_wrap/generator/req.rb
93
+ - lib/req_wrap/generator/string_wrapper.rb
94
+ - lib/req_wrap/http_features/response_store.rb
95
+ - lib/req_wrap/req.rb
96
+ - lib/req_wrap/version.rb
97
+ homepage: https://github.com/vxd7/req_wrap
98
+ licenses:
99
+ - MIT
100
+ metadata:
101
+ homepage_uri: https://github.com/vxd7/req_wrap
102
+ source_code_uri: https://github.com/vxd7/req_wrap
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: 3.0.0
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubygems_version: 3.2.3
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: Simple API client with environment management
122
+ test_files: []