Skip to content

Instantly share code, notes, and snippets.

@yakatz
Created June 12, 2025 01:52
Show Gist options
  • Save yakatz/fed2e70e813e9a4243598738a24e9369 to your computer and use it in GitHub Desktop.
Save yakatz/fed2e70e813e9a4243598738a24e9369 to your computer and use it in GitHub Desktop.
require 'uri'
Puppet::Functions.create_function(:'profile::url_query_merge') do
dispatch :url_query_merge do
required_param 'String', :url
required_repeated_param 'Variant[String, Array, Hash]', :new_params
return_type 'String'
end
def url_query_merge( url, *new_params )
# Allow clearing values - for example, a param ?key=remove would remove all instances of key "key"
#
# Example: url_query_merge(
# "https://signage.example.com/tv.php?&id=39",
# ["a=b", "c=d&e=f"], # Array of strings
# {'y' => 'z'}, # Hash
# "?c=remove&c=123", # Remove and replace items
# {'y1' => 'z1', 'y2' => 'z2', 'y3' => 'z3'}, # Multi-item hash
# [{'w' => 'x'}, {'t' => 'u'}], # Array of Hashes
# )
#
# "https://signage.example.com/tv.php?id=39&a=b&e=f&y=z&c=123&y1=z1&y2=z2&y3=z3&w=x&t=u"
uri = URI.parse(url)
all_query_params = URI.decode_www_form(String(uri.query))
new_params.each do |i|
if i.respond_to?(:keys) then
all_query_params.concat i.map {|k,v| [k, v]}
elsif i.respond_to?(:each)
i.each do |j|
if j.respond_to?(:keys)
all_query_params.concat j.map{ |k,v| [k, v]}
else
all_query_params.concat URI.decode_www_form(j)
end
end
else
all_query_params.concat URI.decode_www_form(i)
end
end
all_query_params.reject! { |k, v| k.empty? }
final_query_params = []
all_query_params.each do |k, v|
if k.start_with?('?') && v == "remove" then
rk = k[1..-1]
final_query_params.reject! { |ik,iv| ik == rk }
else
final_query_params << [k,v]
end
end
uri.query = URI.encode_www_form(final_query_params)
return(uri.to_s)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment