mirror of https://github.com/zulip/zulip.git
devtools: Add custom HTTP headers support to the integrations dev panel.
This commit introduces a simple field where the user can now specify custom HTTP headers. This commit does not introduce an improved system for storing HTTP headers as fixtures - such a change would modify both the existing unit tests as well as this devtool.
This commit is contained in:
parent
64b4fd5923
commit
2bd9c8cb42
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 30 KiB |
|
@ -17,6 +17,7 @@ var clear_handlers = {
|
|||
integration_name: function () { $('#integration_name').children()[0].selected = true; },
|
||||
fixture_name: function () { $('#fixture_name').empty(); },
|
||||
fixture_body: function () { $("#fixture_body")[0].value = ""; },
|
||||
custom_http_headers: function () { $("#custom_http_headers")[0].value = ""; },
|
||||
};
|
||||
|
||||
function clear_elements(elements) {
|
||||
|
@ -141,7 +142,7 @@ function get_fixtures(integration_name) {
|
|||
/* Request fixtures from the backend for any integrations that we don't already have fixtures
|
||||
for (which would be stored in the JS variable called "loaded_fixtures"). */
|
||||
if (integration_name === "") {
|
||||
clear_elements(["fixture_body", "fixture_name", "URL", "message"]);
|
||||
clear_elements(["custom_http_headers", "fixture_body", "fixture_name", "URL", "message"]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -190,9 +191,21 @@ function send_webhook_fixture_message() {
|
|||
return;
|
||||
}
|
||||
|
||||
var custom_headers = $("#custom_http_headers").val();
|
||||
if (custom_headers !== "") {
|
||||
// JSON.parse("") would trigger an error, as empty strings do not qualify as JSON.
|
||||
try {
|
||||
// Let JavaScript validate the JSON for us.
|
||||
custom_headers = JSON.stringify(JSON.parse(custom_headers));
|
||||
} catch (err) {
|
||||
set_message("Custom HTTP headers are not in a valid JSON format.", "warning");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
channel.post({
|
||||
url: "/devtools/integrations/check_send_webhook_fixture_message",
|
||||
data: {url: url, body: body},
|
||||
data: {url: url, body: body, custom_headers: custom_headers},
|
||||
beforeSend: function (xhr) {xhr.setRequestHeader('X-CSRFToken', csrftoken);},
|
||||
success: function () {
|
||||
// If the previous fixture body was sent successfully, then we should change the success
|
||||
|
@ -214,7 +227,7 @@ function send_webhook_fixture_message() {
|
|||
// Initialization
|
||||
$(function () {
|
||||
clear_elements(["stream_name", "topic_name", "URL", "bot_name", "integration_name",
|
||||
"fixture_name", "fixture_body", "message"]);
|
||||
"fixture_name", "custom_http_headers", "fixture_body", "message"]);
|
||||
|
||||
var potential_default_bot = $("#bot_name")[0][1];
|
||||
if (potential_default_bot !== undefined) {
|
||||
|
@ -222,7 +235,7 @@ $(function () {
|
|||
}
|
||||
|
||||
$('#integration_name').change(function () {
|
||||
clear_elements(["fixture_body", "fixture_name", "message"]);
|
||||
clear_elements(["custom_http_headers", "fixture_body", "fixture_name", "message"]);
|
||||
var integration_name = $(this).children("option:selected").val();
|
||||
get_fixtures(integration_name);
|
||||
update_url();
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
padding: 10px;
|
||||
}
|
||||
|
||||
#custom_http_headers {
|
||||
height: 200px;
|
||||
width: 700px;
|
||||
}
|
||||
|
||||
#fixture_body {
|
||||
height: 500px;
|
||||
width: 700px;
|
||||
|
|
|
@ -237,17 +237,19 @@ This is the GUI tool.
|
|||
|
||||
1. Run `./tools/run-dev.py` then go to http://localhost:9991/devtools/integrations/.
|
||||
|
||||
2. Set the following mandatory fields:
|
||||
- **Bot** - Any incoming webhook bot.
|
||||
- **Integration** - One of the integrations.
|
||||
- **Fixture** - Though not mandatory, it's recommended that you select one and then tweak it if necessary.
|
||||
2. Set the following mandatory fields:
|
||||
**Bot** - Any incoming webhook bot.
|
||||
**Integration** - One of the integrations.
|
||||
**Fixture** - Though not mandatory, it's recommended that you select one and then tweak it if necessary.
|
||||
The remaining fields are optional, and the URL will automatically be generated.
|
||||
|
||||
3. Click **Send**!
|
||||
|
||||
By opening Zulip in one tab and this tool in another, you can quickly tweak
|
||||
By opening Zulip in one tab and then this tool in another, you can quickly tweak
|
||||
your code and send sample messages for many different test fixtures.
|
||||
|
||||
Note: Custom HTTP Headers must be entered as a JSON dictionary, if you want to use any in the first place that is.
|
||||
Feel free to use 4-spaces as tabs for indentation if you'd like!
|
||||
|
||||
Your sample notification may look like:
|
||||
|
||||
|
|
|
@ -65,6 +65,15 @@
|
|||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2" class="center-text pad-top"><b>Custom HTTP Headers</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="form-group">
|
||||
<textarea id="custom_http_headers" class="form-control"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td colspan="2" class="center-text pad-top"><b>JSON Body</b></td>
|
||||
</tr>
|
||||
|
|
|
@ -15,7 +15,8 @@ class TestIntegrationsDevPanel(ZulipTestCase):
|
|||
|
||||
data = {
|
||||
"url": url,
|
||||
"body": body
|
||||
"body": body,
|
||||
"custom_headers": "",
|
||||
}
|
||||
|
||||
response = self.client_post(target_url, data)
|
||||
|
@ -24,7 +25,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
|
|||
expected_response = {"result": "error", "msg": "Internal server error"}
|
||||
self.assertEqual(ujson.loads(response.content), expected_response)
|
||||
|
||||
def test_check_send_webhook_fixture_message_for_success(self) -> None:
|
||||
def test_check_send_webhook_fixture_message_for_success_without_headers(self) -> None:
|
||||
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
|
||||
url = "/api/v1/external/airbrake?api_key={key}&stream=Denmark&topic=Airbrake Notifications".format(key=bot.api_key)
|
||||
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
|
||||
|
@ -34,6 +35,7 @@ class TestIntegrationsDevPanel(ZulipTestCase):
|
|||
data = {
|
||||
"url": url,
|
||||
"body": body,
|
||||
"custom_headers": "",
|
||||
}
|
||||
|
||||
response = self.client_post(target_url, data)
|
||||
|
@ -45,6 +47,28 @@ class TestIntegrationsDevPanel(ZulipTestCase):
|
|||
self.assertEqual(Stream.objects.get(id=latest_msg.recipient.type_id).name, "Denmark")
|
||||
self.assertEqual(latest_msg.topic_name(), "Airbrake Notifications")
|
||||
|
||||
def test_check_send_webhook_fixture_message_for_success_with_headers(self) -> None:
|
||||
bot = get_user('webhook-bot@zulip.com', self.zulip_realm)
|
||||
url = "/api/v1/external/github?api_key={key}&stream=Denmark&topic=GitHub Notifications".format(key=bot.api_key)
|
||||
target_url = "/devtools/integrations/check_send_webhook_fixture_message"
|
||||
with open("zerver/webhooks/github/fixtures/ping_organization.json", "r") as f:
|
||||
body = f.read()
|
||||
|
||||
data = {
|
||||
"url": url,
|
||||
"body": body,
|
||||
"custom_headers": ujson.dumps({"X_GITHUB_EVENT": "ping"}),
|
||||
}
|
||||
|
||||
response = self.client_post(target_url, data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
latest_msg = Message.objects.latest('id')
|
||||
expected_message = "GitHub webhook has been successfully configured by eeshangarg."
|
||||
self.assertEqual(latest_msg.content, expected_message)
|
||||
self.assertEqual(Stream.objects.get(id=latest_msg.recipient.type_id).name, "Denmark")
|
||||
self.assertEqual(latest_msg.topic_name(), "GitHub Notifications")
|
||||
|
||||
def test_get_fixtures_for_nonexistant_integration(self) -> None:
|
||||
target_url = "/devtools/integrations/somerandomnonexistantintegration/fixtures"
|
||||
response = self.client_get(target_url)
|
||||
|
|
|
@ -10,6 +10,7 @@ from zerver.lib.integrations import WEBHOOK_INTEGRATIONS
|
|||
from zerver.lib.request import has_request_variables, REQ
|
||||
from zerver.lib.response import json_success, json_error
|
||||
from zerver.models import UserProfile, get_realm
|
||||
from zerver.management.commands.send_webhook_fixture_message import parse_headers
|
||||
|
||||
|
||||
ZULIP_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../../../')
|
||||
|
@ -58,10 +59,19 @@ def get_fixtures(request: HttpResponse,
|
|||
@has_request_variables
|
||||
def check_send_webhook_fixture_message(request: HttpRequest,
|
||||
url: str=REQ(),
|
||||
body: str=REQ()) -> HttpResponse:
|
||||
body: str=REQ(),
|
||||
custom_headers: str=REQ()) -> HttpResponse:
|
||||
client = Client()
|
||||
realm = get_realm("zulip")
|
||||
response = client.post(url, body, content_type="application/json", HTTP_HOST=realm.host)
|
||||
try:
|
||||
headers = parse_headers(custom_headers)
|
||||
except ValueError as ve:
|
||||
return json_error("Custom HTTP headers are not in a valid JSON format. {}".format(ve)) # nolint
|
||||
if not headers:
|
||||
headers = {}
|
||||
http_host = headers.pop("HTTP_HOST", realm.host)
|
||||
content_type = headers.pop("HTTP_CONTENT_TYPE", "application/json")
|
||||
response = client.post(url, body, content_type=content_type, HTTP_HOST=http_host, **headers)
|
||||
if response.status_code == 200:
|
||||
return json_success()
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue