aris 1.3.0 → 1.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 939f838547c98d96452cf200c2b5ae4d9cbdfaf17f6811415f2f341e7cf96a32
4
- data.tar.gz: c7c25cd371a1413068d0b490b7d92fa29809c077fde4c04f75a8619427de600f
3
+ metadata.gz: bf323ca0ed960b60c26e09f0b575212544c8c5b15b95be5e299b6296f03d97df
4
+ data.tar.gz: a68dfcec5a685a815f069f960f9bdcf6462115d6f5758e4adbedaf3ddbe3b3fa
5
5
  SHA512:
6
- metadata.gz: 4f4b0181b8df3cf3f7b421cbfef4bf9082324e833f31c688d638c41808845b81842448243da9e91279d0781f690edb7b76fde2c6859d060df58c4e3bf906e9fb
7
- data.tar.gz: 756840ba2f35be79777e3aeeb01be6a4ca560119d85d5e5ba11a725cc7f87ab8e2afa73a0fbd22c5ac97f4dcccfde31bf1c1ff621cddeea62c4864c3df15bdc9
6
+ metadata.gz: d42298b4ba003ec4d10494b9545e23fc381e037087720293e176e46a49446d9897c665a8dc3d4e684551193df7b2c07850f8743542b75718b7242b0bda816246
7
+ data.tar.gz: b04ef54738e7f457ee594d83407f27a58b94b05c8d8c00c03106f9cfdaf950d3c58d0e153fdfe613d2e98f41a9216d10c93b84d9b9b5768e49474e9e40d283c2
@@ -18,7 +18,7 @@ module Aris
18
18
  redirect = Aris::Utils::Redirects.find(request.path)
19
19
  return nil unless redirect
20
20
 
21
- [redirect[:status], {'Location' => redirect[:to]}, []]
21
+ [redirect[:status], {'location' => redirect[:to]}, []]
22
22
  end
23
23
  end
24
24
  end
@@ -39,7 +39,7 @@ module Aris
39
39
  if domain_config && domain_config[:locales] && domain_config[:locales].any? && domain_config[:root_locale_redirect] != false
40
40
  if path == '/' || path.empty?
41
41
  default_locale = domain_config[:default_locale] || domain_config[:locales].first
42
- return { status: 302, headers: {'Location' => "/#{default_locale}/"}, body: [] }
42
+ return { status: 302, headers: {'location' => "/#{default_locale}/"}, body: [] }
43
43
  end
44
44
  end
45
45
 
@@ -52,7 +52,7 @@ module Aris
52
52
  if defined?(Aris::Utils::Redirects)
53
53
  redirect = Aris::Utils::Redirects.find(path)
54
54
  if redirect
55
- return { status: redirect[:status], headers: {'Location' => redirect[:to]}, body: [] }
55
+ return { status: redirect[:status], headers: {'location' => redirect[:to]}, body: [] }
56
56
  end
57
57
  end
58
58
 
@@ -116,6 +116,24 @@ module Aris
116
116
  cookies
117
117
  end
118
118
 
119
+ def handle_static(request)
120
+ return nil unless request.method == 'GET'
121
+ return nil unless Aris::Config.serve_static
122
+
123
+ path = File.join('public', request.path)
124
+ return nil unless File.file?(path)
125
+
126
+ [200,
127
+ {'content-type' => mime_type(path)},
128
+ [File.binread(path)]
129
+ ]
130
+ end
131
+
132
+ def mime_type(path)
133
+ ext = File.extname(path).downcase
134
+ Aris::Config.mime_types[ext] || 'application/octet-stream'
135
+ end
136
+
119
137
  def format_response(result, response = nil)
120
138
  case result
121
139
  when Response
@@ -13,57 +13,87 @@ module Aris
13
13
  @app = app
14
14
  end
15
15
 
16
- # lib/aris/adapters/rack/adapter.rb
17
-
18
- # lib/aris/adapters/rack/adapter.rb
16
+ def call(env)
17
+ request = Rack::Request.new(env)
18
+ static_response = handle_static(request)
19
+ return static_response if static_response
20
+
21
+ sitemap_response = handle_sitemap(request)
22
+ return sitemap_response if sitemap_response
23
+
24
+ redirect_response = handle_redirect(request)
25
+ return redirect_response if redirect_response
26
+
27
+ redirect_res, normalized_path = Aris.handle_trailing_slash(request.path_info)
28
+ return redirect_res if redirect_res
29
+
30
+ # return res if res = handle_static(request)
31
+ # return res if res = handle_sitemap(request)
32
+ # return res if res = handle_redirect(request)
33
+ # redirect_res, normalized_path = Aris.handle_trailing_slash(request.path_info)
34
+ # return redirect_res if redirect_res
35
+
36
+ path_for_matching = normalized_path || request.path_info
37
+
38
+ request_domain = request.host
39
+ Thread.current[:aris_current_domain] = request_domain
40
+
41
+ response = Rack::Response.new
42
+ request.instance_variable_set(:@response, response)
43
+ request.define_singleton_method(:response) { @response }
19
44
 
20
- def call(env)
21
- request = Rack::Request.new(env)
22
- return res if res = handle_sitemap(request)
23
- return res if res = handle_redirect(request)
24
- redirect_res, normalized_path = Aris.handle_trailing_slash(request.path_info)
25
- return redirect_res if redirect_res
26
-
27
- path_for_matching = normalized_path || request.path_info
28
-
29
- request_domain = request.host
30
- Thread.current[:aris_current_domain] = request_domain
31
-
32
- response = Rack::Response.new
33
- request.instance_variable_set(:@response, response)
34
- request.define_singleton_method(:response) { @response }
35
-
36
- begin
37
- domain_config = Aris::Router.domain_config(request_domain)
38
- route = Aris::Router.match(
39
- domain: request_domain,
40
- method: request.request_method.downcase.to_sym,
41
- path: path_for_matching
42
- )
43
- if route
44
- inject_locale_methods(request, route, domain_config)
45
- result = PipelineRunner.call(request: request, route: route, response: response)
46
- format_response(result, response)
47
- else
48
- format_response(Aris.not_found(request, response), response)
49
- end
45
+ begin
46
+ domain_config = Aris::Router.domain_config(request_domain)
47
+ route = Aris::Router.match(
48
+ domain: request_domain,
49
+ method: request.request_method.downcase.to_sym,
50
+ path: path_for_matching
51
+ )
52
+ if route
53
+ inject_locale_methods(request, route, domain_config)
54
+ result = PipelineRunner.call(request: request, route: route, response: response)
55
+ format_response(result, response)
56
+ else
57
+ format_response(Aris.not_found(request, response), response)
58
+ end
50
59
 
51
- rescue Aris::Router::RouteNotFoundError
52
- format_response(Aris.not_found(request, response), response)
53
- rescue Exception => e
54
- # Error Path: 500
55
- format_response(Aris.error(request, e), response)
60
+ rescue Aris::Router::RouteNotFoundError
61
+ format_response(Aris.not_found(request, response), response)
62
+ rescue Exception => e
63
+ # Error Path: 500
64
+ format_response(Aris.error(request, e), response)
56
65
 
57
- ensure
58
- Thread.current[:aris_current_domain] = nil
59
- end
60
- end
66
+ ensure
67
+ Thread.current[:aris_current_domain] = nil
68
+ end
69
+ end
61
70
 
62
71
  def subdomain
63
72
  @subdomain || extract_subdomain_from_domain
64
73
  end
65
74
 
66
75
  private
76
+ def handle_static(request)
77
+ return nil unless request.request_method == 'GET'
78
+ return nil unless Aris::Config.serve_static
79
+
80
+ path = File.join('public', request.path_info)
81
+ return nil unless File.file?(path)
82
+
83
+ [200,
84
+ {
85
+ 'content-type' => mime_type(path),
86
+ 'cache-control' => 'public, max-age=31536000'
87
+ },
88
+ [File.binread(path)]
89
+ ]
90
+ end
91
+
92
+ def mime_type(path)
93
+ ext = File.extname(path).downcase
94
+ Aris::Config.mime_types[ext] || 'application/octet-stream'
95
+ end
96
+
67
97
 
68
98
  def extract_subdomain_from_domain
69
99
  return nil unless @env[:subdomain] || @env['SUBDOMAIN']
@@ -72,46 +102,57 @@ end
72
102
  end
73
103
 
74
104
 
