-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathresponder.rb
More file actions
134 lines (118 loc) · 5.58 KB
/
responder.rb
File metadata and controls
134 lines (118 loc) · 5.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true
module Html2rss
module Web
module Feeds
##
# Resolves, renders, and writes feed responses for both token and legacy routes.
module Responder
class << self
# @param request [Rack::Request]
# @param target_kind [Symbol]
# @param identifier [String]
# @return [String] serialized feed body.
def call(request:, target_kind:, identifier:)
feed_request, resolved_source, result = resolve_request(request:, target_kind:, identifier:)
body = write_response(response: request.response, representation: feed_request.representation, result:)
emit_response_result(target_kind:, identifier:, feed_request:, resolved_source:, result:)
body
rescue StandardError => error
emit_failure(target_kind:, identifier:, error:)
raise
end
private
# @param request [Rack::Request]
# @param target_kind [Symbol]
# @param identifier [String]
# @return [Array<(Html2rss::Web::Feeds::Contracts::Request, Html2rss::Web::Feeds::Contracts::ResolvedSource, Html2rss::Web::Feeds::Contracts::RenderResult)>]
def resolve_request(request:, target_kind:, identifier:)
feed_request = Request.call(request:, target_kind:, identifier:)
resolved_source = SourceResolver.call(feed_request)
result = Service.call(resolved_source)
[feed_request, resolved_source, result]
end
# @param feed_request [Html2rss::Web::Feeds::Contracts::Request]
# @param identifier [String]
# @return [String]
def normalized_identifier(feed_request, identifier)
feed_request.feed_name || identifier
end
# @param target_kind [Symbol]
# @param identifier [String]
# @param feed_request [Html2rss::Web::Feeds::Contracts::Request]
# @param resolved_source [Html2rss::Web::Feeds::Contracts::ResolvedSource]
# @param result [Html2rss::Web::Feeds::Contracts::RenderResult]
# @return [void]
def emit_response_result(target_kind:, identifier:, feed_request:, resolved_source:, result:)
emit_result(
target_kind:,
identifier: normalized_identifier(feed_request, identifier),
resolved_source:,
result:
)
end
# @param response [Rack::Response]
# @param representation [Symbol]
# @param result [Html2rss::Web::Feeds::Contracts::RenderResult]
# @return [String]
def write_response(response:, representation:, result:)
response.status = result.status == :error ? 500 : 200
response['Content-Type'] = FeedResponseFormat.content_type(representation)
apply_cache_headers(response, result)
::Html2rss::Web::HttpCache.vary(response, 'Accept')
render_result(result, representation)
end
# @param response [Rack::Response]
# @param result [Html2rss::Web::Feeds::Contracts::RenderResult]
# @return [void]
def apply_cache_headers(response, result)
return ::Html2rss::Web::HttpCache.expires_now(response) if result.status == :error
::Html2rss::Web::HttpCache.expires(response, result.ttl_seconds, cache_control: 'public')
end
# @param result [Html2rss::Web::Feeds::Contracts::RenderResult]
# @param representation [Symbol]
# @return [String]
def render_result(result, representation)
return JsonRenderer.call(result) if representation == FeedResponseFormat::JSON_FEED
RssRenderer.call(result)
end
# @param target_kind [Symbol]
# @param identifier [String]
# @param resolved_source [Html2rss::Web::Feeds::Contracts::ResolvedSource]
# @param result [Html2rss::Web::Feeds::Contracts::RenderResult]
# @return [void]
def emit_result(target_kind:, identifier:, resolved_source:, result:)
return emit_success(target_kind:, identifier:, resolved_source:) unless result.status == :error
emit_failure(
target_kind:,
identifier:,
error: Html2rss::Web::InternalServerError.new(
result.error_message || result.message || Html2rss::Web::HttpError::DEFAULT_MESSAGE
)
)
end
# @param target_kind [Symbol]
# @param identifier [String]
# @param resolved_source [Html2rss::Web::Feeds::Contracts::ResolvedSource]
# @return [void]
def emit_success(target_kind:, identifier:, resolved_source:)
details = {
strategy: resolved_source.generator_input[:strategy],
url: resolved_source.generator_input.dig(:channel, :url)
}
details[:feed_name] = identifier if target_kind == :static
Observability.emit(event_name: 'feed.render', outcome: 'success', details:, level: :info)
end
# @param target_kind [Symbol]
# @param identifier [String]
# @param error [StandardError]
# @return [void]
def emit_failure(target_kind:, identifier:, error:)
details = { error_class: error.class.name, error_message: error.message }
details[:feed_name] = identifier if target_kind == :static
Observability.emit(event_name: 'feed.render', outcome: 'failure', details:, level: :warn)
end
end
end
end
end
end