55require 'contentstack/error'
66
77module Contentstack
8- # Centralised endpoint resolver. Reads region→service→URL mappings from the
9- # bundled regions.json and falls back to the live registry when the file is
10- # absent. Delegating to ContentstackUtils.get_contentstack_endpoint is
11- # preferred when that gem exposes the method (PR #41 of contentstack-utils-ruby).
8+ # Centralised endpoint resolver. Reads region metadata from the local
9+ # regions.json (downloaded from https://artifacts.contentstack.com/regions.json
10+ # at gem install time) and falls back to a live fetch when the file is absent.
11+ #
12+ # Delegates to ContentstackUtils.get_contentstack_endpoint when that gem
13+ # ships the method (contentstack-utils-ruby PR #41).
1214 class Endpoint
13- REGISTRY_URL = 'https://raw.githubusercontent .com/contentstack/contentstack-utils-ruby/main/lib/data /regions.json'
15+ REGISTRY_URL = 'https://artifacts.contentstack .com/regions.json'
1416 DATA_FILE_PATH = File . join ( File . dirname ( File . dirname ( __FILE__ ) ) , 'data' , 'regions.json' )
1517
16- DEFAULT_SERVICE = 'cda'
18+ # Maps the SDK's short service keys to the camelCase keys used in regions.json,
19+ # preserving backward compatibility for callers using Service::CDA / Service::CMA.
20+ SERVICE_MAP = {
21+ 'cda' => 'contentDelivery' ,
22+ 'cma' => 'contentManagement' ,
23+ 'preview' => 'preview'
24+ } . freeze
25+
26+ DEFAULT_SERVICE = 'contentDelivery'
1727
1828 # Resolve a Contentstack service URL for the given region and service.
1929 #
2030 # Contentstack::Endpoint.get_contentstack_endpoint('eu')
2131 # # => "https://eu-cdn.contentstack.com"
2232 #
23- # Contentstack::Endpoint.get_contentstack_endpoint('us', 'cma ')
33+ # Contentstack::Endpoint.get_contentstack_endpoint('us', 'contentManagement ')
2434 # # => "https://api.contentstack.io"
2535 #
36+ # Contentstack::Endpoint.get_contentstack_endpoint('eu', 'cda') # short alias
37+ # # => "https://eu-cdn.contentstack.com"
38+ #
2639 # When +custom_host+ is supplied the region CDN prefix is derived from
27- # regions.json and prepended to the custom domain, preserving the
28- # existing SDK behaviour for host-override configurations.
40+ # regions.json and prepended to the custom domain.
2941 def self . get_contentstack_endpoint ( region , service = DEFAULT_SERVICE , custom_host = nil )
3042 region_key = region . to_s . downcase
31- service_key = service . to_s . downcase
43+ service_key = SERVICE_MAP . fetch ( service . to_s , service . to_s )
3244
3345 if custom_host . nil? || custom_host . to_s . empty?
34- # Prefer the utils SDK when it ships endpoint resolution (PR #41)
3546 if defined? ( ContentstackUtils ) && ContentstackUtils . respond_to? ( :get_contentstack_endpoint )
3647 return ContentstackUtils . get_contentstack_endpoint ( region_key , service_key )
3748 end
@@ -41,10 +52,9 @@ def self.get_contentstack_endpoint(region, service = DEFAULT_SERVICE, custom_hos
4152 end
4253 end
4354
44- # Download and persist the latest region metadata from the registry.
45- # Equivalent to `composer refresh-regions` in the PHP SDK.
46- #
47- # Rake: bundle exec rake refresh_regions
55+ # Download the latest regions.json from https://artifacts.contentstack.com/regions.json
56+ # and persist it locally. Called automatically by ext/download_regions/extconf.rb
57+ # during bundle install / bundle update, and by `bundle exec rake refresh_regions`.
4858 def self . refresh_regions
4959 data = fetch_from_registry
5060 FileUtils . mkdir_p ( File . dirname ( DATA_FILE_PATH ) )
@@ -55,34 +65,43 @@ def self.refresh_regions
5565 private
5666
5767 def self . resolve_standard ( region_key , service_key )
58- regions = load_regions
59- unless regions . key? ( region_key )
68+ region_data = find_region ( region_key )
69+ unless region_data
6070 raise Contentstack ::Error . new (
61- Contentstack ::ErrorMessages . region_invalid ( region_key , regions . keys )
71+ Contentstack ::ErrorMessages . region_invalid ( region_key , all_region_ids )
6272 )
6373 end
64- unless regions [ region_key ] . key? ( service_key )
74+ unless region_data [ 'endpoints' ] . key? ( service_key )
6575 raise Contentstack ::Error . new (
66- Contentstack ::ErrorMessages . service_invalid ( service_key , regions [ region_key ] . keys )
76+ Contentstack ::ErrorMessages . service_invalid ( service_key , region_data [ 'endpoints' ] . keys )
6777 )
6878 end
69- regions [ region_key ] [ service_key ]
79+ region_data [ 'endpoints' ] [ service_key ]
7080 end
7181
72- # Derive the CDN subdomain prefix from regions.json and combine with the
73- # caller-supplied custom domain, e.g. "eu-cdn" + "example.com" →
74- # "https://eu-cdn.example.com".
7582 def self . resolve_custom_host ( region_key , service_key , custom_host )
76- regions = load_regions
77- if regions . key? ( region_key ) && regions [ region_key ] . key? ( service_key )
78- standard_url = regions [ region_key ] [ service_key ]
83+ region_data = find_region ( region_key )
84+ if region_data && region_data [ 'endpoints' ] . key? ( service_key )
85+ standard_url = region_data [ 'endpoints' ] [ service_key ]
7986 prefix = URI . parse ( standard_url ) . host . split ( '.' ) . first
8087 "https://#{ prefix } .#{ custom_host } "
8188 else
8289 "https://cdn.#{ custom_host } "
8390 end
8491 end
8592
93+ # Find a region by its canonical id or any of its declared aliases.
94+ def self . find_region ( region_key )
95+ load_regions [ 'regions' ] . find do |r |
96+ r [ 'id' ] == region_key ||
97+ r [ 'alias' ] . any? { |a | a . downcase == region_key }
98+ end
99+ end
100+
101+ def self . all_region_ids
102+ load_regions [ 'regions' ] . map { |r | r [ 'id' ] }
103+ end
104+
86105 def self . load_regions
87106 if File . exist? ( DATA_FILE_PATH )
88107 JSON . parse ( File . read ( DATA_FILE_PATH ) )
0 commit comments