simple-http 0.3.4 → 0.3.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af4c48df122f1e2d75e2646e7175e8356b3d29ed29090b7b2d50e5b045ac4c67
4
- data.tar.gz: 377058a3745909a67b4cf51307fcc87743bf5e054e681541e72b668473a07933
3
+ metadata.gz: 1cb6ffe1146cced4e3a576fcb776e13143be9a51e04352b421bec43eb18ca495
4
+ data.tar.gz: d071d8653cc3b7ad160a3e556a045d4441b425a1830b1c60ddef64703feab641
5
5
  SHA512:
6
- metadata.gz: 3bb65d9e2a2fe14e197fcab613fe587523fb932cd1f45b2648d2a160defe25762490223d66a338d342095abb83fafc3c564a6d3bd525c0dc5033728dad33dde8
7
- data.tar.gz: 910e7c3e08cd98361067e79082496b972cb24e0b3bc64365807d058119696e23758a3ac2e166ebdbe1dd678c8a0c4b10dcfaeeaf1c5b105cb7613fe8dd6765da
6
+ metadata.gz: fa509ffb0416b20cbb3cde6820d69a4daa6560f741ce69088dda99ed55b61394ec6964608a7a3156fb8cd17cdae7fc48b5d3d912efb5981f6658ddfc429faedb
7
+ data.tar.gz: 4c1b2ce423984fe8c5c043360fd40196bc9e79007182b6b6d2fce605948ac2e166b8ef9d4a6028e7687044164b323a397f02573d3c6885e8b226e4c2e708d04f
@@ -0,0 +1,81 @@
1
+ # The code in this module was originally taken from rack/media_type.rb
2
+ # and modified. We don't include a rack dependency here, since we don't
3
+ # want to use a server library in a client tool.
4
+
5
+ # parses content_type to return media_type and charset.
6
+ class Simple::HTTP::ContentTypeParser
7
+ SPLIT_PATTERN = %r{\s*[;,]\s*}
8
+
9
+ # The content_type value as being passed in.
10
+ attr_reader :content_type
11
+
12
+ # The media type (type/subtype) portion of the CONTENT_TYPE header
13
+ # without any media type parameters. e.g., when CONTENT_TYPE is
14
+ # "text/plain;charset=utf-8", the media-type is "text/plain".
15
+ #
16
+ # For more information on the use of media types in HTTP, see:
17
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
18
+ attr_reader :media_type
19
+
20
+ # The charset as embedded on the Content-Type header
21
+ attr_reader :charset
22
+
23
+ def initialize(content_type)
24
+ @content_type = content_type
25
+ @media_type = content_type.split(SPLIT_PATTERN, 2).first.downcase if content_type
26
+ @charset = extract_charset_from_content_type if content_type
27
+ end
28
+
29
+ # returns the encoding the body is supposed to be encoded as.
30
+ def encoding
31
+ resolve_encoding_name(charset || guess_encoding_name)
32
+ end
33
+
34
+ def reencode!(body)
35
+ body.force_encoding(encoding)
36
+ unless body.valid_encoding?
37
+ raise "Invalid payload: body is encoded invalid; encoding is #{content_type_parser.encoding.name}"
38
+ end
39
+
40
+ body
41
+ end
42
+
43
+ private
44
+
45
+ def resolve_encoding_name(str)
46
+ ::Encoding.find(str)
47
+ rescue ArgumentName
48
+ raise "Cannot resolve encoding name #{encoding_name.inspect} from Content-Type: #{content_type.inspect}"
49
+ end
50
+
51
+ # This method is being called when there is no charset value in the content_type header.
52
+ def guess_encoding_name
53
+ case media_type
54
+ when /^application\/json/, /^application\/xml/, /^text\// then "UTF-8"
55
+ else "ASCII-8BIT"
56
+ end
57
+ end
58
+
59
+ CHARSET_PARAMETER_NAME = "charset"
60
+
61
+ # The media type parameters provided in CONTENT_TYPE as a Hash, or
62
+ # an empty Hash if no CONTENT_TYPE or media-type parameters were
63
+ # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
64
+ # this method responds with the following Hash:
65
+ # { 'charset' => 'utf-8' }
66
+ def extract_charset_from_content_type
67
+ content_type.split(SPLIT_PATTERN)[1..-1].each do |s|
68
+ k, v = s.split("=", 2)
69
+ next unless k.downcase == CHARSET_PARAMETER_NAME
70
+
71
+ return strip_double_quotes(v)
72
+ end
73
+
74
+ nil
75
+ end
76
+
77
+ def strip_double_quotes(str)
78
+ str = str[1..-2] if str[0] == '"' && str[-1] == '"'
79
+ str
80
+ end
81
+ end
@@ -1,4 +1,4 @@
1
- require_relative "./body_builder"
1
+ require_relative "./content_type_parser"
2
2
 
3
3
  class Simple::HTTP::Response
4
4
  class << self
@@ -18,48 +18,35 @@ class Simple::HTTP::Response
18
18
  end
19
19
  end
20
20
 
21
- BodyBuilder = Simple::HTTP::BodyBuilder
21
+ ContentTypeParser = Simple::HTTP::ContentTypeParser
22
22
 
23
23
  attr_reader :request
24
24
  attr_reader :status
25
25
  attr_reader :message
