diff --git a/errbot/core_plugins/wsview.py b/errbot/core_plugins/wsview.py index 589ef8267..c63cd0021 100644 --- a/errbot/core_plugins/wsview.py +++ b/errbot/core_plugins/wsview.py @@ -46,16 +46,19 @@ def route(obj): func.__name__ + "_" + "_".join(verbs), func, form_param, raw ) - # Change existing rule. + # Update existing rule if present; otherwise register a new rule for rule in flask_app.url_map._rules: if rule.rule == uri_rule: flask_app.view_functions[rule.endpoint] = callable_view - return - - # Add a new rule - flask_app.add_url_rule( - uri_rule, view_func=callable_view, methods=verbs, strict_slashes=False - ) + break + else: + flask_app._got_first_request = False + flask_app.add_url_rule( + uri_rule, + view_func=callable_view, + methods=verbs, + strict_slashes=False, + ) class WebView(View): diff --git a/tests/webhooks_test.py b/tests/webhooks_test.py index de32e6b03..d8ed11db8 100644 --- a/tests/webhooks_test.py +++ b/tests/webhooks_test.py @@ -210,3 +210,71 @@ def test_lambda_webhook(webhook_testbot): requests.post("http://localhost:{}/lambda".format(WEBSERVER_PORT)).status_code == 200 ) + + +def test_route_webhook_after_first_request(webhook_testbot): + from errbot import BotPlugin, webhook + from errbot.core_plugins.wsview import route + + assert ( + requests.post( + f"http://localhost:{WEBSERVER_PORT}/echo", + JSONOBJECT, + ).status_code + == 200 + ) + + class DynamicPlugin(BotPlugin): + @webhook("/dynamic/late_webhook") + def late_webhook(self, payload): + return "late webhook ok" + + @webhook("/dynamic/late_webhook2") + def late_webhook2(self, payload): + return "late webhook2 ok" + + plugin = DynamicPlugin(webhook_testbot.bot) + route(plugin) + + resp = requests.post(f"http://localhost:{WEBSERVER_PORT}/dynamic/late_webhook") + assert resp.status_code == 200 + assert resp.text == "late webhook ok" + + resp2 = requests.post(f"http://localhost:{WEBSERVER_PORT}/dynamic/late_webhook2") + assert resp2.status_code == 200 + assert resp2.text == "late webhook2 ok" + + +def test_route_webhook_reload_updates_all_methods(webhook_testbot): + from errbot import BotPlugin, webhook + from errbot.core_plugins.wsview import route + + class MultiWebhookPlugin(BotPlugin): + @webhook("/reload/w1") + def w1(self, payload): + return "v1_w1" + + @webhook("/reload/w2") + def w2(self, payload): + return "v1_w2" + + plugin_v1 = MultiWebhookPlugin(webhook_testbot.bot) + route(plugin_v1) + + assert requests.post(f"http://localhost:{WEBSERVER_PORT}/reload/w1").text == "v1_w1" + assert requests.post(f"http://localhost:{WEBSERVER_PORT}/reload/w2").text == "v1_w2" + + class MultiWebhookPluginV2(BotPlugin): + @webhook("/reload/w1") + def w1(self, payload): + return "v2_w1" + + @webhook("/reload/w2") + def w2(self, payload): + return "v2_w2" + + plugin_v2 = MultiWebhookPluginV2(webhook_testbot.bot) + route(plugin_v2) + + assert requests.post(f"http://localhost:{WEBSERVER_PORT}/reload/w1").text == "v2_w1" + assert requests.post(f"http://localhost:{WEBSERVER_PORT}/reload/w2").text == "v2_w2"