-
-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathapp.rb
More file actions
138 lines (123 loc) · 4.21 KB
/
app.rb
File metadata and controls
138 lines (123 loc) · 4.21 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
135
136
137
138
# frozen_string_literal: true
require 'roda'
require 'rack/cache'
require 'json'
require 'base64'
require 'html2rss'
require_relative 'app/web/boot'
Html2rss::Web::Boot.setup!(reloadable: ENV['RACK_ENV'] == 'development')
Html2rss::Web::Boot::Setup.call!
module Html2rss
module Web
DEFAULT_HEADERS = {
'X-Content-Type-Options' => 'nosniff',
'X-XSS-Protection' => '1; mode=block',
'X-Frame-Options' => 'SAMEORIGIN',
'X-Permitted-Cross-Domain-Policies' => 'none',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Permissions-Policy' => 'geolocation=(), microphone=(), camera=()',
'Strict-Transport-Security' => 'max-age=31536000; includeSubDomains; preload',
'Cross-Origin-Embedder-Policy' => 'require-corp',
'Cross-Origin-Opener-Policy' => 'same-origin',
'Cross-Origin-Resource-Policy' => 'same-origin',
'X-DNS-Prefetch-Control' => 'off',
'X-Download-Options' => 'noopen'
}.freeze
##
# Roda app serving RSS feeds via html2rss
class App < Roda
FALLBACK_HTML = <<~HTML
<!DOCTYPE html>
<html>
<head>
<title>html2rss-web</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
</head>
<body>
<h1>html2rss-web</h1>
<p>Convert websites to RSS feeds</p>
<p>API available at <a href="/api/v1"><code>/api/v1</code></a></p>
</body>
</html>
HTML
FRONTEND_DIST_PATH = 'frontend/dist'
FRONTEND_INDEX_PATH = File.join(FRONTEND_DIST_PATH, 'index.html')
def self.development? = EnvironmentValidator.development?
def development? = self.class.development?
opts.merge!(check_dynamic_arity: false, check_arity: :warn)
use RequestContextMiddleware
use Rack::Cache, metastore: 'file:./tmp/rack-cache-meta', entitystore: 'file:./tmp/rack-cache-body',
verbose: development?
# rubocop:disable Metrics/BlockLength
plugin :content_security_policy do |csp|
csp.default_src :none
if development?
csp.style_src :self, "'unsafe-inline'"
else
csp.style_src :self
end
csp.script_src :self
csp.connect_src :self
csp.img_src :self
csp.font_src :self
csp.form_action :self
csp.base_uri :none
if development?
csp.frame_ancestors 'http://localhost:*', 'https://localhost:*',
'http://127.0.0.1:*', 'https://127.0.0.1:*'
else
csp.frame_ancestors :none
end
csp.frame_src :self
csp.object_src :none
csp.media_src :none
csp.manifest_src :none
csp.worker_src :none
csp.child_src :none
csp.block_all_mixed_content
csp.upgrade_insecure_requests
end
# rubocop:enable Metrics/BlockLength
plugin :default_headers, DEFAULT_HEADERS
plugin :json_parser
plugin :static,
['/assets'],
root: FRONTEND_DIST_PATH,
headers: { 'Cache-Control' => 'public, max-age=31536000, immutable' }
plugin :public
plugin :head
plugin :not_allowed
plugin :exception_page
plugin :error_handler do |error|
next exception_page(error) if development?
ErrorResponder.respond(request: request, response: response, error: error)
end
route do |r|
r.public
r.root do
if development?
render_development_api_landing(r)
else
render_index_page(r)
end
end
Routes::ApiV1.call(r) ||
Routes::FeedPages.call(
r,
index_renderer: ->(router_ctx) { render_index_page(router_ctx) },
serve_spa: !development?
)
end
private
def render_index_page(router)
router.response['Content-Type'] = 'text/html'
File.exist?(FRONTEND_INDEX_PATH) ? File.read(FRONTEND_INDEX_PATH) : FALLBACK_HTML
end
def render_development_api_landing(router)
router.response['Content-Type'] = 'text/html'
DevelopmentLandingPage::HTML
end
end
end
end