nekonote-framework 1.0.0.pre.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +49 -0
  4. data/bin/nekonote +45 -0
  5. data/data/structure/Gemfile +25 -0
  6. data/data/structure/config.ru +14 -0
  7. data/data/structure/handler/base.rb +21 -0
  8. data/data/structure/handler/error.rb +35 -0
  9. data/data/structure/handler/welcome.rb +11 -0
  10. data/data/structure/lib/.gitkeep +0 -0
  11. data/data/structure/preference/development/logger.yml +62 -0
  12. data/data/structure/preference/development/middlewares.rb +152 -0
  13. data/data/structure/preference/development/public.yml +29 -0
  14. data/data/structure/preference/development/route.yml +30 -0
  15. data/data/structure/preference/development/route_error.yml +28 -0
  16. data/data/structure/preference/development/route_include.yml +22 -0
  17. data/data/structure/preference/development/server/puma.rb +63 -0
  18. data/data/structure/preference/development/setting/example.yml +40 -0
  19. data/data/structure/preference/development/setting/site.yml +3 -0
  20. data/data/structure/preference/development/setting/welcome.yml +7 -0
  21. data/data/structure/public/css/layout/common.css +11 -0
  22. data/data/structure/public/css/layout/default.css +3 -0
  23. data/data/structure/public/css/layout/error.css +3 -0
  24. data/data/structure/public/css/welcome.css +47 -0
  25. data/data/structure/public/favicon.ico +0 -0
  26. data/data/structure/public/img/.gitkeep +0 -0
  27. data/data/structure/public/img/logo.png +0 -0
  28. data/data/structure/public/js/.gitkeep +0 -0
  29. data/data/structure/static/layout/default.tpl +19 -0
  30. data/data/structure/static/layout/error.tpl +15 -0
  31. data/data/structure/static/sass/welcome.scss +52 -0
  32. data/data/structure/static/template/error.tpl +4 -0
  33. data/data/structure/static/template/welcome/index.tpl +26 -0
  34. data/data/structure/tmp/pids/.gitkeep +0 -0
  35. data/lib/loader.rb +83 -0
  36. data/lib/nekonote.rb +9 -0
  37. data/lib/nekonote/cli.rb +702 -0
  38. data/lib/nekonote/cmd_parser.rb +55 -0
  39. data/lib/nekonote/core.rb +116 -0
  40. data/lib/nekonote/env.rb +56 -0
  41. data/lib/nekonote/exception/cli_error.rb +34 -0
  42. data/lib/nekonote/exception/error.rb +75 -0
  43. data/lib/nekonote/exception/handler_error.rb +5 -0
  44. data/lib/nekonote/exception/logger_error.rb +8 -0
  45. data/lib/nekonote/exception/page_cache_error.rb +6 -0
  46. data/lib/nekonote/exception/preference_error.rb +11 -0
  47. data/lib/nekonote/exception/view_error.rb +7 -0
  48. data/lib/nekonote/handler.rb +274 -0
  49. data/lib/nekonote/handler/protected_methods.rb +119 -0
  50. data/lib/nekonote/liquid/tag_env_get.rb +12 -0
  51. data/lib/nekonote/liquid/tag_setting_get.rb +12 -0
  52. data/lib/nekonote/logger.rb +135 -0
  53. data/lib/nekonote/page_cache.rb +111 -0
  54. data/lib/nekonote/preference.rb +215 -0
  55. data/lib/nekonote/puma.rb +131 -0
  56. data/lib/nekonote/rack/rack_static.rb +17 -0
  57. data/lib/nekonote/rack/rack_static_file.rb +19 -0
  58. data/lib/nekonote/rack/url_mapper.rb +193 -0
  59. data/lib/nekonote/rackup.rb +319 -0
  60. data/lib/nekonote/request.rb +295 -0
  61. data/lib/nekonote/setting.rb +59 -0
  62. data/lib/nekonote/spec.rb +22 -0
  63. data/lib/nekonote/util/filer.rb +69 -0
  64. data/lib/nekonote/util/process.rb +43 -0
  65. data/lib/nekonote/view.rb +398 -0
  66. data/lib/nekonote/yaml_access.rb +60 -0
  67. metadata +144 -0
@@ -0,0 +1,119 @@
1
+ # protected methods for conclete handlers
2
+ module Nekonote
3
+ class Handler
4
+ module ProtectedMethods
5
+ # assign variables into tempate and layout
6
+ # @param hash list
7
+ # @throw ::Nekonote::Error
8
+ protected
9
+ def __assign(list)
10
+ @view.assign_variables list
11
+ end
12
+
13
+ # @param type string|symbol
14
+ protected
15
+ def __set_content_type(type)
16
+ @view.set_content_type type
17
+ end
18
+
19
+ # @param string|symbol subject
20
+ # @param mixed value
21
+ protected
22
+ def __set_header(subject, value)
23
+ @view.set_header(subject, value)
24
+ end
25
+
26
+ # @param hash headers
27
+ protected
28
+ def __set_headers(headers)
29
+ raise HandlerError, HandlerError::MSG_WRONG_TYPE%[headers.class, 'Hash'] if !headers.is_a?(Hash)
30
+ headers.each_pair do |key, val|
31
+ @view.set_header(key, val)
32
+ end
33
+ end
34
+
35
+ # @param string|symbol subject
36
+ # @param mixed value
37
+ # @param string delimiter
38
+ protected
39
+ def __add_header(subject, value, delimiter = '; ')
40
+ @view.add_header subject, value, delimiter
41
+ end
42
+
43
+ # @param int code
44
+ protected
45
+ def __set_code(code)
46
+ @view.set_code code
47
+ end
48
+
49
+ # @param string body
50
+ protected
51
+ def __set_body(body)
52
+ @view.set_body body
53
+ end
54
+
55
+ # @param string body
56
+ protected
57
+ def __add_body(body)
58
+ @view.add_body body
59
+ end
60
+
61
+ # @param hash body
62
+ protected
63
+ def __set_json_body(body)
64
+ raise HandlerError, HandlerError::MSG_WRONG_TYPE%[body.class, 'Hash'] if !body.is_a?(Hash)
65
+ require 'json' if !defined? JSON
66
+ __set_body JSON.pretty_generate(body)
67
+ end
68
+
69
+ # Get values in a specified field(s).
70
+ # @param string|synbol fields you can set plual arguments like field1, field2, field3, ...
71
+ # @return mixed|nil in the case of that missing specified key or missing fields will return nil
72
+ protected
73
+ def __setting_get(*fields)
74
+ return Nekonote::Setting.get fields
75
+ end
76
+
77
+ # @return array
78
+ protected
79
+ def __setting_keys
80
+ return Nekonote::Setting.keys
81
+ end
82
+
83
+ # Get values in a specified field
84
+ # @param string|synbol|nil field
85
+ # @return mixed|nil in the case of that missing specified key or missing fields will return nil
86
+ protected
87
+ def __env_get(field = nil)
88
+ return Nekonote::Env.get field
89
+ end
90
+
91
+ # @return array
92
+ protected
93
+ def __env_keys
94
+ return Nekonote::Env.keys
95
+ end
96
+
97
+
98
+ # @param string dest
99
+ # @param int code
100
+ protected
101
+ def __redirect(dest, code=302)
102
+ # validation for types
103
+ raise HandlerError, HandlerError::MSG_WRONG_TYPE%[dest.class, 'String'] if !dest.is_a?(String)
104
+ if !code.is_a?(Fixnum)
105
+ begin
106
+ code = code.to_i
107
+ rescue
108
+ raise HandlerError, HandlerError::MSG_WRONG_TYPE%[code.class, 'Fixnum or convertible types into Fixnum']
109
+ end
110
+ end
111
+
112
+ # set redirect information
113
+ __set_code code
114
+ __set_header 'Location', dest
115
+ @view.is_redirect = true
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,12 @@
1
+ module Nekonote
2
+ class TagEnvGet < Liquid::Tag
3
+ def initialize(tag_name, val, parse_context)
4
+ super
5
+ @val = val.strip
6
+ end
7
+
8
+ def render(context)
9
+ return Env.get @val
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Nekonote
2
+ class TagSettingGet < Liquid::Tag
3
+ def initialize(tag_name, val, parse_context)
4
+ super
5
+ @val = val.strip.split ','
6
+ end
7
+
8
+ def render(context)
9
+ return Nekonote::Setting.get @val
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,135 @@
1
+ module Nekonote
2
+ class Logger
3
+ include Singleton
4
+ DEBUG = 0
5
+ INFO = 1
6
+ WARN = 2
7
+ ERROR = 3
8
+ FATAL = 4
9
+
10
+ public
11
+ def init(pref)
12
+ logf = pref['logfile']%Nekonote.get_env
13
+ limit = pref['limit']
14
+ keep = pref['keep'].to_i
15
+
16
+ if logf == nil || limit == nil || keep == nil
17
+ raise LoggerError, LoggerError::MSG_MISSING_LOGFILE
18
+ end
19
+
20
+ if !logf.start_with? '/'
21
+ # when log file path is relative
22
+ logf = Nekonote.get_root_path + logf
23
+ end
24
+
25
+ # initialize logger
26
+ @logger = SimpleRotate.instance
27
+ set_optional pref
28
+ begin
29
+ @logger.init logf, limit, keep
30
+ rescue
31
+ msg = $/ + Error::SPACE + "Logger definitions are: logfile = #{logf}, limit = #{limit}, keep = #{keep}"
32
+ raise LoggerError, LoggerError::MSG_FAILED_INITIALIZE%[ENV['USER'], logf] + msg
33
+ end
34
+
35
+ # set default log level
36
+ @default_log_level = get_log_level_by_name pref['default_log_level']
37
+ switch_level @default_log_level
38
+ end
39
+
40
+ # @param mixed msg
41
+ public
42
+ def write(msg, level = nil)
43
+ if level != nil
44
+ switch_level level
45
+ end
46
+ @logger << msg
47
+ end
48
+
49
+ public
50
+ def set_level_default
51
+ switch_level @default_log_level
52
+ end
53
+
54
+ # @param string log_level_name
55
+ private
56
+ def get_log_level_by_name(log_level_name)
57
+ case log_level_name
58
+ when 'debug'
59
+ level = DEBUG
60
+ when 'info'
61
+ level = INFO
62
+ when 'warn'
63
+ level = WARN
64
+ when 'error'
65
+ level = ERROR
66
+ when 'fatal'
67
+ level = FATAL
68
+ else
69
+ # set default level for missing or unknown value is given
70
+ level = INFO
71
+ end
72
+ return level
73
+ end
74
+
75
+ # @param int level
76
+ private
77
+ def switch_level(level)
78
+ case level
79
+ when DEBUG
80
+ @logger.debug
81
+ when INFO
82
+ @logger.info
83
+ when WARN
84
+ @logger.warn
85
+ when ERROR
86
+ @logger.error
87
+ when FATAL
88
+ @logger.fatal
89
+ else
90
+ raise LoggerError. LoggerError::MSG_UNDIFINED_LOG_LEVEL
91
+ end
92
+ end
93
+
94
+ # set optional preferences to @logger
95
+ # @param array pref
96
+ private
97
+ def set_optional(pref)
98
+ begin
99
+ @logger.logging_format = pref['format']['log']
100
+ @logger.date_format = pref['format']['datetime']
101
+ @logger.threshold = pref['threshold'].upcase
102
+ @logger.sleep_time = pref['sleeptime']
103
+
104
+ if pref['compress']['enabled'] == true
105
+ @logger.compress_level pref['compress']['level']
106
+ end
107
+
108
+ if pref['with_stdout'] == true
109
+ @logger.with_stdout
110
+ end
111
+
112
+ if pref['verbose'] == false
113
+ @logger.silence
114
+ end
115
+
116
+ if pref['psync'] == true
117
+ @logger.psync
118
+ end
119
+
120
+ if pref['flush'] == true
121
+ @logger.enable_wflush
122
+ end
123
+
124
+ rescue
125
+ raise LoggerError, LoggerError::MSG_FAILED_DEF_OPT
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ # @param mixed msg
132
+ # @param int level
133
+ def logwrite(msg, level = nil)
134
+ Nekonote::Logger.instance.write msg, level
135
+ end
@@ -0,0 +1,111 @@
1
+ module Nekonote
2
+ class PageCache
3
+ include Singleton
4
+ CACHE_DIR = 'cache'
5
+
6
+ def initialize
7
+ @cache_path = Nekonote.get_root_path + CACHE_DIR
8
+
9
+ # check the accessibility
10
+ if !Util::Filer.available_dir? @cache_path
11
+ raise PageCacheError, PageCacheError::MSG_CHACHE_DIR_WRONG_PERMIT% @cache_path
12
+ end
13
+ end
14
+
15
+ # @return bool
16
+ public
17
+ def cache_clear
18
+ files = Dir.glob("#{@cache_path}/*")
19
+ if files.size > 0
20
+ deleted = true
21
+ else
22
+ deleted = false
23
+ end
24
+
25
+ begin
26
+ files.each do |full_path|
27
+ File.delete full_path
28
+ end
29
+ rescue Errno::EISDIR
30
+ raise PageCacheError, PageCacheError::MSG_THERE_IS_DIRECTORY
31
+ end
32
+
33
+ return deleted
34
+ end
35
+
36
+ # Makes a cache file newly.
37
+ # The cache files will be created under 'cache' directory and its filename is SHA-256 hash value.
38
+ # @param string uri
39
+ # @param int code
40
+ # @param hash header
41
+ # @param array body
42
+ public
43
+ def make_cache(uri, code, header, body)
44
+ created_at = Time.now.to_i
45
+ data = {
46
+ :code => code,
47
+ :header => header,
48
+ :body => body
49
+ }
50
+ data = [code, header, body]
51
+ serialized_data = Marshal.dump data
52
+
53
+ # create new page cache file, delete it if it already exists
54
+ File.open(get_cache_file_path(uri), File::RDWR|File::CREAT|File::TRUNC) do |f|
55
+ f.flock File::LOCK_EX
56
+ f.puts created_at
57
+ f.print serialized_data
58
+ f.flock File::LOCK_UN
59
+ end
60
+ end
61
+
62
+ # @param string uri
63
+ # array
64
+ public
65
+ def get_page_cache(uri)
66
+ response_data = []
67
+ File.open(get_cache_file_path(uri), 'r') do |f|
68
+ f.flock File::LOCK_SH
69
+ f.readline
70
+ response_data = Marshal.load(f.read)
71
+ f.flock File::LOCK_UN
72
+ end
73
+ return response_data
74
+ end
75
+
76
+ # Returns true if cache file exists and its valid time hasn't passed.
77
+ # @param string uri
78
+ # @param int page_cache_time
79
+ # @return bool
80
+ public
81
+ def has_available_cache?(uri, page_cache_time)
82
+ path = get_cache_file_path uri
83
+ # check cache file exists?
84
+ return false if !Util::Filer.available_file? path
85
+
86
+ # check expiration
87
+ latest_access = 0
88
+ File.open(get_cache_file_path(uri), 'r') do |f|
89
+ f.flock File::LOCK_SH
90
+ latest_access = f.readline.strip.to_i
91
+ f.flock File::LOCK_UN
92
+ end
93
+ sec_passed = Time.now.to_i - latest_access # passed sec
94
+
95
+ # return false if page_cache_time has passed
96
+ if page_cache_time < sec_passed
97
+ return false
98
+ end
99
+
100
+ # availale
101
+ return true
102
+ end
103
+
104
+ # @param string uri
105
+ # @return string SHA-256 hash value
106
+ public
107
+ def get_cache_file_path(uri)
108
+ return "#{@cache_path}/#{Digest::SHA256.hexdigest(uri)}"
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,215 @@
1
+ module Nekonote
2
+ class Preference
3
+ include Singleton
4
+
5
+ # hidden file name for reloading preferences
6
+ FILE_NAME_FOR_RELOAD = '.reload_preference'
7
+
8
+ # for route.yml
9
+ FIELD_ROUTE_INCLUDE = 'include'
10
+
11
+ # for route options
12
+ FIELD_OPTION_ROUTE = 'preference'
13
+ FIELD_OPTION_ROUTE_REGEXP = 'path_as_regexp'
14
+ FIELD_OPTION_ALLOW_DUP_SLASH = 'allow_dup_slash'
15
+
16
+ # for route_error.yml
17
+ FIELD_ROUTE_ERR_MISSING_ROUTE = 'missing_route'
18
+ FIELD_ROUTE_ERR_WRONG_METHOD = 'wrong_http_method'
19
+ FIELD_ROUTE_ERR_FATAL = 'fatal'
20
+ FIELD_ROUTE_ERR_NOT_FOUND = 'not_found'
21
+
22
+ # for route.yml and route_error.yml
23
+ FIELD_ROUTE_PATH = 'path'
24
+ FIELD_ROUTE_EXEC_METHOD = 'execute'
25
+ FIELD_ROUTE_ALLOW_METHODS = 'method'
26
+ FIELD_ROUTE_PARAMS = 'params'
27
+ FIELD_ROUTE_CONTENT_TYPE = 'content'
28
+ FIELD_ROUTE_TEMPLATE = 'template'
29
+ FIELD_ROUTE_LAYOUT = 'layout'
30
+ FIELD_ROUTE_PAGE_CACHE_TIME = 'page_cache_time'
31
+ FIELD_ROUTE_HANDLER = 'handler'
32
+
33
+ # Except these fields are custom fields
34
+ FIELDS_IN_ROUTE = [
35
+ FIELD_ROUTE_PATH,
36
+ FIELD_ROUTE_EXEC_METHOD,
37
+ FIELD_ROUTE_ALLOW_METHODS,
38
+ FIELD_ROUTE_PARAMS,
39
+ FIELD_ROUTE_CONTENT_TYPE,
40
+ FIELD_ROUTE_TEMPLATE,
41
+ FIELD_ROUTE_LAYOUT,
42
+ FIELD_ROUTE_PAGE_CACHE_TIME,
43
+ FIELD_ROUTE_HANDLER
44
+ ]
45
+ FIELDS_IN_ROUTE_ERROR = [
46
+ FIELD_ROUTE_HANDLER,
47
+ FIELD_ROUTE_EXEC_METHOD,
48
+ FIELD_ROUTE_CONTENT_TYPE,
49
+ FIELD_ROUTE_TEMPLATE,
50
+ FIELD_ROUTE_LAYOUT,
51
+ FIELD_ROUTE_PAGE_CACHE_TIME
52
+ ]
53
+
54
+ # allowed to read or write from context of outside
55
+ attr_accessor :is_enabled_show_exceptions
56
+
57
+ # only reading is allowed
58
+ attr_reader :path_route_yml,
59
+ :path_route_include_yml,
60
+ :path_route_error_yml,
61
+ :path_public_yml,
62
+ :path_middlewares_rb,
63
+ :path_logger_yml
64
+
65
+ def initialize
66
+ env = Nekonote.get_env
67
+ path = Nekonote.get_root_path + YamlAccess::DIR_PREFERENCE + "/#{env}/"
68
+
69
+ @path_route_yml = path + 'route.yml'
70
+ @path_route_include_yml = path + 'route_include.yml'
71
+ @path_route_error_yml = path + 'route_error.yml'
72
+ @path_public_yml = path + 'public.yml'
73
+ @path_middlewares_rb = path + 'middlewares.rb'
74
+ @path_logger_yml = path + 'logger.yml'
75
+
76
+ @parsed_route_yml = nil
77
+ @parsed_route_include_yml = nil
78
+ @parsed_route_error_yml = nil
79
+ @parsed_public_yml = nil
80
+ @parsed_mw_yml = nil
81
+ @parsed_logger_yml = nil
82
+
83
+ # in route.yml
84
+ @is_path_regexp = nil
85
+ @is_allow_dup_slash = nil
86
+
87
+ # in middleware.yml
88
+ @is_enabled_show_exceptions = nil
89
+
90
+ # check there are required yaml files
91
+ if !Util::Filer.available_file? 'config.ru'
92
+ msg = Error::MSG_MISSING_RACKUP% @@root_path + $/
93
+ msg += Error::SPACE + Error::MSG_WRONG_ROOT
94
+ raise Error, msg
95
+ end
96
+
97
+ if !Util::Filer.available_file? @path_route_yml
98
+ raise PreferenceError, Error::MSG_MISSING_FILE% @path_route_yml
99
+ end
100
+ end
101
+
102
+ # @param string field
103
+ # @return bool
104
+ public
105
+ def has_error_route?(field)
106
+ pref = get_route_error
107
+
108
+ # missing route_error.yml
109
+ if pref == nil
110
+ Error.warning "Missing a file which for error routes #{@path_route_error_yml}."
111
+ return false
112
+ end
113
+
114
+ return pref[field].is_a?(Hash) && pref[field][FIELD_ROUTE_HANDLER].is_a?(String)
115
+ end
116
+
117
+ # @param bool fresh
118
+ # @return hash or exit from program
119
+ public
120
+ def get_route(fresh = false)
121
+ if !@parsed_route_yml.is_a?(Hash) || fresh
122
+ @parsed_route_yml = YamlAccess::get_parsed_route @path_route_yml
123
+ if @parsed_route_yml.size == 0
124
+ raise PreferenceError, PreferenceError::MSG_EMPTY_YAML% @path_route_yml
125
+ end
126
+ end
127
+ return @parsed_route_yml
128
+ end
129
+
130
+ # @param bool fresh
131
+ # @return hash
132
+ public
133
+ def get_route_include(fresh = false)
134
+ if !@parsed_route_include_yml.is_a?(Hash) || fresh
135
+ @parsed_route_include_yml = YamlAccess::get_parsed @path_route_include_yml
136
+ end
137
+ return @parsed_route_include_yml
138
+ end
139
+
140
+ # @param bool fresh
141
+ # @return hash
142
+ public
143
+ def get_route_error(fresh = false)
144
+ if !@parsed_route_error_yml.is_a?(Hash) || fresh
145
+ @parsed_route_error_yml = YamlAccess::get_parsed @path_route_error_yml
146
+ end
147
+ return @parsed_route_error_yml
148
+ end
149
+
150
+ # @param bool fresh
151
+ # @return hash
152
+ public
153
+ def get_public(fresh = false)
154
+ if !@parsed_public_yml.is_a?(Hash) || fresh
155
+ @parsed_public_yml = YamlAccess::get_parsed @path_public_yml
156
+ end
157
+ return @parsed_public_yml
158
+ end
159
+
160
+ # @param bool fresh
161
+ # @return hash
162
+ public
163
+ def get_logger(fresh = false)
164
+ if !@parsed_logger_yml.is_a?(Hash) || fresh
165
+ @parsed_logger_yml = YamlAccess::get_parsed @path_logger_yml
166
+ end
167
+ return @parsed_logger_yml
168
+ end
169
+
170
+ # @param bool fresh
171
+ # @return bool
172
+ public
173
+ def is_path_regexp?(fresh = false)
174
+ if @is_path_regexp == nil || fresh
175
+ pref = YamlAccess::get_parsed @path_route_yml
176
+
177
+ if pref[FIELD_OPTION_ROUTE].is_a?(Hash) \
178
+ && (pref[FIELD_OPTION_ROUTE][FIELD_OPTION_ROUTE_REGEXP] == true || pref[FIELD_OPTION_ROUTE][FIELD_OPTION_ROUTE_REGEXP] == 1)
179
+ @is_path_regexp = true # using Nekonote::URLMapper
180
+ else
181
+ @is_path_regexp = false # using ::Rack::URLMap
182
+ end
183
+ end
184
+
185
+ return @is_path_regexp
186
+ end
187
+
188
+ # @param bool fresh
189
+ # @return bool
190
+ public
191
+ def is_allow_dup_slash?(fresh = false)
192
+ if @is_allow_dup_slash == nil || fresh
193
+ pref = YamlAccess::get_parsed @path_route_yml
194
+ if pref[FIELD_OPTION_ROUTE].is_a?(Hash) && pref[FIELD_OPTION_ROUTE][FIELD_OPTION_ALLOW_DUP_SLASH] != nil
195
+ @is_allow_dup_slash = pref[FIELD_OPTION_ROUTE][FIELD_OPTION_ALLOW_DUP_SLASH]
196
+ else
197
+ @is_allow_dup_slash = false
198
+ end
199
+ end
200
+
201
+ return @is_allow_dup_slash
202
+ end
203
+
204
+ # @param array info information about route
205
+ # @param bool is_error_route
206
+ def self.get_custom_fields(info, is_error_route = false)
207
+ except_fields = is_error_route ? FIELDS_IN_ROUTE_ERROR : FIELDS_IN_ROUTE
208
+ except_fields.each do |field_name|
209
+ info.delete field_name
210
+ end
211
+
212
+ return info
213
+ end
214
+ end
215
+ end