vigiles 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.ruby-version +1 -0
  4. data/lib/generators/vigiles/initializer_generator.rb +1 -1
  5. data/lib/generators/vigiles/install_generator.rb +1 -1
  6. data/lib/generators/vigiles/migration_generator.rb +2 -1
  7. data/lib/vigiles/archive/extras.rb +1 -1
  8. data/lib/vigiles/archive/metadata.rb +1 -1
  9. data/lib/vigiles/archive/response.rb +31 -5
  10. data/lib/vigiles/archive.rb +1 -1
  11. data/lib/vigiles/constants.rb +161 -1
  12. data/lib/vigiles/conversation_recorder.rb +3 -0
  13. data/lib/vigiles/conversation_recorders/application_json.rb +11 -6
  14. data/lib/vigiles/conversation_recorders/unknown.rb +3 -0
  15. data/lib/vigiles/middleware/record_conversation.rb +2 -2
  16. data/lib/vigiles/options.rb +1 -0
  17. data/lib/vigiles/types.rb +6 -0
  18. data/lib/vigiles/utilities/http.rb +60 -0
  19. data/lib/vigiles/utilities/json.rb +3 -2
  20. data/lib/vigiles/version.rb +1 -1
  21. data/lib/vigiles.rb +15 -3
  22. data/sorbet/rbi/gems/concurrent-ruby@1.3.1.rbi +11627 -0
  23. data/sorbet/rbi/gems/{json@2.7.1.rbi → json@2.7.2.rbi} +73 -72
  24. data/sorbet/rbi/gems/{minitest@5.22.2.rbi → minitest@5.23.1.rbi} +841 -159
  25. data/sorbet/rbi/gems/{parser@3.3.0.5.rbi → parser@3.3.1.0.rbi} +233 -186
  26. data/sorbet/rbi/gems/{prism@0.24.0.rbi → prism@0.29.0.rbi} +19135 -12188
  27. data/sorbet/rbi/gems/{racc@1.7.3.rbi → racc@1.8.0.rbi} +34 -33
  28. data/sorbet/rbi/gems/{rake@13.1.0.rbi → rake@13.2.1.rbi} +77 -55
  29. data/sorbet/rbi/gems/{rbi@0.1.9.rbi → rbi@0.1.13.rbi} +226 -154
  30. data/sorbet/rbi/gems/{rdoc@6.6.3.1.rbi → rdoc@6.7.0.rbi} +333 -327
  31. data/sorbet/rbi/gems/{regexp_parser@2.9.0.rbi → regexp_parser@2.9.2.rbi} +3 -2
  32. data/sorbet/rbi/gems/{reline@0.5.7.rbi → reline@0.5.8.rbi} +1 -0
  33. data/sorbet/rbi/gems/{rexml@3.2.6.rbi → rexml@3.2.8.rbi} +121 -108
  34. data/sorbet/rbi/gems/{rubocop-ast@1.30.0.rbi → rubocop-ast@1.31.3.rbi} +92 -62
  35. data/sorbet/rbi/gems/{rubocop-minitest@0.34.5.rbi → rubocop-minitest@0.35.0.rbi} +35 -0
  36. data/sorbet/rbi/gems/{rubocop-sorbet@0.7.4.rbi → rubocop-sorbet@0.8.3.rbi} +327 -162
  37. data/sorbet/rbi/gems/{rubocop@1.60.2.rbi → rubocop@1.64.0.rbi} +1719 -1065
  38. data/sorbet/rbi/gems/{spoom@1.2.4.rbi → spoom@1.3.2.rbi} +1057 -413
  39. data/sorbet/rbi/gems/strscan@3.1.0.rbi +9 -0
  40. data/sorbet/rbi/gems/{tapioca@0.12.0.rbi → tapioca@0.14.2.rbi} +123 -448
  41. data/sorbet/rbi/gems/{thor@1.3.0.rbi → thor@1.3.1.rbi} +57 -50
  42. data/sorbet/rbi/gems/{yard@0.9.34.rbi → yard@0.9.36.rbi} +230 -37
  43. data/sorbet/rbi/gems/{zeitwerk@2.6.13.rbi → zeitwerk@2.6.15.rbi} +47 -36
  44. data/vigiles.gemspec +1 -1
  45. metadata +30 -29
  46. data/sorbet/rbi/gems/concurrent-ruby@1.2.3.rbi +0 -8
  47. data/sorbet/rbi/gems/prettier_print@1.2.1.rbi +0 -951
  48. data/sorbet/rbi/gems/syntax_tree@6.2.0.rbi +0 -23136
  49. /data/lib/generators/{templates → vigiles/templates}/archive_conversation_migration.rb.erb +0 -0
  50. /data/lib/generators/{templates → vigiles/templates}/initializer.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 41caead3a350b299aaccd28f0a57472d7c91e1a3f4d99edc93fb5721883ede73
