forked from stripe-samples/accept-a-payment
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowser_compatibility_helper.rb
More file actions
135 lines (122 loc) · 4.19 KB
/
browser_compatibility_helper.rb
File metadata and controls
135 lines (122 loc) · 4.19 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
# frozen_string_literal: true
# Browser Compatibility Helper Module
# Provides cross-browser compatibility utilities for Sinatra applications
module BrowserCompatibilityHelper
# CORS headers for cross-browser support
def self.cors_headers
{
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type, Authorization, X-Requested-With',
'Access-Control-Max-Age' => '86400'
}
end
# Security headers for modern browsers
def self.security_headers
{
'X-Content-Type-Options' => 'nosniff',
'X-Frame-Options' => 'SAMEORIGIN',
'X-XSS-Protection' => '1; mode=block',
'Referrer-Policy' => 'strict-origin-when-cross-origin',
'Content-Security-Policy' => "default-src 'self' https://js.stripe.com https://api.stripe.com; " \
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://js.stripe.com; " \
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " \
"font-src 'self' https://fonts.gstatic.com; " \
"img-src 'self' data: https: blob:; " \
"connect-src 'self' https://api.stripe.com https://js.stripe.com; " \
"frame-src https://js.stripe.com https://hooks.stripe.com;"
}
end
# Cache control headers for static assets
def self.cache_headers(max_age = 3600)
{
'Cache-Control' => "public, max-age=#{max_age}",
'Vary' => 'Accept-Encoding'
}
end
# Proper MIME types for common file extensions
def self.mime_type(filename)
ext = File.extname(filename).downcase
mime_types = {
'.html' => 'text/html; charset=utf-8',
'.css' => 'text/css; charset=utf-8',
'.js' => 'application/javascript; charset=utf-8',
'.json' => 'application/json; charset=utf-8',
'.png' => 'image/png',
'.jpg' => 'image/jpeg',
'.jpeg' => 'image/jpeg',
'.gif' => 'image/gif',
'.svg' => 'image/svg+xml',
'.ico' => 'image/x-icon',
'.woff' => 'font/woff',
'.woff2' => 'font/woff2',
'.ttf' => 'font/ttf',
'.eot' => 'application/vnd.ms-fontobject'
}
mime_types[ext] || 'application/octet-stream'
end
# Detect browser from user agent
def self.detect_browser(user_agent)
return 'unknown' if user_agent.nil? || user_agent.empty?
case user_agent
when /MSIE|Trident/
'ie'
when /Edge/
'edge'
when /Chrome/
'chrome'
when /Safari/
'safari'
when /Firefox/
'firefox'
when /Opera|OPR/
'opera'
else
'unknown'
end
end
# Check if browser needs polyfills
def self.needs_polyfills?(user_agent)
browser = detect_browser(user_agent)
['ie', 'edge'].include?(browser) || user_agent =~ /Safari\/[0-9]{3}\./
end
# Generate browser-specific class for HTML
def self.browser_class(user_agent)
browser = detect_browser(user_agent)
"browser-#{browser}"
end
# Add compatibility headers to response
def self.add_compatibility_headers(response, content_type = nil)
cors_headers.merge(security_headers).each do |key, value|
response[key] = value
end
response['Content-Type'] = content_type if content_type
response
end
end
# Sinatra extension for browser compatibility
module Sinatra
module BrowserCompatibility
def self.registered(app)
# Add before filter to set compatibility headers
app.before do
headers.merge!(BrowserCompatibilityHelper.cors_headers)
headers.merge!(BrowserCompatibilityHelper.security_headers)
end
# Handle OPTIONS requests for CORS preflight
app.options '*' do
headers.merge!(BrowserCompatibilityHelper.cors_headers)
status 200
end
# Override send_file to set proper MIME types
app.helpers do
def send_file_with_mime(path, opts = {})
content_type BrowserCompatibilityHelper.mime_type(path)
headers.merge!(BrowserCompatibilityHelper.cache_headers)
send_file(path, opts)
end
end
end
end
register BrowserCompatibility
end