|
| 1 | +# frozen_string_literal: true |
| 2 | + |
| 3 | +require_relative '../feed_response_format' |
| 4 | +require_relative '../feeds/json_renderer' |
| 5 | +require_relative '../feeds/request_parser' |
| 6 | +require_relative '../feeds/resolver' |
| 7 | +require_relative '../feeds/rss_renderer' |
| 8 | +require_relative '../feeds/service' |
| 9 | +require_relative '../http_cache' |
| 10 | + |
| 11 | +module Html2rss |
| 12 | + module Web |
| 13 | + module Http |
| 14 | + ## |
| 15 | + # Renders static feed requests through the shared feed pipeline. |
| 16 | + module FeedRouteHandler |
| 17 | + class << self |
| 18 | + # @param context [Html2rss::Web::AppContext::Context] |
| 19 | + # @param router [Roda::RodaRequest] |
| 20 | + # @param feed_name [String] |
| 21 | + # @return [String] |
| 22 | + def call(context:, router:, feed_name:) |
| 23 | + feed_request = Feeds::RequestParser.call(request: router, target_kind: :static, identifier: feed_name) |
| 24 | + resolved_source = Feeds::Resolver.call(feed_request) |
| 25 | + result = Feeds::Service.call(resolved_source) |
| 26 | + |
| 27 | + raise InternalServerError, result.message if result.status == :error |
| 28 | + |
| 29 | + emit_success(context, feed_name, resolved_source.generator_input[:strategy]) |
| 30 | + configure_response(router, result.ttl_seconds, feed_request.representation) |
| 31 | + render_result(result, feed_request.representation) |
| 32 | + rescue StandardError => error |
| 33 | + emit_failure(context, feed_name, error) |
| 34 | + raise |
| 35 | + end |
| 36 | + |
| 37 | + private |
| 38 | + |
| 39 | + # @param context [Html2rss::Web::AppContext::Context] |
| 40 | + # @param feed_name [String] |
| 41 | + # @param strategy [String, nil] |
| 42 | + # @return [void] |
| 43 | + def emit_success(context, feed_name, strategy) |
| 44 | + context.observability.emit( |
| 45 | + event_name: 'feed.render', |
| 46 | + outcome: 'success', |
| 47 | + details: { feed_name: feed_name, strategy: strategy }, |
| 48 | + level: :info |
| 49 | + ) |
| 50 | + end |
| 51 | + |
| 52 | + # @param context [Html2rss::Web::AppContext::Context] |
| 53 | + # @param feed_name [String] |
| 54 | + # @param error [StandardError] |
| 55 | + # @return [void] |
| 56 | + def emit_failure(context, feed_name, error) |
| 57 | + context.observability.emit( |
| 58 | + event_name: 'feed.render', |
| 59 | + outcome: 'failure', |
| 60 | + details: { feed_name: feed_name, error_class: error.class.name, error_message: error.message }, |
| 61 | + level: :warn |
| 62 | + ) |
| 63 | + end |
| 64 | + |
| 65 | + # @param result [Html2rss::Web::Feeds::Result] |
| 66 | + # @param format [Symbol] |
| 67 | + # @return [String] |
| 68 | + def render_result(result, format) |
| 69 | + return Feeds::JsonRenderer.call(result) if format == Feeds::ResponseFormat::JSON_FEED |
| 70 | + |
| 71 | + Feeds::RssRenderer.call(result) |
| 72 | + end |
| 73 | + |
| 74 | + # @param router [Roda::RodaRequest] |
| 75 | + # @param ttl_seconds [Integer] |
| 76 | + # @param format [Symbol] |
| 77 | + # @return [void] |
| 78 | + def configure_response(router, ttl_seconds, format) |
| 79 | + router.response['Content-Type'] = FeedResponseFormat.content_type(format) |
| 80 | + HttpCache.expires(router.response, ttl_seconds, cache_control: 'public') |
| 81 | + HttpCache.vary(router.response, 'Accept') |
| 82 | + end |
| 83 | + end |
| 84 | + end |
| 85 | + end |
| 86 | + end |
| 87 | +end |
0 commit comments