Class: FaradayJSON::ParseJson

Inherits:
Faraday::Middleware
  • Object
show all
Includes:
Encoding
Defined in:
lib/faraday_json/parse_json.rb

Overview

Public: Parse response bodies as JSON.

Direct Known Subclasses

ParseJsonMimeTypeFix

Defined Under Namespace

Modules: OptionsExtension

Constant Summary collapse

CONTENT_TYPE =
'Content-Type'.freeze

Instance Method Summary collapse

Methods included from Encoding

#bin_to_hex, #get_bom, #get_canonical_encoding, #get_dominant_encoding, #strip_bom, #to_utf8, #transcode

Constructor Details

#initialize(app = nil, options = {}) ⇒ ParseJson



22
23
24
25
26
# File 'lib/faraday_json/parse_json.rb', line 22

def initialize(app = nil, options = {})
  super(app)
  @options = options
  @content_types = Array(options[:content_type])
end

Instance Method Details

#call(environment) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/faraday_json/parse_json.rb', line 28

def call(environment)
  @app.call(environment).on_complete do |env|
    if process_response_type?(response_type(env)) and parse_response?(env)
      process_response(env)
    end
  end
end

#parse_response?(env) ⇒ Boolean



86
87
88
# File 'lib/faraday_json/parse_json.rb', line 86

def parse_response?(env)
  env[:body].respond_to? :to_str
end

#preserve_raw?(env) ⇒ Boolean



90
91
92
# File 'lib/faraday_json/parse_json.rb', line 90

def preserve_raw?(env)
  env[:request].fetch(:preserve_raw, @options[:preserve_raw])
end

#process_response(env) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/faraday_json/parse_json.rb', line 36

def process_response(env)
  env[:raw_body] = env[:body] if preserve_raw?(env)
  body = env[:body]

  # Body will be in an unknown encoding. Use charset field to coerce it to
  # internal UTF-8.
  charset = response_charset(env)

  # We must ensure we're interpreting the body as the right charset. First,
  # strip the BOM (if any).
  body = strip_bom(body, charset, { 'default_encoding' => 'us-ascii' })

  # Transcode to UTF-8
  body = to_utf8(body, charset, { 'force_input_charset' => true })

  # Now that's done, parse the JSON.
  ret = nil
  begin
    ret = ::JSON.parse(body) unless body.strip.empty?
  rescue StandardError, SyntaxError => err
    raise err if err.is_a? SyntaxError and err.class.name != 'Psych::SyntaxError'
    raise Faraday::Error::ParsingError, err
  end
  env[:body] = ret
end

#process_response_type?(type) ⇒ Boolean



80
81
82
83
84
# File 'lib/faraday_json/parse_json.rb', line 80

def process_response_type?(type)
  @content_types.empty? or @content_types.any? { |pattern|
    pattern.is_a?(Regexp) ? type =~ pattern : type == pattern
  }
end

#response_charset(env) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/faraday_json/parse_json.rb', line 68

def response_charset(env)
  header = env[:response_headers][CONTENT_TYPE].to_s
  if header.index(';')
    header.split(';').each do |part|
      if part.index('charset=')
        return part.split('charset=', 2).last
      end
    end
  end
  return nil
end

#response_type(env) ⇒ Object



62
63
64
65
66
# File 'lib/faraday_json/parse_json.rb', line 62

def response_type(env)
  type = env[:response_headers][CONTENT_TYPE].to_s
  type = type.split(';', 2).first if type.index(';')
  type
end