Module: OvertureMaps::Storage
- Defined in:
- lib/overture_maps/storage.rb
Overview
Anonymous HTTP access to the public Overture bucket (or a configured mirror): object listing via the S3 REST API's XML responses and streaming downloads. No AWS SDK, no credentials, no global state.
Defined Under Namespace
Classes: Error
Constant Summary collapse
- MAX_REDIRECTS =
5
Class Method Summary collapse
-
.download(key, to:, expected_size: nil) ⇒ Object
Streams an object to a local file.
-
.download_url(url, to:) ⇒ Object
Downloads any URL to a file, following redirects, writing through a temp file so failures never leave a truncated file at the target path.
-
.get(url) ⇒ Object
GET returning the body as a string, following redirects.
-
.list(prefix:, delimiter: nil) ⇒ Object
Lists objects under a prefix.
Class Method Details
.download(key, to:, expected_size: nil) ⇒ Object
Streams an object to a local file. Skips the download when the local file already has the expected size.
51 52 53 54 55 56 57 58 |
# File 'lib/overture_maps/storage.rb', line 51 def download(key, to:, expected_size: nil) if expected_size && File.exist?(to) && File.size(to) == expected_size return :skipped end download_url("#{base_url}/#{escape_key(key)}", to: to) :downloaded end |
.download_url(url, to:) ⇒ Object
Downloads any URL to a file, following redirects, writing through a temp file so failures never leave a truncated file at the target path.
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/overture_maps/storage.rb', line 62 def download_url(url, to:) FileUtils.mkdir_p(File.dirname(to)) tmp = "#{to}.part" fetch_streaming(url) do |response| File.open(tmp, "wb") do |file| response.read_body { |chunk| file.write(chunk) } end end FileUtils.mv(tmp, to) to ensure FileUtils.rm_f(tmp) if tmp && File.exist?(tmp) end |
.get(url) ⇒ Object
GET returning the body as a string, following redirects.
79 80 81 82 83 |
# File 'lib/overture_maps/storage.rb', line 79 def get(url) body = nil fetch_streaming(url) { |response| body = response.body } body end |
.list(prefix:, delimiter: nil) ⇒ Object
Lists objects under a prefix. Returns { objects: [size:], prefixes: [String] }, following continuation tokens.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/overture_maps/storage.rb', line 20 def list(prefix:, delimiter: nil) objects = [] prefixes = [] token = nil loop do params = { "list-type" => "2", "prefix" => prefix } params["delimiter"] = delimiter if delimiter params["continuation-token"] = token if token doc = REXML::Document.new(get("#{base_url}/?#{URI.encode_www_form(params)}")) root = doc.root raise Error, "unexpected listing response" unless root&.name == "ListBucketResult" root.each_element("Contents") do |el| objects << { key: el.elements["Key"]&.text, size: el.elements["Size"]&.text.to_i } end root.each_element("CommonPrefixes/Prefix") { |el| prefixes << el.text } token = root.elements["NextContinuationToken"]&.text break unless token end { objects: objects, prefixes: prefixes } end |