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
|
class ApplicationController < ActionController::Base
protect_from_forgery
before_action :check_mime_types
before_filter :set_locale
before_filter :no_cache_header
before_filter :no_frame_header
before_filter :language_header
rescue_from StandardError, :with => :default_error_handler
rescue_from CouchRest::Exception, :with => :default_error_handler
ActiveSupport.run_load_hooks(:application_controller, self)
# by default we only respond to html.
# If you want to respond with json you are probably working on
# an ApiController.
respond_to :html
protected
# UPGRADE: this won't be needed in Rails 5 anymore as it's the default
# behavior if a template is present but a different format would be
# rendered and that template is not present
def check_mime_types
mimes = collect_mimes_from_class_level()
return if mimes.empty?
collector = ActionController::MimeResponds::Collector.new(mimes, request.variant)
unless collector.negotiate_format(request)
raise ActionController::UnknownFormat
end
end
def default_error_handler(exc)
respond_to do |format|
format.json { render_json_error(exc) }
format.all { raise exc } # reraise the exception so the normal thing happens.
end
end
#
# I think this should be 'errors', not 'error', since that is what
# `respond_with @object` will return. For now, I am leaving this as 'error',
# since there is some code that depends on this.
#
def render_json_error(e)
Rails.logger.error e
Rails.logger.error e.backtrace.join("\n")
if e.is_a?(CouchRest::StorageMissing)
render status: 500, json: {error: "The database '#{e.db}' does not exist!"}
else
render status: 500, json: {error: "The server failed to process your request. We'll look into it (#{e.class})."}
end
end
##
## LOCALE
##
#
# Before filter to set the current locale. Possible outcomes:
#
# (a) do nothing for certain routes and requests.
# (b) if path already starts with locale, set I18n.locale and default_url_options.
# (c) otherwise, redirect so that path starts with locale.
#
def set_locale
if request_may_have_locale?(request)
if CommonLanguages::available_code?(params[:locale])
I18n.locale = params[:locale]
else
I18n.locale = http_accept_language.compatible_language_from(I18n.available_locales) || I18n.default_locale
if I18n.locale != I18n.default_locale
redirect_to url_for(params.merge(:locale => I18n.locale))
end
end
end
end
def default_url_options(options={})
if request_may_have_locale?(request) && I18n.locale != I18n.default_locale
{ :locale => I18n.locale }
else
{ :locale => nil }
end
end
##
## HTTP HEADERS
## These are in individual helpers so that controllers can disable them if needed.
##
#
# Not necessary, but kind to let the browser know the current locale.
#
def language_header
response.headers["Content-Language"] = I18n.locale.to_s
end
#
# prevent app from being embedded in an iframe, for browsers that support x-frame-options.
#
def no_frame_header
response.headers["X-Frame-Options"] = "DENY"
end
#
# we want to prevent the browser from caching anything, just to be safe.
#
def no_cache_header
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
end
private
#
# URL paths for which we don't enforce the locale as the prefix of the path.
#
NON_LOCALE_PATHS = /^\/(assets|webfinger|.well-known|rails|key|[0-9]+)($|\/)/
#
# For some requests, we ignore locale determination.
#
def request_may_have_locale?(request)
request.path !~ NON_LOCALE_PATHS
end
end
|