Commit 4122023

mo khan <mo@mokhan.ca>
2026-08-04 02:19:05
fix: percent-encode query values per RFC 3986
URI.encode_www_form sent a SCIM filter as userName+eq+%22bj%22. A server that percent-decodes the query rejects that as a malformed filter.
cli
1 parent 9a14954
Changed files (2)
lib
scim
kit
spec
scim
lib/scim/kit/cli/client.rb
@@ -20,10 +20,19 @@ module Scim
 
         def uri_for(path, query)
           uri = URI.join("#{base_url.to_s.sub(%r{/+\z}, '')}/", path)
-          encoded = URI.encode_www_form(query.compact)
+          encoded = encode_query(query)
           uri.query = encoded unless encoded.empty?
           uri
         end
+
+        # Percent-encode per RFC 3986 rather than as a form body, so a SCIM
+        # filter arrives with %20 instead of +.
+        def encode_query(query)
+          query.compact.map do |name, value|
+            "#{URI.encode_uri_component(name.to_s)}=" \
+              "#{URI.encode_uri_component(value.to_s)}"
+          end.join('&')
+        end
       end
     end
   end
spec/scim/kit/cli/client_spec.rb
@@ -45,6 +45,16 @@ RSpec.describe Scim::Kit::Cli::Client do
       expect(stub).to have_been_requested
     end
 
+    it 'percent-encodes spaces in query values' do
+      http = instance_double(Scim::Kit::Http, fetch: nil)
+      expected = URI('https://example.com/Users?filter=userName%20eq%20%22bj%22')
+
+      described_class.new('https://example.com', http: http)
+        .fetch('Users', query: { 'filter' => 'userName eq "bj"' })
+
+      expect(http).to have_received(:fetch).with(expected, headers: {})
+    end
+
     it 'omits blank query values' do
       stub = stub_request(:get, 'https://example.com/Users')
         .to_return(status: 200, body: body)