75
- def inject_locale_methods(request, route, domain_config)
76
- return unless route[:locale]
105
+ def inject_locale_methods(request, route, domain_config)
106
+ return unless route[:locale]
107
+
108
+ # Inject the locale helper
109
+ request.define_singleton_method(:locale) { route[:locale] }
110
+
111
+ # Inject domain-specific locale configuration if it exists
112
+ if domain_config
113
+ request.define_singleton_method(:available_locales) { domain_config[:locales] }
114
+ request.define_singleton_method(:default_locale) { domain_config[:default_locale] }
115
+ end
116
+ end
117
+ def handle_sitemap(request)
118
+ # Overridden by sitemap utils if loaded
119
+ nil
120
+ end
121
+
122
+ def handle_redirect(request)
123
+ # Overridden by redirects utils if loaded
124
+ nil
125
+ end
126
+
127
+ def format_response(result, response = nil)
128
+ # 1. Identify the 'active' response source
129
+ # We check the passed object (response) and the returned object (result)
130
+ active_res = if result.respond_to?(:body) && !Array(result.body).empty?
131
+ result
132
+ elsif response.respond_to?(:body) && !Array(response.body).empty?
133
+ response
134
+ else
135
+ nil
136
+ end
137
+
138
+ # 2. If we found a response with content, send it to the Rack server
139
+ if active_res
140
+ # Standardize the body as an Array of Strings for Rack 3 compatibility
141
+ body = active_res.body
142
+ body = [body] if body.is_a?(String)
143
+
144
+ return [active_res.status, active_res.headers, body]
145
+ end
146
+
147
+ # 3. Final Fallback (If Joys rendered nothing)
148
+ case result
149
+ when Array then result
150
+ when Hash then [200, {'content-type' => 'application/json'}, [result.to_json]]
151
+ else [200, {'content-type' => 'text/plain'}, [result.to_s]]
152
+ end
153
+ end
77
154
 
78
- # Inject the locale helper
79
- request.define_singleton_method(:locale) { route[:locale] }
80
-
81
- # Inject domain-specific locale configuration if it exists
82
- if domain_config
83
- request.define_singleton_method(:available_locales) { domain_config[:locales] }
84
- request.define_singleton_method(:default_locale) { domain_config[:default_locale] }
85
- end
86
- end
87
-
88
- def format_response(result, response = nil)
89
- # 1. Identify the 'active' response source
90
- # We check the passed object (response) and the returned object (result)
91
- active_res = if result.respond_to?(:body) && !Array(result.body).empty?
92
- result
93
- elsif response.respond_to?(:body) && !Array(response.body).empty?
94
- response
95
- else
96
- nil
97
- end
98
-
99
- # 2. If we found a response with content, send it to the Rack server
100
- if active_res
101
- # Standardize the body as an Array of Strings for Rack 3 compatibility
102
- body = active_res.body
103
- body = [body] if body.is_a?(String)
104
-
105
- return [active_res.status, active_res.headers, body]
106
- end
107
155
 
108
- # 3. Final Fallback (If Joys rendered nothing)
109
- case result
110
- when Array then result
111
- when Hash then [200, {'content-type' => 'application/json'}, [result.to_json]]
112
- else [200, {'content-type' => 'text/plain'}, [result.to_s]]
113
- end
114
- end
115
156
  end
116
157
  end
117
158
  end
@@ -0,0 +1,53 @@
1
+ module Aris
2
+ module Config
3
+ class << self
4
+ attr_accessor :trailing_slash, :trailing_slash_status,:secret_key_base, :cookie_options, :serve_static
5
+ DEFAULT_MIME_TYPES = {
6
+ '.html' => 'text/html',
7
+ '.css' => 'text/css',
8
+ '.js' => 'application/javascript',
9
+ '.json' => 'application/json',
10
+ '.jpg' => 'image/jpeg',
11
+ '.jpeg' => 'image/jpeg',
12
+ '.png' => 'image/png',
13
+ '.gif' => 'image/gif',
14
+ '.svg' => 'image/svg+xml',
15
+ '.webp' => 'image/webp',
16
+ '.ico' => 'image/x-icon',
17
+ '.woff' => 'font/woff',
18
+ '.woff2' => 'font/woff2',
19
+ '.ttf' => 'font/ttf',
20
+ '.pdf' => 'application/pdf',
21
+ '.xml' => 'application/xml',
22
+ '.txt' => 'text/plain',
23
+ '.mp3' => 'audio/mpeg',
24
+ '.wav' => 'audio/wav',
25
+ '.ogg' => 'audio/ogg',
26
+ '.flac' => 'audio/flac',
27
+ '.m4a' => 'audio/mp4'
28
+ }.freeze
29
+ def mime_types
30
+ @mime_types ||= DEFAULT_MIME_TYPES.dup
31
+ end
32
+
33
+ def mime_types=(custom_types)
34
+ @mime_types = DEFAULT_MIME_TYPES.merge(custom_types)
35
+ end
36
+
37
+ def reset!
38
+ @trailing_slash = :strict
39
+ @serve_static = false
40
+ @trailing_slash_status = 301
41
+ @secret_key_base = nil
42
+ @cookie_options = {
43
+ httponly: true,
44
+ secure: false, # Default to false for development
45
+ same_site: :lax,
46
+ path: '/'
47
+ }
48
+ end
49
+ end
50
+
51
+ reset!
52
+ end
53
+ end