26
26
  attr_reader :headers
27
- attr_reader :original_body
27
+ attr_reader :body
28
+
29
+ # e.g "text/plain"
30
+ attr_reader :media_type
28
31
 
29
32
  private
30
33
 
31
34
  def initialize(request, body, headers, status, message)
32
35
  @request = request
33
36
  @headers = headers
34
- @status = status
37
+ @status = status
35
38
  @message = message
36
- @original_body = body
37
-
38
- # adjust encoding on original_body
39
- @body_builder = BodyBuilder.new(headers["Content-Type"])
40
39
 
41
- if @original_body && (charset = @body_builder.charset)
42
- @original_body.force_encoding(charset)
43
- end
40
+ # evaluate content type header, set media_type and set body encoding.
41
+ ctp = ContentTypeParser.new(headers["Content-Type"])
42
+ @media_type = ctp.media_type
43
+ @body = ctp.reencode!(body) if body
44
44
  end
45
45
 
46
46
  public
47
47
 
48
- # e.g "text/plain"
49
- def media_type
50
- @body_builder.media_type
51
- end
52
-
53
- # returns the body
54
- #
55
- # This method reencodes the text body into UTF-8. Non-text bodies should be
56
- # encoded as ASCII-8BIT (a.k.a. "BINARY")
57
- def body
58
- @body ||= @body_builder.reencode(@original_body)
59
- end
60
-
61
48
  def bytes
62
- @original_body&.bytesize || 0
49
+ @body ? @body.bytesize : 0
63
50
  end
64
51
 
65
52
  def to_s
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - radiospiel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-25 00:00:00.000000000 Z
11
+ date: 2020-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: expectation
@@ -39,9 +39,9 @@ files:
39
39
  - README.md
40
40
  - lib/simple-http.rb
41
41
  - lib/simple/http.rb
42
- - lib/simple/http/body_builder.rb
43
42
  - lib/simple/http/caching.rb
44
43
  - lib/simple/http/checked_response.rb
44
+ - lib/simple/http/content_type_parser.rb
45
45
  - lib/simple/http/driver/default.rb
46
46
  - lib/simple/http/driver/faraday.rb
47
47
  - lib/simple/http/errors.rb
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
78
  - !ruby/object:Gem::Version
79
79
  version: '0'
80
80
  requirements: []
81
- rubygems_version: 3.0.6
81
+ rubygems_version: 3.0.4
82
82
  signing_key:
83
83
  specification_version: 4
84
84
  summary: Simple code for simple HTTP requests
@@ -1,71 +0,0 @@
1
- # This module originally was taken from rack/media_type.rb and modified:
2
- # we don't want to have a rack (which is a server toolset) dependency
3
- # in simple-http, which is a client after all.
4
-
5
- # parses content_type to return media_type and charset, and can reencode bodies.
6
- class Simple::HTTP::BodyBuilder
7
- SPLIT_PATTERN = %r{\s*[;,]\s*}
8
-
9
- def initialize(content_type)
10
- @media_type = content_type.split(SPLIT_PATTERN, 2).first.downcase if content_type
11
- @charset = fetch_content_type_param(content_type, "charset", default: nil)
12
- end
13
-
14
- # The media type (type/subtype) portion of the CONTENT_TYPE header
15
- # without any media type parameters. e.g., when CONTENT_TYPE is
16
- # "text/plain;charset=utf-8", the media-type is "text/plain".
17
- #
18
- # For more information on the use of media types in HTTP, see:
19
- # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
20
- attr_reader :media_type
21
-
22
- # The charset as embedded on the Content-Type header
23
- attr_reader :charset
24
-
25
- # returns the body
26
- #
27
- # This method reencodes the text body into UTF-8. Non-text bodies should be
28
- # encoded as ASCII-8BIT (a.k.a. "BINARY")
29
- def reencode(body)
30
- body&.encode(best_encoding)
31
- end
32
-
33
- private
34
-
35
- BINARY = ::Encoding.find "ASCII-8BIT"
36
- UTF8 = ::Encoding.find "UTF-8"
37
-
38
- # returns the encoding we want for the body.
39
- #
40
- # This method makes sure to reencode text bodies into UTF-8, and non-text
41
- # bodies as ASCII-8BIT (a.k.a. "BINARY")
42
- def best_encoding
43
- case media_type
44
- when /^application\/json/, /^application\/xml/, /^text\// then UTF8
45
- else BINARY
46
- end
47
- end
48
-
49
- # The media type parameters provided in CONTENT_TYPE as a Hash, or
50
- # an empty Hash if no CONTENT_TYPE or media-type parameters were
51
- # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
52
- # this method responds with the following Hash:
53
- # { 'charset' => 'utf-8' }
54
- def fetch_content_type_param(content_type, parameter_name, default:)
55
- return default if content_type.nil?
56
-
57
- parameter_name = parameter_name.downcase
58
-
59
- content_type.split(SPLIT_PATTERN)[1..-1]
60
- .each do |s|
61
- k, v = s.split("=", 2)
62
- return strip_doublequotes(v) if k.downcase == parameter_name
63
- end
64
-
65
- default
66
- end
67
-
68
- def strip_doublequotes(str)
69
- str[0] == '"' && str[-1] == '"' ? str[1..-2] : str
70
- end
71
- end