Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ coverage
.DS_Store
.bundle/
**/rspec_results.html
.dccache
.dccache
vendor/
lib/contentstack_utils/assets/regions.json
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.4
3.3.11
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [1.3.0](https://github.com/contentstack/contentstack-utils-ruby/tree/v1.3.0) (2026-06-15)
- Added `ContentstackUtils::Endpoint.get_contentstack_endpoint` for dynamic endpoint resolution based on region and service.
- Added `ContentstackUtils.get_contentstack_endpoint` as a backward-compatible proxy.
- Added `ContentstackUtils::Endpoint.refresh_regions` for manual region metadata refresh.
- Added runtime fallback to automatically download `regions.json` from the Contentstack Regions Registry when not present locally.

## [1.2.4](https://github.com/contentstack/contentstack-utils-ruby/tree/v1.2.4) (2026-04-15)
- Fixed Security issues.

Expand Down
20 changes: 10 additions & 10 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ GEM
public_suffix (>= 2.0.2, < 8.0)
base64 (0.3.0)
benchmark (0.5.0)
bigdecimal (4.1.1)
bigdecimal (4.1.2)
concurrent-ruby (1.3.6)
connection_pool (3.0.2)
crack (1.0.1)
Expand All @@ -38,21 +38,21 @@ GEM
concurrent-ruby (~> 1.0)
logger (1.7.0)
minitest (5.27.0)
nokogiri (1.19.2-aarch64-linux-gnu)
nokogiri (1.19.3-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-aarch64-linux-musl)
nokogiri (1.19.3-aarch64-linux-musl)
racc (~> 1.4)
nokogiri (1.19.2-arm-linux-gnu)
nokogiri (1.19.3-arm-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-arm-linux-musl)
nokogiri (1.19.3-arm-linux-musl)
racc (~> 1.4)
nokogiri (1.19.2-arm64-darwin)
nokogiri (1.19.3-arm64-darwin)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-darwin)
nokogiri (1.19.3-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-gnu)
nokogiri (1.19.3-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-musl)
nokogiri (1.19.3-x86_64-linux-musl)
racc (~> 1.4)
public_suffix (7.0.5)
racc (1.8.1)
Expand Down Expand Up @@ -84,7 +84,7 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
yard (0.9.42)
yard (0.9.44)

PLATFORMS
aarch64-linux-gnu
Expand Down
96 changes: 96 additions & 0 deletions lib/contentstack_utils/endpoint.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
require 'json'
require 'net/http'
require 'uri'

module ContentstackUtils
module Endpoint
REGIONS_URL = 'https://artifacts.contentstack.com/regions.json'
REGIONS_FILE = File.expand_path('../assets/regions.json', __FILE__)

@regions_data = nil

class << self
def get_contentstack_endpoint(region: 'us', service: '', omit_https: false)
raise ArgumentError, 'Empty region provided' if region.nil? || region.to_s.strip.empty?

normalized = region.to_s.strip.downcase
regions = load_regions

region_row = find_region_by_id_or_alias(regions, normalized)
raise ArgumentError, "Invalid region: #{region}" if region_row.nil?

endpoints = region_row['endpoints']

if service.nil? || service.to_s.strip.empty?
return omit_https ? strip_https_from_map(endpoints) : endpoints.dup
end

url = endpoints[service.to_s]
raise ArgumentError, "Service \"#{service}\" not found for region \"#{region}\"" if url.nil?

omit_https ? strip_https(url) : url
end

def refresh_regions
download_and_save(REGIONS_FILE)
@regions_data = nil
load_regions
true
end

def reset_cache
@regions_data = nil
end

private

def load_regions
return @regions_data if @regions_data

unless File.exist?(REGIONS_FILE)
download_and_save(REGIONS_FILE)
end

raw = File.read(REGIONS_FILE)
parsed = JSON.parse(raw)
raise RuntimeError, 'Invalid regions data: missing "regions" key' unless parsed.is_a?(Hash) && parsed['regions']

@regions_data = parsed['regions']
rescue JSON::ParserError => e
raise RuntimeError, "Failed to parse regions data: #{e.message}"
rescue Errno::ENOENT => e
raise RuntimeError, "Failed to read regions file: #{e.message}"
end

def download_and_save(dest)
uri = URI.parse(REGIONS_URL)
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', open_timeout: 30, read_timeout: 30) do |http|
http.get(uri.request_uri)
end

raise RuntimeError, "Failed to download regions: HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)

parsed = JSON.parse(response.body)
raise RuntimeError, 'Downloaded regions data is invalid' unless parsed.is_a?(Hash) && parsed['regions']

FileUtils.mkdir_p(File.dirname(dest))
File.write(dest, JSON.pretty_generate(parsed))
rescue StandardError => e
raise RuntimeError, "Failed to fetch region metadata: #{e.message}"
end

def find_region_by_id_or_alias(regions, input)
regions.find { |r| r['id'] == input } ||
regions.find { |r| r['alias']&.any? { |a| a.downcase == input } }
end

def strip_https(url)
url.sub(%r{\Ahttps?://}, '')
end

def strip_https_from_map(endpoints)
endpoints.transform_values { |url| strip_https(url) }
end
end
end
end
5 changes: 5 additions & 0 deletions lib/contentstack_utils/utils.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require_relative './model/options.rb'
require_relative './model/metadata.rb'
require_relative './support/helper.rb'
require_relative './endpoint.rb'
require 'nokogiri'

module ContentstackUtils
Expand Down Expand Up @@ -136,6 +137,10 @@ def self.json_doc_to_html(node, options, callback)
return nil
end

def self.get_contentstack_endpoint(region: 'us', service: '', omit_https: false)
Endpoint.get_contentstack_endpoint(region: region, service: service, omit_https: omit_https)
end

module GQL
include ContentstackUtils
def self.json_to_html(content, options)
Expand Down
2 changes: 1 addition & 1 deletion lib/contentstack_utils/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ContentstackUtils
VERSION = "1.2.4"
VERSION = "1.3.0"
end
Loading
Loading