@@ -39,14 +39,21 @@ def initialize(job:, gateway: DEFAULT_GATEWAY, grouping_key: {}, **kwargs)
3939 @gateway = gateway || DEFAULT_GATEWAY
4040 @grouping_key = grouping_key
4141 @path = build_path ( job , grouping_key )
42+
4243 @uri = parse ( "#{ @gateway } #{ @path } " )
44+ validate_no_basic_auth! ( @uri )
4345
4446 @http = Net ::HTTP . new ( @uri . host , @uri . port )
4547 @http . use_ssl = ( @uri . scheme == 'https' )
4648 @http . open_timeout = kwargs [ :open_timeout ] if kwargs [ :open_timeout ]
4749 @http . read_timeout = kwargs [ :read_timeout ] if kwargs [ :read_timeout ]
4850 end
4951
52+ def basic_auth ( user , password )
53+ @user = user
54+ @password = password
55+ end
56+
5057 def add ( registry )
5158 synchronize do
5259 request ( Net ::HTTP ::Post , registry )
@@ -113,7 +120,7 @@ def request(req_class, registry = nil)
113120
114121 req = req_class . new ( @uri )
115122 req . content_type = Formats ::Text ::CONTENT_TYPE
116- req . basic_auth ( @uri . user , @uri . password ) if @uri . user
123+ req . basic_auth ( @user , @password ) if @user
117124 req . body = Formats ::Text . marshal ( registry ) if registry
118125
119126 response = @http . request ( req )
@@ -126,6 +133,39 @@ def synchronize
126133 @mutex . synchronize { yield }
127134 end
128135
136+ def validate_no_basic_auth! ( uri )
137+ if uri . user || uri . password
138+ raise ArgumentError , <<~EOF
139+ Setting Basic Auth credentials in the gateway URL is not supported, please call the `basic_auth` method.
140+
141+ Received username `#{ uri . user } ` in gateway URL. Instead of passing
142+ Basic Auth credentials like this:
143+
144+ ```
145+ push = Prometheus::Client::Push.new(job: "my-job", gateway: "http://user:password@localhost:9091")
146+ ```
147+
148+ please pass them like this instead:
149+
150+ ```
151+ push = Prometheus::Client::Push.new(job: "my-job", gateway: "http://localhost:9091")
152+ push.basic_auth("user", "password")
153+ ```
154+
155+ While URLs do support passing Basic Auth credentials using the
156+ `http://user:[email protected] /` syntax, the username and 157+ password in that syntax have to follow the usual rules for URL
158+ encoding of characters per RFC 3986
159+ (https://datatracker.ietf.org/doc/html/rfc3986#section-2.1).
160+
161+ Rather than place the burden of correctly performing that encoding
162+ on users of this gem, we decided to have a separate method for
163+ supplying Basic Auth credentials, with no requirement to URL encode
164+ the characters in them.
165+ EOF
166+ end
167+ end
168+
129169 def validate_no_label_clashes! ( registry )
130170 # There's nothing to check if we don't have a grouping key
131171 return if @grouping_key . empty?
0 commit comments