wovnrb 3.13.0 → 3.13.1

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: c25c86e04efab85fc760c24f2fb1905e2cb95a8636b2ad27a9f59bbef78e99e5
4
- data.tar.gz: ab246aa58e1cb9ed5989f262ac8144eac400c77b556a5d9fb259e62534b9bac5
3
+ metadata.gz: a2bdf648db98d590ad2f2c05db1373552996dd9e3c942951f78097b3b6debd6c
4
+ data.tar.gz: 1036495c61840b5027f25d4b68c07a50682b4e84c7f78898cb3a9c2c0ad6a876
5
5
  SHA512:
6
- metadata.gz: b5f42f8edb1b03dc3fe14d513aac9dffc97df0b62b9186fabba98b60373335579be893eddd4305c3e6cdbea9c9798e758fc73ceb8077f0f044efb36b0b6fb17c
7
- data.tar.gz: 48431e3fba479475e39ed4a5a0f77ca2e53e8ecc4e474ae27166a613e62da176069c40e90349b2fd2764c3d6f66577651ba7b8eded732ccf23cdbb82fb6886bd
6
+ metadata.gz: a88cbd3f984eb1c32cd3f2c8588e0e697562f4c5a42e82fd62a1d91b76e4b8b58436a447d56aecf267b13cebabde0ca46b5c17bdecd1b49f27d0901c5af09d2a
7
+ data.tar.gz: bd575bcb78e7f3c3fa98480c1b627b78515b5bf8181de8c6d7907dbcac349d0fefdf34662849e19452aed784ebcb503a67090602df24b26a07c929ce4bc261b7
data/README.md CHANGED
@@ -1 +1 @@
1
- README.ja.md
1
+ ./README.ja.md
@@ -14,7 +14,7 @@ module Wovnrb
14
14
  @settings = settings
15
15
  @protocol = request.scheme
16
16
  @unmasked_host = if settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
17
- @env['HTTP_X_FORWARDED_HOST']
17
+ first_header_value(@env['HTTP_X_FORWARDED_HOST'])
18
18
  else
19
19
  @env['HTTP_HOST']
20
20
  end
@@ -29,7 +29,7 @@ module Wovnrb
29
29
  @unmasked_pathname += '/' unless @unmasked_pathname =~ /\/$/ || @unmasked_pathname =~ /\/[^\/.]+\.[^\/.]+$/
30
30
  @unmasked_url = "#{@protocol}://#{@unmasked_host}#{@unmasked_pathname}"
31
31
  @host = if settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
32
- @env['HTTP_X_FORWARDED_HOST']
32
+ first_header_value(@env['HTTP_X_FORWARDED_HOST'])
33
33
  else
34
34
  @env['HTTP_HOST']
35
35
  end
@@ -81,7 +81,7 @@ module Wovnrb
81
81
  def url_language
82
82
  if @url_language.nil?
83
83
  full_url = if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
84
- "#{@env['HTTP_X_FORWARDED_HOST']}#{@env['REQUEST_URI']}"
84
+ "#{first_header_value(@env['HTTP_X_FORWARDED_HOST'])}#{@env['REQUEST_URI']}"
85
85
  else
86
86
  "#{@env['SERVER_NAME']}#{@env['REQUEST_URI']}"
87
87
  end
@@ -173,7 +173,7 @@ module Wovnrb
173
173
 
174
174
  def remove_lang_from_host
175
175
  if @settings['use_proxy'] && @env.key?('HTTP_X_FORWARDED_HOST')