4
- data.tar.gz: d890a26b05693bb9503e4ed5583489d9100eed2703c4e2b2028b03c4d7e863bc
3
+ metadata.gz: 5cad76457ae57c5b08da94044394a063e57f5d1e5ea5a8b9cea412876dce12bf
4
+ data.tar.gz: 6eb84b1766ef2e737652fc63e28924756b8d26d74b676d9f716f1db8e0744c8f
5
5
  SHA512:
6
- metadata.gz: 06fd18e862c094ae7e90f602eb4505f0906528c17a28d69d04c2bd1f2dfa49b771c65bffdcd42590a93b44a85bdb13a0a7822889ec329cc9aee7b165297b171f
7
- data.tar.gz: 036f4843fe70977471e7bf67d08850971593cff46abf1a47ae9fe8634b413b4eb7911eb92ac0fcbb107b34ff273f8d2d74d96148abab118efed400e22f25469d
6
+ metadata.gz: 23a0e61a11a529603eebc7e197961762b493c940a2b33cb510f0f81e419b2379a9a3e207eb236be1a1aae44009cf75f95aec401dc1b3ee95cefad6b678809505
7
+ data.tar.gz: 697eb918976d40ea0189d9b1de700caeae6931e28f41a6627d055c7c3d6eed4df44cf541d705f2ecb66931549c8af5825cf0177e9835eb2f2a7d2705dcf000b5
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ require:
4
4
  - rubocop-sorbet
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 3.0
7
+ TargetRubyVersion: 3.3
8
8
  Exclude:
9
9
  - "**/generators/**/*"
10
10
  - "**/sorbet/**/*"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.3.1
@@ -10,7 +10,7 @@ module Vigiles
10
10
  default configuration.
11
11
  DOC
12
12
 
13
- source_root File.expand_path("../templates", __dir__)
13
+ source_root File.expand_path("templates", __dir__)
14
14
 
15
15
  def copy_initializer_file
16
16
  copy_file \
@@ -13,7 +13,7 @@ module Vigiles
13
13
  ]
14
14
  ).freeze
15
15
 
16
- source_root File.expand_path("../templates", __dir__)
16
+ source_root File.expand_path("templates", __dir__)
17
17
 
18
18
  def install_vigiles
19
19
  SUB_GENERATORS.each do |generator_task|
@@ -3,6 +3,7 @@
3
3
 
4
4
  require "rails/generators"
5
5
  require "rails/generators/active_record"
6
+ require "active_record"
6
7
 
7
8
  module Vigiles
8
9
  module Generators
@@ -12,7 +13,7 @@ module Vigiles
12
13
 
13
14
  include ::Rails::Generators::Migration
14
15
 
15
- source_root File.expand_path("../templates", __dir__)
16
+ source_root File.expand_path("templates", __dir__)
16
17
 
17
18
  def install
18
19
  migration_template(
@@ -8,7 +8,7 @@ module Vigiles
8
8
 
9
9
  sig { params(request_env: T::Hash[T.untyped, T.untyped]).returns(Extras) }
10
10
  def self.from(request_env)
11
- Extras.new(request_env: request_env)
11
+ Extras.new(request_env:)
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Vigiles
8
8
 
9
9
  sig { params(request_env: T::Hash[T.untyped, T.untyped]).returns(Metadata) }
10
10
  def self.from(request_env)
11
- Metadata.new(request_env: request_env)
11
+ Metadata.new(request_env:)
12
12
  end
13
13
  end
14
14
  end
@@ -1,4 +1,4 @@
1
- # typed: false
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Vigiles
@@ -10,6 +10,33 @@ module Vigiles
10
10
  const :payload, Types::Payload
11
11
  const :status, Integer
12
12
 
13
+ class ResponseBodyTooDeepError < StandardError
14
+ sig { returns(Integer) }
15
+ attr_reader :max_stack_depth
16
+
17
+ sig { returns(Integer) }
18
+ attr_reader :stack_depth
19
+
20
+ sig { params(stack_depth: Integer, max_stack_depth: Integer).void }
21
+ def initialize(stack_depth, max_stack_depth)
22
+ @max_stack_depth = max_stack_depth
23
+ @stack_depth = stack_depth
24
+
25
+ super()
26
+ end
27
+ end
28
+
29
+ sig { params(body: Rack::BodyProxy, stack_depth: Integer).returns(String) }
30
+ private_class_method def self.extract_body_from_rack_body_proxy(body, stack_depth = 1)
31
+ raise ResponseBodyTooDeepError.new(stack_depth, 5) unless stack_depth < 5
32
+
33
+ case (inner_body = body.instance_variable_get(:@body))
34
+ when Rack::BodyProxy then extract_body_from_rack_body_proxy(inner_body, stack_depth + 1)
35
+ when Array then inner_body[0] || "null"
36
+ else raise
37
+ end
38
+ end
39
+
13
40
  sig { params(rack_response: Rack::Response).returns(Types::Payload) }
14
41
  private_class_method def self.extract_payload(rack_response)
15
42
  case (body = rack_response.body)
@@ -18,12 +45,11 @@ module Vigiles
18
45
 
19
46
  { __false_body: :not_empty_handle_later }
20
47
  when Rack::BodyProxy
21
- body_proxy = body
22
- body_proxy = body_proxy.instance_variable_get(:@body) until body_proxy.is_a?(Array)
48
+ extracted_body = extract_body_from_rack_body_proxy(body)
23
49
  begin
24
- JSON.parse(body_proxy[0])
50
+ JSON.parse(extracted_body)
25
51
  rescue StandardError
26
- { __false_body: body_proxy[0] }
52
+ { __false_body: extracted_body }
27
53
  end
28
54
  else
29
55
  { __false_body: :unknown_response_payload_type }
@@ -15,7 +15,7 @@ module Vigiles
15
15
  super
16
16
  end
17
17
  end
18
-
18
+
19
19
  sig { params(req: ActionDispatch::Request, res: Rack::Response).returns(T.nilable(Conversation)) }
20
20
  def self.record_conversation(req:, res:)
21
21
  content_type = req.content_type
@@ -8,7 +8,167 @@ module Vigiles
8
8
  %w[
9
9
  application/json
10
10
  ]
11
- ), T::Set[String]
11
+ ).freeze,
12
+ T::Set[String]
13
+ )
14
+
15
+ ALL_IANA_CONTENT_TYPES = T.let(
16
+ {
17
+ Types::ContentType::ApplicationJson => Set.new(
18
+ %w[
19
+ application/3gppHal+json
20
+ application/3gppHalForms+json
21
+ application/ace+json
22
+ application/activity+json
23
+ application/aif+json
24
+ application/alto-cdni+json
25
+ application/alto-cdnifilter+json
26
+ application/alto-costmap+json
27
+ application/alto-costmapfilter+json
28
+ application/alto-directory+json
29
+ application/alto-endpointprop+json
30
+ application/alto-endpointpropparams+json
31
+ application/alto-endpointcost+json
32
+ application/alto-endpointcostparams+json
33
+ application/alto-error+json
34
+ application/alto-networkmapfilter+json
35
+ application/alto-networkmap+json
36
+ application/alto-propmap+json
37
+ application/alto-propmapparams+json
38
+ application/alto-tips+json
39
+ application/alto-tipsparams+json
40
+ application/alto-updatestreamcontrol+json
41
+ application/alto-updatestreamparams+json
42
+ application/atsc-rdt+json
43
+ application/calendar+json
44
+ application/captive+json
45
+ application/city+json
46
+ application/coap-group+json
47
+ application/csvm+json
48
+ application/cwl+json
49
+ application/dicom+json
50
+ application/dns+json
51
+ application/elm+json
52
+ application/EmergencyCallData.LegacyESN+json
53
+ application/expect-ct-report+json
54
+ application/fhir+json
55
+ application/geo+json
56
+ application/geo+json-seq
57
+ application/geoxacml+json
58
+ application/jf2feed+json
59
+ application/jose+json
60
+ application/jrd+json
61
+ application/jscalendar+json
62
+ application/jscontact+json
63
+ application/json
64
+ application/json-patch+json
65
+ application/json-seq
66
+ application/jsonpath
67
+ application/jwk+json
68
+ application/jwk-set+json
69
+ application/ld+json
70
+ application/linkset+json
71
+ application/manifest+json
72
+ application/merge-patch+json
73
+ application/mud+json
74
+ application/ppsp-tracker+json
75
+ application/problem+json
76
+ application/prs.implied-object+json
77
+ application/prs.implied-object+json-seq
78
+ application/pvd+json
79
+ application/rdap+json
80
+ application/reputon+json
81
+ application/sarif-external-properties+json
82
+ application/sarif+json
83
+ application/scim+json
84
+ application/senml-etch+json
85
+ application/senml+json
86
+ application/sensml+json
87
+ application/spdx+json
88
+ application/stix+json
89
+ application/taxii+json
90
+ application/td+json
91
+ application/tlsrpt+json
92
+ application/tm+json
93
+ application/vcard+json
94
+ application/vnd.acm.addressxfer+json
95
+ application/vnd.acm.chatbot+json
96
+ application/vnd.amadeus+json
97
+ application/vnd.apache.thrift.json
98
+ application/vnd.api+json
99
+ application/vnd.aplextor.warrp+json
100
+ application/vnd.apothekende.reservation+json
101
+ application/vnd.artisan+json
102
+ application/vnd.avalon+json
103
+ application/vnd.bbf.usp.msg+json
104
+ application/vnd.bekitzur-stech+json
105
+ application/vnd.byu.uapi+json
106
+ application/vnd.capasystems-pg+json
107
+ application/vnd.cncf.helm.config.v1+json
108
+ application/vnd.collection.doc+json
109
+ application/vnd.collection+json
110
+ application/vnd.collection.next+json
111
+ application/vnd.coreos.ignition+json
112
+ application/vnd.cryptii.pipe+json
113
+ application/vnd.cyclonedx+json
114
+ application/vnd.datapackage+json
115
+ application/vnd.dataresource+json
116
+ application/vnd.document+json
117
+ application/vnd.drive+json
118
+ application/vnd.eclipse.ditto+json
119
+ application/vnd.eu.kasparian.car+json
120
+ application/vnd.futoin+json
121
+ application/vnd.gentics.grd+json
122
+ application/vnd.geo+json
123
+ application/vnd.gnu.taler.exchange+json
124
+ application/vnd.gnu.taler.merchant+json
125
+ application/vnd.hal+json
126
+ application/vnd.hc+json
127
+ application/vnd.heroku+json
128
+ application/vnd.hyper-item+json
129
+ application/vnd.hyper+json
130
+ application/vnd.hyperdrive+json
131
+ application/vnd.ims.lis.v2.result+json
132
+ application/vnd.ims.lti.v2.toolconsumerprofile+json
133
+ application/vnd.ims.lti.v2.toolproxy.id+json
134
+ application/vnd.ims.lti.v2.toolproxy+json
135
+ application/vnd.ims.lti.v2.toolsettings+json
136
+ application/vnd.ims.lti.v2.toolsettings.simple+json
137
+ application/vnd.ipld.dag-json
138
+ application/vnd.las.las+json
139
+ application/vnd.leap+json
140
+ application/vnd.mason+json
141
+ application/vnd.micro+json
142
+ application/vnd.miele+json
143
+ application/vnd.nacamar.ybrid+json
144
+ application/vnd.nato.bindingdataobject+json
145
+ application/vnd.nearst.inv+json
146
+ application/vnd.oai.workflows+json
147
+ application/vnd.oci.image.manifest.v1+json
148
+ application/vnd.oftn.l10n+json
149
+ application/vnd.oma.lwm2m+json
150
+ application/vnd.oracle.resource+json
151
+ application/vnd.pagerduty+json
152
+ application/vnd.restful+json
153
+ application/vnd.seis+json
154
+ application/vnd.shootproof+json
155
+ application/vnd.shopkick+json
156
+ application/vnd.siren+json
157
+ application/vnd.syft+json
158
+ application/vnd.tableschema+json
159
+ application/vnd.think-cell.ppttc+json
160
+ application/vnd.vel+json
161
+ application/vnd.veritone.aion+json
162
+ application/vnd.xacml+json
163
+ application/voucher-cms+json
164
+ application/webpush-options+json
165
+ application/yang-data+json
166
+ application/yang-patch+json
167
+ application/yang-sid+json
168
+ ].map(&:downcase)
169
+ ).freeze
170
+ }.freeze,
171
+ T::Hash[Types::ContentType, T::Set[String]]
12
172
  )
