ddtrace 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -1
- data/ext/ddtrace_profiling_native_extension/collectors_cpu_and_wall_time.c +10 -10
- data/ext/ddtrace_profiling_native_extension/collectors_stack.c +32 -32
- data/ext/ddtrace_profiling_native_extension/collectors_stack.h +2 -2
- data/ext/ddtrace_profiling_native_extension/http_transport.c +50 -49
- data/ext/ddtrace_profiling_native_extension/libdatadog_helpers.h +5 -1
- data/ext/ddtrace_profiling_native_extension/native_extension_helpers.rb +34 -12
- data/ext/ddtrace_profiling_native_extension/private_vm_api_access.c +10 -0
- data/ext/ddtrace_profiling_native_extension/stack_recorder.c +32 -32
- data/ext/ddtrace_profiling_native_extension/stack_recorder.h +4 -4
- data/lib/datadog/appsec/assets/waf_rules/recommended.json +75 -8
- data/lib/datadog/appsec/assets/waf_rules/risky.json +1 -1
- data/lib/datadog/appsec/assets/waf_rules/strict.json +1 -1
- data/lib/datadog/appsec/assets.rb +1 -1
- data/lib/datadog/appsec/configuration/settings.rb +35 -22
- data/lib/datadog/appsec/configuration.rb +4 -2
- data/lib/datadog/appsec/contrib/auto_instrument.rb +1 -1
- data/lib/datadog/appsec/contrib/configuration/settings.rb +1 -1
- data/lib/datadog/appsec/contrib/integration.rb +1 -1
- data/lib/datadog/appsec/contrib/patcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/configuration/settings.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/ext.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/request_body.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/reactive/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rack/response.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/configuration/settings.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/ext.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/framework.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/reactive/action.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/request.rb +1 -1
- data/lib/datadog/appsec/contrib/rails/request_middleware.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/configuration/settings.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/ext.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/framework.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/gateway/watcher.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/reactive/routed.rb +1 -1
- data/lib/datadog/appsec/contrib/sinatra/request_middleware.rb +1 -1
- data/lib/datadog/appsec/event.rb +1 -1
- data/lib/datadog/appsec/extensions.rb +36 -26
- data/lib/datadog/appsec/instrumentation/gateway.rb +3 -3
- data/lib/datadog/appsec/processor.rb +15 -19
- data/lib/datadog/appsec/rate_limiter.rb +1 -1
- data/lib/datadog/appsec/reactive/address_hash.rb +1 -1
- data/lib/datadog/appsec/reactive/engine.rb +1 -1
- data/lib/datadog/appsec/reactive/operation.rb +2 -2
- data/lib/datadog/appsec/reactive/subscriber.rb +1 -1
- data/lib/datadog/appsec/response.rb +18 -9
- data/lib/datadog/appsec/utils/http/media_range.rb +201 -0
- data/lib/datadog/appsec/utils/http/media_type.rb +87 -0
- data/lib/datadog/appsec/utils/http.rb +9 -0
- data/lib/datadog/appsec/utils.rb +7 -0
- data/lib/datadog/appsec.rb +1 -1
- data/lib/datadog/ci/ext/environment.rb +57 -13
- data/lib/datadog/core/configuration/agent_settings_resolver.rb +2 -2
- data/lib/datadog/core/configuration/base.rb +3 -0
- data/lib/datadog/core/configuration/ext.rb +8 -0
- data/lib/datadog/core/configuration/option_definition.rb +11 -2
- data/lib/datadog/core/configuration/settings.rb +6 -4
- data/lib/datadog/core/diagnostics/environment_logger.rb +4 -3
- data/lib/datadog/core/metrics/client.rb +3 -2
- data/lib/datadog/core/metrics/ext.rb +0 -2
- data/lib/datadog/core/telemetry/collector.rb +1 -0
- data/lib/datadog/kit/appsec/events.rb +75 -0
- data/lib/datadog/kit/enable_core_dumps.rb +1 -0
- data/lib/datadog/kit/identity.rb +8 -7
- data/lib/datadog/opentelemetry/api/context.rb +187 -0
- data/lib/datadog/opentelemetry/api/trace/span.rb +15 -0
- data/lib/datadog/opentelemetry/sdk/configurator.rb +38 -0
- data/lib/datadog/opentelemetry/sdk/id_generator.rb +27 -0
- data/lib/datadog/opentelemetry/sdk/propagator.rb +91 -0
- data/lib/datadog/opentelemetry/sdk/span_processor.rb +92 -0
- data/lib/datadog/opentelemetry.rb +48 -0
- data/lib/datadog/tracing/configuration/ext.rb +1 -2
- data/lib/datadog/tracing/contrib/http/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/http/distributed/fetcher.rb +10 -3
- data/lib/datadog/tracing/contrib/http/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/http/instrumentation.rb +3 -6
- data/lib/datadog/tracing/contrib/httpclient/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/httpclient/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httpclient/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/httprb/configuration/settings.rb +5 -0
- data/lib/datadog/tracing/contrib/httprb/ext.rb +1 -0
- data/lib/datadog/tracing/contrib/httprb/instrumentation.rb +3 -4
- data/lib/datadog/tracing/contrib/pg/instrumentation.rb +44 -31
- data/lib/datadog/tracing/contrib/stripe/configuration/settings.rb +33 -0
- data/lib/datadog/tracing/contrib/stripe/ext.rb +26 -0
- data/lib/datadog/tracing/contrib/stripe/integration.rb +43 -0
- data/lib/datadog/tracing/contrib/stripe/patcher.rb +29 -0
- data/lib/datadog/tracing/contrib/stripe/request.rb +67 -0
- data/lib/datadog/tracing/contrib.rb +1 -0
- data/lib/datadog/tracing/distributed/trace_context.rb +16 -7
- data/lib/datadog/tracing/metadata/tagging.rb +6 -0
- data/lib/datadog/tracing/trace_digest.rb +17 -7
- data/lib/datadog/tracing/trace_operation.rb +8 -0
- data/lib/ddtrace/version.rb +1 -1
- metadata +23 -6
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
module Datadog
|
4
4
|
module AppSec
|
@@ -8,7 +8,8 @@ module Datadog
|
|
8
8
|
class Settings
|
9
9
|
class << self
|
10
10
|
def boolean
|
11
|
-
|
11
|
+
# @type ^(::String) -> bool
|
12
|
+
->(v) do # rubocop:disable Style/Lambda
|
12
13
|
case v
|
13
14
|
when /(1|true)/i
|
14
15
|
true
|
@@ -22,14 +23,16 @@ module Datadog
|
|
22
23
|
|
23
24
|
# TODO: allow symbols
|
24
25
|
def string
|
26
|
+
# @type ^(::String) -> ::String
|
25
27
|
->(v) { v.to_s }
|
26
28
|
end
|
27
29
|
|
28
30
|
def integer
|
29
|
-
|
31
|
+
# @type ^(::String) -> ::Integer
|
32
|
+
->(v) do # rubocop:disable Style/Lambda
|
30
33
|
case v
|
31
34
|
when /(\d+)/
|
32
|
-
|
35
|
+
Regexp.last_match(1).to_i
|
33
36
|
else
|
34
37
|
raise ArgumentError, "invalid integer: #{v.inspect}"
|
35
38
|
end
|
@@ -38,7 +41,8 @@ module Datadog
|
|
38
41
|
|
39
42
|
# rubocop:disable Metrics/MethodLength
|
40
43
|
def duration(base = :ns, type = :integer)
|
41
|
-
|
44
|
+
# @type ^(::String) -> ::Integer | ::Float
|
45
|
+
->(v) do # rubocop:disable Style/Lambda
|
42
46
|
cast = case type
|
43
47
|
when :integer, Integer
|
44
48
|
method(:Integer)
|
@@ -63,19 +67,19 @@ module Datadog
|
|
63
67
|
|
64
68
|
case v
|
65
69
|
when /^(\d+)h$/
|
66
|
-
cast.call(Regexp.last_match
|
70
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 * 60 * 60 / scale
|
67
71
|
when /^(\d+)m$/
|
68
|
-
cast.call(Regexp.last_match
|
72
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 * 60 / scale
|
69
73
|
when /^(\d+)s$/
|
70
|
-
cast.call(Regexp.last_match
|
74
|
+
cast.call(Regexp.last_match(1)) * 1_000_000_000 / scale
|
71
75
|
when /^(\d+)ms$/
|
72
|
-
cast.call(Regexp.last_match
|
76
|
+
cast.call(Regexp.last_match(1)) * 1_000_000 / scale
|
73
77
|
when /^(\d+)us$/
|
74
|
-
cast.call(Regexp.last_match
|
78
|
+
cast.call(Regexp.last_match(1)) * 1_000 / scale
|
75
79
|
when /^(\d+)ns$/
|
76
|
-
cast.call(Regexp.last_match
|
80
|
+
cast.call(Regexp.last_match(1)) / scale
|
77
81
|
when /^(\d+)$/
|
78
|
-
cast.call(Regexp.last_match
|
82
|
+
cast.call(Regexp.last_match(1))
|
79
83
|
else
|
80
84
|
raise ArgumentError, "invalid duration: #{v.inspect}"
|
81
85
|
end
|
@@ -109,7 +113,8 @@ module Datadog
|
|
109
113
|
'DD_APPSEC_OBFUSCATION_PARAMETER_VALUE_REGEXP' => [:obfuscator_value_regex, Settings.string],
|
110
114
|
}.freeze
|
111
115
|
|
112
|
-
|
116
|
+
# Struct constant whisker cast for Steep
|
117
|
+
Integration = _ = Struct.new(:integration, :options) # rubocop:disable Naming/ConstantName
|
113
118
|
|
114
119
|
def initialize
|
115
120
|
@integrations = []
|
@@ -121,37 +126,45 @@ module Datadog
|
|
121
126
|
end
|
122
127
|
|
123
128
|
def enabled
|
124
|
-
|
129
|
+
# Cast for Steep
|
130
|
+
_ = @options[:enabled]
|
125
131
|
end
|
126
132
|
|
127
133
|
def ruleset
|
128
|
-
|
134
|
+
# Cast for Steep
|
135
|
+
_ = @options[:ruleset]
|
129
136
|
end
|
130
137
|
|
131
138
|
# EXPERIMENTAL: This configurable is not meant to be publicly used, but
|
132
139
|
# is very useful for testing. It may change at any point in time.
|
133
140
|
def ip_denylist
|
134
|
-
|
141
|
+
# Cast for Steep
|
142
|
+
_ = @options[:ip_denylist]
|
135
143
|
end
|
136
144
|
|
137
145
|
def waf_timeout
|
138
|
-
|
146
|
+
# Cast for Steep
|
147
|
+
_ = @options[:waf_timeout]
|
139
148
|
end
|
140
149
|
|
141
150
|
def waf_debug
|
142
|
-
|
151
|
+
# Cast for Steep
|
152
|
+
_ = @options[:waf_debug]
|
143
153
|
end
|
144
154
|
|
145
155
|
def trace_rate_limit
|
146
|
-
|
156
|
+
# Cast for Steep
|
157
|
+
_ = @options[:trace_rate_limit]
|
147
158
|
end
|
148
159
|
|
149
160
|
def obfuscator_key_regex
|
150
|
-
|
161
|
+
# Cast for Steep
|
162
|
+
_ = @options[:obfuscator_key_regex]
|
151
163
|
end
|
152
164
|
|
153
165
|
def obfuscator_value_regex
|
154
|
-
|
166
|
+
# Cast for Steep
|
167
|
+
_ = @options[:obfuscator_value_regex]
|
155
168
|
end
|
156
169
|
|
157
170
|
def [](integration_name)
|
@@ -159,7 +172,7 @@ module Datadog
|
|
159
172
|
|
160
173
|
raise ArgumentError, "'#{integration_name}' is not a valid integration." unless integration
|
161
174
|
|
162
|
-
integration.options
|
175
|
+
integration.options
|
163
176
|
end
|
164
177
|
|
165
178
|
def merge(dsl)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
require_relative 'configuration/settings'
|
4
4
|
|
@@ -14,7 +14,9 @@ module Datadog
|
|
14
14
|
|
15
15
|
# Configuration DSL implementation
|
16
16
|
class DSL
|
17
|
-
|
17
|
+
# Struct constant whisker cast for Steep
|
18
|
+
Instrument = _ = Struct.new(:name, :options) # rubocop:disable Naming/ConstantName
|
19
|
+
|
18
20
|
def initialize
|
19
21
|
@instruments = []
|
20
22
|
@options = {}
|
data/lib/datadog/appsec/event.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
require_relative 'configuration'
|
4
4
|
|
@@ -29,21 +29,16 @@ module Datadog
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# Writer methods
|
32
|
-
def trace_rate_limit=(arg)
|
33
|
-
dsl = AppSec::Configuration::DSL.new
|
34
|
-
dsl.trace_rate_limit = arg
|
35
|
-
@settings.merge(dsl)
|
36
|
-
end
|
37
32
|
|
38
|
-
def options
|
33
|
+
def instrument(name, options = {})
|
39
34
|
dsl = AppSec::Configuration::DSL.new
|
40
|
-
dsl.options
|
35
|
+
dsl.instrument(name, options)
|
41
36
|
@settings.merge(dsl)
|
42
37
|
end
|
43
38
|
|
44
|
-
def
|
39
|
+
def enabled=(arg)
|
45
40
|
dsl = AppSec::Configuration::DSL.new
|
46
|
-
dsl.
|
41
|
+
dsl.enabled = arg
|
47
42
|
@settings.merge(dsl)
|
48
43
|
end
|
49
44
|
|
@@ -59,51 +54,58 @@ module Datadog
|
|
59
54
|
@settings.merge(dsl)
|
60
55
|
end
|
61
56
|
|
62
|
-
def
|
57
|
+
def waf_timeout=(arg)
|
63
58
|
dsl = AppSec::Configuration::DSL.new
|
64
|
-
dsl.
|
59
|
+
dsl.waf_timeout = arg
|
65
60
|
@settings.merge(dsl)
|
66
61
|
end
|
67
62
|
|
68
|
-
def
|
63
|
+
def waf_debug=(arg)
|
69
64
|
dsl = AppSec::Configuration::DSL.new
|
70
|
-
dsl.
|
65
|
+
dsl.waf_debug = arg
|
71
66
|
@settings.merge(dsl)
|
72
67
|
end
|
73
68
|
|
74
|
-
def
|
69
|
+
def trace_rate_limit=(arg)
|
75
70
|
dsl = AppSec::Configuration::DSL.new
|
76
|
-
dsl.
|
71
|
+
dsl.trace_rate_limit = arg
|
77
72
|
@settings.merge(dsl)
|
78
73
|
end
|
79
74
|
|
80
|
-
def
|
75
|
+
def obfuscator_key_regex=(arg)
|
81
76
|
dsl = AppSec::Configuration::DSL.new
|
82
|
-
dsl.
|
77
|
+
dsl.obfuscator_key_regex = arg
|
78
|
+
@settings.merge(dsl)
|
79
|
+
end
|
80
|
+
|
81
|
+
def obfuscator_value_regex=(arg)
|
82
|
+
dsl = AppSec::Configuration::DSL.new
|
83
|
+
dsl.obfuscator_value_regex = arg
|
83
84
|
@settings.merge(dsl)
|
84
85
|
end
|
85
86
|
|
86
87
|
# Reader methods
|
87
|
-
|
88
|
-
|
88
|
+
|
89
|
+
def [](key)
|
90
|
+
@settings[key]
|
91
|
+
end
|
92
|
+
|
93
|
+
def enabled
|
94
|
+
@settings.enabled
|
89
95
|
end
|
90
96
|
|
91
97
|
def ruleset
|
92
98
|
@settings.ruleset
|
93
99
|
end
|
94
100
|
|
95
|
-
def
|
96
|
-
@settings.
|
101
|
+
def ip_denylist
|
102
|
+
@settings.ip_denylist
|
97
103
|
end
|
98
104
|
|
99
105
|
def waf_timeout
|
100
106
|
@settings.waf_timeout
|
101
107
|
end
|
102
108
|
|
103
|
-
def enabled
|
104
|
-
@settings.enabled
|
105
|
-
end
|
106
|
-
|
107
109
|
def waf_debug
|
108
110
|
@settings.waf_debug
|
109
111
|
end
|
@@ -112,6 +114,14 @@ module Datadog
|
|
112
114
|
@settings.trace_rate_limit
|
113
115
|
end
|
114
116
|
|
117
|
+
def obfuscator_key_regex
|
118
|
+
@settings.obfuscator_key_regex
|
119
|
+
end
|
120
|
+
|
121
|
+
def obfuscator_value_regex
|
122
|
+
@settings.obfuscator_key_regex
|
123
|
+
end
|
124
|
+
|
115
125
|
def merge(arg)
|
116
126
|
@settings.merge(arg)
|
117
127
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
module Datadog
|
4
4
|
module AppSec
|
@@ -15,8 +15,8 @@ module Datadog
|
|
15
15
|
@block = block
|
16
16
|
end
|
17
17
|
|
18
|
-
def call(
|
19
|
-
@block.call(
|
18
|
+
def call(stack, env)
|
19
|
+
@block.call(stack, env)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -6,16 +6,6 @@ module Datadog
|
|
6
6
|
module AppSec
|
7
7
|
# Processor integrates libddwaf into datadog/appsec
|
8
8
|
class Processor
|
9
|
-
# Interface object to check using case .. when
|
10
|
-
module IOLike
|
11
|
-
def read; end
|
12
|
-
def rewind; end
|
13
|
-
|
14
|
-
def self.===(other)
|
15
|
-
instance_methods.all? { |meth| other.respond_to?(meth) }
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
9
|
# Context manages a sequence of runs
|
20
10
|
class Context
|
21
11
|
attr_reader :time_ns, :time_ext_ns, :timeouts, :events
|
@@ -28,10 +18,12 @@ module Datadog
|
|
28
18
|
@events = []
|
29
19
|
end
|
30
20
|
|
31
|
-
def run(
|
21
|
+
def run(input, timeout = WAF::LibDDWAF::DDWAF_RUN_TIMEOUT)
|
32
22
|
start_ns = Core::Utils::Time.get_time(:nanosecond)
|
33
23
|
|
34
|
-
|
24
|
+
# TODO: remove multiple assignment
|
25
|
+
_code, res = _ = @context.run(input, timeout)
|
26
|
+
# @type var res: WAF::Result
|
35
27
|
|
36
28
|
stop_ns = Core::Utils::Time.get_time(:nanosecond)
|
37
29
|
|
@@ -50,10 +42,8 @@ module Datadog
|
|
50
42
|
attr_reader :ruleset_info, :addresses
|
51
43
|
|
52
44
|
def initialize
|
53
|
-
@ruleset = nil
|
54
|
-
@handle = nil
|
55
45
|
@ruleset_info = nil
|
56
|
-
@addresses =
|
46
|
+
@addresses = []
|
57
47
|
|
58
48
|
unless load_libddwaf && load_ruleset && create_waf_handle
|
59
49
|
Datadog.logger.warn { 'AppSec is disabled, see logged errors above' }
|
@@ -117,8 +107,8 @@ module Datadog
|
|
117
107
|
JSON.parse(Datadog::AppSec::Assets.waf_rules(ruleset_setting))
|
118
108
|
when String
|
119
109
|
JSON.parse(File.read(ruleset_setting))
|
120
|
-
when
|
121
|
-
JSON.parse(ruleset_setting.read).tap { ruleset_setting.rewind }
|
110
|
+
when File, StringIO
|
111
|
+
JSON.parse(ruleset_setting.read || '').tap { ruleset_setting.rewind }
|
122
112
|
when Hash
|
123
113
|
ruleset_setting
|
124
114
|
else
|
@@ -148,12 +138,18 @@ module Datadog
|
|
148
138
|
@addresses = @handle.required_addresses
|
149
139
|
|
150
140
|
true
|
151
|
-
rescue
|
141
|
+
rescue WAF::LibDDWAF::Error => e
|
152
142
|
Datadog.logger.error do
|
153
143
|
"libddwaf failed to initialize, error: #{e.inspect}"
|
154
144
|
end
|
155
145
|
|
156
|
-
@ruleset_info = e.ruleset_info if e.
|
146
|
+
@ruleset_info = e.ruleset_info if e.ruleset_info
|
147
|
+
|
148
|
+
false
|
149
|
+
rescue StandardError => e
|
150
|
+
Datadog.logger.error do
|
151
|
+
"libddwaf failed to initialize, error: #{e.inspect}"
|
152
|
+
end
|
157
153
|
|
158
154
|
false
|
159
155
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
require_relative 'engine'
|
4
4
|
|
@@ -15,7 +15,7 @@ module Datadog
|
|
15
15
|
Datadog.logger.debug { "operation: #{name} initialize" }
|
16
16
|
@name = name
|
17
17
|
@parent = parent
|
18
|
-
@reactive = reactive_engine || parent
|
18
|
+
@reactive = reactive_engine || (parent.reactive unless parent.nil?) || Reactive::Engine.new
|
19
19
|
|
20
20
|
# TODO: concurrent store
|
21
21
|
# TODO: constant
|
@@ -1,6 +1,7 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: ignore
|
2
2
|
|
3
3
|
require_relative 'assets'
|
4
|
+
require_relative 'utils/http/media_range'
|
4
5
|
|
5
6
|
module Datadog
|
6
7
|
module AppSec
|
@@ -37,16 +38,24 @@ module Datadog
|
|
37
38
|
|
38
39
|
private
|
39
40
|
|
41
|
+
FORMAT_MAP = {
|
42
|
+
'text/html' => :html,
|
43
|
+
'application/json' => :json,
|
44
|
+
'text/plain' => :text,
|
45
|
+
}.freeze
|
46
|
+
|
47
|
+
DEFAULT_FORMAT = :text
|
48
|
+
|
40
49
|
def format(env)
|
41
|
-
|
42
|
-
if accept.start_with?('text/html')
|
43
|
-
break :html
|
44
|
-
elsif accept.start_with?('application/json')
|
45
|
-
break :json
|
46
|
-
end
|
47
|
-
end
|
50
|
+
return DEFAULT_FORMAT unless env.key?('HTTP_ACCEPT')
|
48
51
|
|
49
|
-
|
52
|
+
accepted = env['HTTP_ACCEPT'].split(',').map { |m| Utils::HTTP::MediaRange.new(m) }.sort
|
53
|
+
|
54
|
+
accepted.each_with_object(DEFAULT_FORMAT) do |_default, range|
|
55
|
+
format = FORMAT_MAP.keys.find { |type, _format| range === type }
|
56
|
+
|
57
|
+
return FORMAT_MAP[format] if format
|
58
|
+
end
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|