176
- @env['HTTP_X_FORWARDED_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_X_FORWARDED_HOST'], lang_code, self)
176
+ @env['HTTP_X_FORWARDED_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(first_header_value(@env['HTTP_X_FORWARDED_HOST']), lang_code, self)
177
177
  else
178
178
  @env['HTTP_HOST'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_HOST'], lang_code, self)
179
179
  @env['SERVER_NAME'] = @url_lang_switcher.remove_lang_from_uri_component(@env['SERVER_NAME'], lang_code, self)
@@ -188,5 +188,11 @@ module Wovnrb
188
188
  @env['ORIGINAL_FULLPATH'] = @url_lang_switcher.remove_lang_from_uri_component(@env['ORIGINAL_FULLPATH'], lang_code, self) if @env.key?('ORIGINAL_FULLPATH')
189
189
  @env['HTTP_REFERER'] = @url_lang_switcher.remove_lang_from_uri_component(@env['HTTP_REFERER'], lang_code, self) if @env.key?('HTTP_REFERER')
190
190
  end
191
+
192
+ # X-Forwarded-Host can contain multiple comma-separated values when
193
+ # the request passes through more than one proxy (RFC 7230 §3.2.2).
194
+ def first_header_value(value)
195
+ value.include?(',') ? value.split(',', 2).first.strip : value
196
+ end
191
197
  end
192
198
  end
@@ -1,3 +1,3 @@
1
1
  module Wovnrb
2
- VERSION = '3.13.0'.freeze
2
+ VERSION = '3.13.1'.freeze
3
3
  end
@@ -947,5 +947,81 @@ module Wovnrb
947
947
  assert_equal(expected_lang_code, header.url_language)
948
948
  end
949
949
  end
950
+
951
+ def test_multi_value_x_forwarded_host_uses_first_value
952
+ settings = Wovnrb.get_settings({ 'use_proxy' => true })
953
+ store = Wovnrb.get_store(settings)
954
+ env = Wovnrb.get_env({
955
+ 'HTTP_X_FORWARDED_HOST' => 'www.example.com, www.example.com',
956
+ 'REQUEST_URI' => '/en/page'
957
+ })
958
+ url_lang_switcher = UrlLanguageSwitcher.new(store)
959
+ header = Wovnrb::Headers.new(env, settings, url_lang_switcher)
960
+
961
+ assert_equal('www.example.com', header.unmasked_host)
962
+ assert_equal('www.example.com', header.host)
963
+ end
964
+
965
+ def test_multi_value_x_forwarded_host_with_spaces
966
+ settings = Wovnrb.get_settings({ 'use_proxy' => true })
967
+ store = Wovnrb.get_store(settings)
968
+ env = Wovnrb.get_env({
969
+ 'HTTP_X_FORWARDED_HOST' => ' www.example.com , proxy.internal ',
970
+ 'REQUEST_URI' => '/page'
971
+ })
972
+ url_lang_switcher = UrlLanguageSwitcher.new(store)
973
+ header = Wovnrb::Headers.new(env, settings, url_lang_switcher)
974
+
975
+ assert_equal('www.example.com', header.unmasked_host)
976
+ end
977
+
978
+ def test_single_value_x_forwarded_host_unchanged
979
+ settings = Wovnrb.get_settings({ 'use_proxy' => true })
980
+ store = Wovnrb.get_store(settings)
981
+ env = Wovnrb.get_env({
982
+ 'HTTP_X_FORWARDED_HOST' => 'www.example.com',
983
+ 'REQUEST_URI' => '/page'
984
+ })
985
+ url_lang_switcher = UrlLanguageSwitcher.new(store)
986
+ header = Wovnrb::Headers.new(env, settings, url_lang_switcher)
987
+
988
+ assert_equal('www.example.com', header.unmasked_host)
989
+ assert_equal('www.example.com', header.host)
990
+ end
991
+
992
+ def test_multi_value_x_forwarded_host_subdomain_url_language
993
+ settings = Wovnrb.get_settings({
994
+ 'use_proxy' => true,
995
+ 'url_pattern' => 'subdomain',
996
+ 'url_pattern_reg' => '^(?<lang>[^.]+)\.'
997
+ })
998
+ store = Wovnrb.get_store(settings)
999
+ env = Wovnrb.get_env({
1000
+ 'HTTP_X_FORWARDED_HOST' => 'ja.wovn.io, proxy.internal',
1001
+ 'REQUEST_URI' => '/page'
1002
+ })
1003
+ url_lang_switcher = UrlLanguageSwitcher.new(store)
1004
+ header = Wovnrb::Headers.new(env, settings, url_lang_switcher)
1005
+
1006
+ assert_equal('ja', header.url_language)
1007
+ end
1008
+
1009
+ def test_multi_value_x_forwarded_host_request_out
1010
+ settings = Wovnrb.get_settings({
1011
+ 'url_pattern' => 'subdomain',
1012
+ 'url_pattern_reg' => '^(?<lang>[^.]+)\.',
1013
+ 'use_proxy' => true
1014
+ })
1015
+ store = Wovnrb.get_store(settings)
1016
+ env = Wovnrb.get_env({
1017
+ 'url' => 'http://localhost/contact',
1018
+ 'HTTP_X_FORWARDED_HOST' => 'ja.wovn.io, proxy.internal'
1019
+ })
1020
+ url_lang_switcher = UrlLanguageSwitcher.new(store)
1021
+ header = Wovnrb::Headers.new(env, settings, url_lang_switcher)
1022
+
1023
+ request_out_env = header.request_out
1024
+ assert_equal('wovn.io', request_out_env['HTTP_X_FORWARDED_HOST'])
1025
+ end
950
1026
  end
951
1027
  end
data/wovnrb.gemspec CHANGED
@@ -24,5 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.add_dependency 'addressable'
25
25
  spec.add_dependency 'lz4-ruby'
26
26
  spec.add_dependency 'nokogiri', '>= 1.12', '<2'
27
- spec.add_dependency 'rack'
27
+ # Rack 3 drops Ruby 2.5 compatibility; keep the gem on Rack 2.x for the
28
+ # supported Ruby matrix.
29
+ spec.add_dependency 'rack', '< 3'
28
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wovnrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.0
4
+ version: 3.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wovn Technologies, Inc.
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-10-17 00:00:00.000000000 Z
11
+ date: 2026-06-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -76,16 +76,16 @@ dependencies:
76
76
  name: rack
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - ">="
79
+ - - "<"
80
80
  - !ruby/object:Gem::Version
81
- version: '0'
81
+ version: '3'
82
82
  type: :runtime
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
- - - ">="
86
+ - - "<"
87
87
  - !ruby/object:Gem::Version
88
- version: '0'
88
+ version: '3'
89
89
  description: Ruby gem for WOVN backend on Rack.
90
90
  email:
91
91
  - dev@wovn.io
@@ -262,7 +262,7 @@ licenses:
262
262
  - MIT
263
263
  metadata:
264
264
  rubygems_mfa_required: 'true'
265
- post_install_message:
265
+ post_install_message:
266
266
  rdoc_options: []
267
267
  require_paths:
268
268
  - lib
@@ -277,8 +277,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
277
277
  - !ruby/object:Gem::Version
278
278
  version: '0'
279
279
  requirements: []
280
- rubygems_version: 3.5.11
281
- signing_key:
280
+ rubygems_version: 3.1.4
281
+ signing_key:
282
282
  specification_version: 4
283
283
  summary: Gem for WOVN.io
284
284
  test_files: []