webhook: quote URL variables to prevent url errors with special chars like # in pr title.
ergo -
r3477:976a0af2 default
Not Reviewed
Show More
Add another comment
TODOs: 0 unresolved 0 Resolved
COMMENTS: 0 General 0 Inline
@@ -23,17 +23,27
23 23 import collections
24 24 import logging
25 25 import requests
26 import urllib
26 27 from requests.adapters import HTTPAdapter
27 28 from requests.packages.urllib3.util.retry import Retry
28 29
29 30 from mako import exceptions
30 31
32 from rhodecode.lib.utils2 import safe_str
31 33 from rhodecode.translation import _
32 34
33 35
34 36 log = logging.getLogger(__name__)
35 37
36 38
39 class UrlTmpl(string.Template):
40
41 def safe_substitute(self, **kws):
42 # url encode the kw for usage in url
43 kws = {k: urllib.quote(safe_str(v)) for k, v in kws.items()}
44 return super(UrlTmpl, self).safe_substitute(**kws)
45
46
37 47 class IntegrationTypeBase(object):
38 48 """ Base class for IntegrationType plugins """
39 49 is_dummy = False
@@ -217,7 +227,9
217 227 common_vars.update(extra_vars)
218 228
219 229 template_url = self.template_url.replace('${extra:', '${extra__')
220 return string.Template(template_url).safe_substitute(**common_vars)
230 for k, v in common_vars.items():
231 template_url = UrlTmpl(template_url).safe_substitute(**{k: v})
232 return template_url
221 233
222 234 def repo_push_event_handler(self, event, data):
223 235 url = self.get_base_parsed_template(data)
@@ -228,20 +240,18
228 240 if '${branch}' in url or '${branch_head}' in url or '${commit_id}' in url:
229 241 # call it multiple times, for each branch if used in variables
230 242 for branch, commit_ids in branches_commits.items():
231 branch_url = string.Template(url).safe_substitute(branch=branch)
243 branch_url = UrlTmpl(url).safe_substitute(branch=branch)
232 244
233 245 if '${branch_head}' in branch_url:
234 246 # last commit in the aggregate is the head of the branch
235 247 branch_head = commit_ids['branch_head']
236 branch_url = string.Template(branch_url).safe_substitute(
237 branch_head=branch_head)
248 branch_url = UrlTmpl(branch_url).safe_substitute(branch_head=branch_head)
238 249
239 250 # call further down for each commit if used
240 251 if '${commit_id}' in branch_url:
241 252 for commit_data in commit_ids['commits']:
242 253 commit_id = commit_data['raw_id']
243 commit_url = string.Template(branch_url).safe_substitute(
244 commit_id=commit_id)
254 commit_url = UrlTmpl(branch_url).safe_substitute(commit_id=commit_id)
245 255 # register per-commit call
246 256 log.debug(
247 257 'register %s call(%s) to url %s',
@@ -251,36 +261,34
251 261
252 262 else:
253 263 # register per-branch call
254 log.debug(
255 'register %s call(%s) to url %s',
256 self.name, event, branch_url)
257 url_calls.append(
258 (branch_url, self.headers, data))
264 log.debug('register %s call(%s) to url %s',
265 self.name, event, branch_url)
266 url_calls.append((branch_url, self.headers, data))
259 267
260 268 else:
261 log.debug(
262 'register %s call(%s) to url %s', self.name, event, url)
269 log.debug('register %s call(%s) to url %s', self.name, event, url)
263 270 url_calls.append((url, self.headers, data))
264 271
265 272 return url_calls
266 273
267 274 def repo_create_event_handler(self, event, data):
268 275 url = self.get_base_parsed_template(data)
269 log.debug(
270 'register %s call(%s) to url %s', self.name, event, url)
276 log.debug('register %s call(%s) to url %s', self.name, event, url)
271 277 return [(url, self.headers, data)]
272 278
273 279 def pull_request_event_handler(self, event, data):
274 280 url = self.get_base_parsed_template(data)
275 log.debug(
276 'register %s call(%s) to url %s', self.name, event, url)
277 url = string.Template(url).safe_substitute(
278 pull_request_id=data['pullrequest']['pull_request_id'],
279 pull_request_title=data['pullrequest']['title'],
280 pull_request_url=data['pullrequest']['url'],
281 pull_request_shadow_url=data['pullrequest']['shadow_url'],
282 pull_request_commits_uid=data['pullrequest']['commits_uid'],
283 )
281 log.debug('register %s call(%s) to url %s', self.name, event, url)
282 pr_vars = [
283 ('pull_request_id', data['pullrequest']['pull_request_id']),
284 ('pull_request_title', data['pullrequest']['title']),
285 ('pull_request_url', data['pullrequest']['url']),
286 ('pull_request_shadow_url', data['pullrequest']['shadow_url']),
287 ('pull_request_commits_uid', data['pullrequest']['commits_uid']),
288 ]
289 for k, v in pr_vars:
290 url = UrlTmpl(url).safe_substitute(**{k: v})
291
284 292 return [(url, self.headers, data)]
285 293
286 294 def __call__(self, event, data):
@@ -188,7 +188,7
188 188 handler = WebhookDataHandler(template_url, headers)
189 189
190 190 url_calls = handler(event, data)
191 log.debug('webhook: calling following urls: %s', [x[0] for x in url_calls])
191 log.debug('Webhook: calling following urls: %s', [x[0] for x in url_calls])
192 192
193 193 run_task(post_to_webhook, url_calls, self.settings)
194 194
@@ -78,15 +78,18
78 78 ('http://server.com/${repo_name}/${pull_request_id}',
79 79 ['http://server.com/foo/999']),
80 80 ('http://server.com/${repo_name}/${pull_request_url}',
81 ['http://server.com/foo/http://pr-url.com']),
81 ['http://server.com/foo/http%3A//pr-url.com']),
82 ('http://server.com/${repo_name}/${pull_request_url}/?TITLE=${pull_request_title}',
83 ['http://server.com/foo/http%3A//pr-url.com/?TITLE=example-pr-title%20Ticket%20%23123']),
84 ('http://server.com/${repo_name}/?SHADOW_URL=${pull_request_shadow_url}',
85 ['http://server.com/foo/?SHADOW_URL=http%3A//pr-url.com/repository']),
82 86 ])
83 def test_webook_parse_url_for_pull_request_event(
84 base_data, template, expected_urls):
87 def test_webook_parse_url_for_pull_request_event(base_data, template, expected_urls):
85 88
86 89 base_data['pullrequest'] = {
87 90 'pull_request_id': 999,
88 91 'url': 'http://pr-url.com',
89 'title': 'example-pr-title',
92 'title': 'example-pr-title Ticket #123',
90 93 'commits_uid': 'abcdefg1234',
91 94 'shadow_url': 'http://pr-url.com/repository'
92 95 }
Comments 0
You need to be logged in to leave comments. Login now