13
173
 
14
174
  DEFAULT_CONTENT_TYPE_RECORDERS = T.let(
@@ -20,6 +20,9 @@ module Vigiles
20
20
 
21
21
  abstract!
22
22
 
23
+ sig { abstract.params(req: ActionDispatch::Request).void }
24
+ def ensure_content_type_matches!(req); end
25
+
23
26
  sig { abstract.params(req: ActionDispatch::Request, res: Rack::Response).returns(Archive::Conversation) }
24
27
  def record(req:, res:); end
25
28
  end
@@ -14,14 +14,19 @@ module Vigiles
14
14
  Request = Vigiles::Archive::Request
15
15
  Extras = Vigiles::Archive::Extras
16
16
 
17
+ sig { override.params(req: ActionDispatch::Request).void }
18
+ private def ensure_content_type_matches!(req)
19
+ return if req.content_type == ContentType::ApplicationJson.serialize
20
+
21
+ raise ConversationRecorder::MisconfiguredRecorderError.new(
22
+ expected: ContentType::ApplicationJson.serialize,
23
+ actual: req.content_type
24
+ )
25
+ end
26
+
17
27
  sig { override.params(req: ActionDispatch::Request, res: Rack::Response).returns(Archive::Conversation) }
18
28
  def record(req:, res:)
19
- unless req.content_type == ContentType::ApplicationJson.serialize
20
- raise ConversationRecorder::MisconfiguredRecorderError.new(
21
- expected: ContentType::ApplicationJson.serialize,
22
- actual: req.content_type
23
- )
24
- end
29
+ ensure_content_type_matches!(req)
25
30
 
26
31
  response = Response.from(res)
27
32
  request = Request.from(req)
@@ -6,6 +6,9 @@ module Vigiles
6
6
  class Unknown < ConversationRecorder
7
7
  include Singleton
8
8
 
9
+ sig { override.params(req: ActionDispatch::Request).void }
10
+ def ensure_content_type_matches!(req); end
11
+
9
12
  sig { override.params(req: ActionDispatch::Request, res: Rack::Response).returns(Archive::Conversation) }
10
13
  def record(req:, res:) = Archive::Conversation.new
11
14
  end
@@ -13,7 +13,7 @@ module Vigiles
13
13
  to: :options
14
14
 
15
15
  sig { params(app: T.untyped, options: Vigiles::Options).void }
16
- def initialize(app, options=Vigiles::Options.make_default_options)
16
+ def initialize(app, options = Vigiles::Options.make_default_options)
17
17
  @app = app
18
18
  @options = options
19
19
  end
@@ -36,7 +36,7 @@ module Vigiles
36
36
  "[vigiles] conversation recorder: " \
37
37
  "conversation=#{convo.nil? ? "not_recorded" : convo.id} " \
38
38
  "request=#{req.request_id}"
39
- rescue => e
39
+ rescue StandardError => e
40
40
  capture_exception.call(e)
41
41
  logger.warn \
42
42
  "[vigiles] conversation recorder error: " \
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "logger"
5
+ require "rails"
5
6
 
6
7
  module Vigiles
7
8
  class Options < T::Struct
data/lib/vigiles/types.rb CHANGED
@@ -24,6 +24,12 @@ module Vigiles
24
24
  end
25
25
  end
26
26
 
27
+ class WellKnownHttpHeader < T::Enum
28
+ enums do
29
+ ContentType = new("content-type")
30
+ end
31
+ end
32
+
27
33
  HtmlPayload = String
28
34
 
29
35
  UntypedHash = T.type_alias { T::Hash[T.untyped, T.untyped] }
@@ -0,0 +1,60 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module Vigiles
5
+ module Utilities
6
+ module HTTP
7
+ extend T::Sig
8
+
9
+ WellKnownHttpHeader = Vigiles::Types::WellKnownHttpHeader
10
+ ContentType = Vigiles::Types::ContentType
11
+
12
+ # if http headers could be stemmed, this is what the
13
+ # method below would have done. at the moment, it works
14
+ # for only a few headers, and tries to clean up excesses
15
+ # that are not necessarily part of the value.
16
+ #
17
+ # since it raises, do not call unless you have explicitly
18
+ # handled the header. thanks!
19
+ sig { params(header: String, value: String).returns(String) }
20
+ def self.sanitize_header_value(header:, value:)
21
+ # don't attempt to sanitize values for relatively unknown
22
+ # headers. for example, custom headers (those with the x
23
+ # prefix). obviously if the value is blank then no sanitization
24
+ # is necessary.
25
+ return value if value.blank? || !well_known?(header)
26
+
27
+ case header.downcase
28
+ when "content-type" then sanitize_content_type(value.strip)
29
+ else raise ArgumentError, header
30
+ end
31
+ end
32
+
33
+ sig { params(header_value: String).returns(String) }
34
+ private_class_method def self.sanitize_content_type(header_value)
35
+ downcased_v = header_value.downcase
36
+ return ContentType::ApplicationJson.serialize if json?(downcased_v)
37
+
38
+ raise
39
+ end
40
+
41
+ sig { params(header: String).returns(T::Boolean) }
42
+ private_class_method def self.well_known?(header)
43
+ WellKnownHttpHeader.deserialize(header.downcase)
44
+ true
45
+ rescue StandardError
46
+ false
47
+ end
48
+
49
+ sig { params(header_value: String).returns(T::Boolean) }
50
+ private_class_method def self.json?(header_value)
51
+ return false if header_value.blank?
52
+
53
+ application_json = T.must(header_value.split(/;/).first)
54
+ T.must(
55
+ Constants::ALL_IANA_CONTENT_TYPES[ContentType::ApplicationJson]
56
+ ).include?(application_json)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -8,11 +8,12 @@ module Vigiles
8
8
  module JSON
9
9
  extend T::Sig
10
10
 
11
- sig { params(text: String).returns(T.any(String, Vigiles::Types::UntypedHash)) }
11
+ sig { params(text: String).returns(T.untyped) }
12
12
  def self.parse_benignly(text)
13
13
  ::JSON.parse(text)
14
14
  rescue StandardError
15
- text
15
+ return text unless block_given?
16
+ yield text
16
17
  end
17
18
  end
18
19
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Vigiles
5
- VERSION = "0.1.3"
5
+ VERSION = "0.1.5"
6
6
  end
data/lib/vigiles.rb CHANGED
@@ -1,13 +1,18 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "zeitwerk"
5
4
  require "sorbet-runtime"
6
5
  require "action_dispatch"
6
+ require "zeitwerk"
7
+
7
8
  require_relative "core_ext"
8
9
 
9
10
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
10
- loader.inflector.inflect("uri" => "URI", "json" => "JSON")
11
+ loader.inflector.inflect(
12
+ "json" => "JSON",
13
+ "http" => "HTTP",
14
+ "uri" => "URI"
15
+ )
11
16
  loader.ignore("#{__dir__}/generators")
12
17
  loader.ignore("#{__dir__}/core_ext.rb")
13
18
  loader.ignore("#{__dir__}/core_ext")
@@ -49,7 +54,14 @@ module Vigiles
49
54
 
50
55
  sig { params(request: ActionDispatch::Request).returns(T::Boolean) }
51
56
  private_class_method def self.content_type_match?(request)
52
- !request.nil?
57
+ return false if (content_type = request.content_type).nil?
58
+
59
+ spec.request_content_types.include?(
60
+ Utilities::HTTP.sanitize_header_value(
61
+ header: "content-type",
62
+ value: content_type
63
+ )
64
+ )
53
65
  end
54
66
 
55
67
  sig { params(req: ActionDispatch::Request).returns(T::Boolean) }