Class: Apipie::Extractor::Recorder
- Inherits:
-
Object
- Object
- Apipie::Extractor::Recorder
- Defined in:
- lib/apipie/extractor/recorder.rb
Defined Under Namespace
Modules: FunctionalTestRecording Classes: Middleware
Constant Summary collapse
- MULTIPART_BOUNDARY =
'APIPIE_RECORDER_EXAMPLE_BOUNDARY'.freeze
Instance Method Summary collapse
- #analyse_controller(controller) ⇒ Object
- #analyse_env(env) ⇒ Object
- #analyse_response(response) ⇒ Object
- #analyze_functional_test(test_context) ⇒ Object
- #content_disposition(name) ⇒ Object
-
#initialize ⇒ Recorder
constructor
A new instance of Recorder.
- #parse_data(data) ⇒ Object
- #record ⇒ Object
- #reformat_array(boundary, attrs, key, lines) ⇒ Object
- #reformat_boolean(boundary, attrs, key, lines) ⇒ Object
- #reformat_data(data) ⇒ Object
- #reformat_hash(boundary, attrs, lines) ⇒ Object
- #reformat_multipart_data(form) ⇒ Object
- #reformat_uploaded_file(boundary, file, key, lines) ⇒ Object
Constructor Details
#initialize ⇒ Recorder
Returns a new instance of Recorder.
6 7 8 |
# File 'lib/apipie/extractor/recorder.rb', line 6 def initialize @ignored_params = [:controller, :action] end |
Instance Method Details
#analyse_controller(controller) ⇒ Object
25 26 27 28 |
# File 'lib/apipie/extractor/recorder.rb', line 25 def analyse_controller(controller) @controller = controller.class @action = Apipie.configuration.api_action_matcher.call(controller) end |
#analyse_env(env) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/apipie/extractor/recorder.rb', line 10 def analyse_env(env) @verb = env["REQUEST_METHOD"].to_sym @path = env["PATH_INFO"].sub(%r{^/*},"/") @query = env["QUERY_STRING"] unless env["QUERY_STRING"].blank? @params = Rack::Utils.parse_nested_query(@query) @params.merge!(env["action_dispatch.request.request_parameters"] || {}) rack_input = env["rack.input"] if data = parse_data(rack_input&.read) @request_data = data elsif form_hash = env["rack.request.form_hash"] @request_data = reformat_multipart_data(form_hash) end rack_input&.rewind end |
#analyse_response(response) ⇒ Object
30 31 32 33 34 35 36 37 38 39 |
# File 'lib/apipie/extractor/recorder.rb', line 30 def analyse_response(response) if response.last.respond_to?(:body) && data = parse_data(response.last.body) @response_data = if response[1]['Content-Disposition'].to_s.start_with?('attachment') '<STREAMED ATTACHMENT FILE>' else data end end @code = response.first end |
#analyze_functional_test(test_context) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/apipie/extractor/recorder.rb', line 41 def analyze_functional_test(test_context) request, response = test_context.request, test_context.response @verb = request.request_method.to_sym @path = request.path @params = request.request_parameters if [:POST, :PUT, :PATCH, :DELETE].include?(@verb) @request_data = request.content_type == "multipart/form-data" ? reformat_multipart_data(@params) : @params else @query = request.query_string end if response.media_type != 'application/pdf' @response_data = parse_data(response.body) end @code = response.code end |
#content_disposition(name) ⇒ Object
115 116 117 |
# File 'lib/apipie/extractor/recorder.rb', line 115 def content_disposition(name) %{Content-Disposition: form-data; name="#{name}"} end |
#parse_data(data) ⇒ Object
57 58 59 60 61 62 |
# File 'lib/apipie/extractor/recorder.rb', line 57 def parse_data(data) return nil if data.strip.blank? JSON.parse(data) rescue StandardError data end |
#record ⇒ Object
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/apipie/extractor/recorder.rb', line 131 def record if @controller {:controller => @controller, :action => @action, :verb => @verb, :path => @path, :params => @params, :query => @query, :request_data => @request_data, :response_data => @response_data, :code => @code} else nil end end |
#reformat_array(boundary, attrs, key, lines) ⇒ Object
102 103 104 105 106 107 |
# File 'lib/apipie/extractor/recorder.rb', line 102 def reformat_array(boundary, attrs, key, lines) attrs.each do |item| lines << boundary << content_disposition("#{key}[]") lines << '' << item end end |
#reformat_boolean(boundary, attrs, key, lines) ⇒ Object
97 98 99 100 |
# File 'lib/apipie/extractor/recorder.rb', line 97 def reformat_boolean(boundary, attrs, key, lines) lines << boundary << content_disposition(key) lines << '' << attrs.to_s end |
#reformat_data(data) ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/apipie/extractor/recorder.rb', line 119 def reformat_data(data) parsed = parse_data(data) case parsed when nil nil when String parsed else JSON.pretty_generate().gsub(/: \[\s*\]/,": []").gsub(/\{\s*\}/,"{}") end end |
#reformat_hash(boundary, attrs, lines) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/apipie/extractor/recorder.rb', line 85 def reformat_hash(boundary, attrs, lines) if head = attrs[:head] lines << boundary lines.concat(head.split("\r\n")) # To avoid large and/or binary file bodies, simply indicate the contents in the output. lines << '' << %{... contents of "#{attrs[:name]}" ...} else # Look for subelements that contain a part. attrs.each_value { |v| v.is_a?(Hash) and reformat_hash(boundary, v, lines) } end end |
#reformat_multipart_data(form) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/apipie/extractor/recorder.rb', line 64 def reformat_multipart_data(form) form.empty? and return '' lines = ["Content-Type: multipart/form-data; boundary=#{MULTIPART_BOUNDARY}",''] boundary = "--#{MULTIPART_BOUNDARY}" form.each do |key, attrs| if attrs.is_a?(String) # rubocop:disable Style/CaseLikeIf lines << boundary << content_disposition(key) << "Content-Length: #{attrs.size}" << '' << attrs elsif attrs.is_a?(Rack::Test::UploadedFile) || attrs.is_a?(ActionDispatch::Http::UploadedFile) reformat_uploaded_file(boundary, attrs, key, lines) elsif attrs.is_a?(Array) reformat_array(boundary, attrs, key, lines) elsif attrs.is_a?(TrueClass) || attrs.is_a?(FalseClass) reformat_boolean(boundary, attrs, key, lines) else reformat_hash(boundary, attrs, lines) end end lines << "#{boundary}--" lines.join("\n") end |
#reformat_uploaded_file(boundary, file, key, lines) ⇒ Object
109 110 111 112 113 |
# File 'lib/apipie/extractor/recorder.rb', line 109 def reformat_uploaded_file(boundary, file, key, lines) lines << boundary << %{#{content_disposition(key)}; filename="#{file.original_filename}"} lines << "Content-Length: #{file.size}" << "Content-Type: #{file.content_type}" << "Content-Transfer-Encoding: binary" lines << '' << %{... contents of "#{key}" ...} end |