diff --git a/back/config/util.ts b/back/config/util.ts index 92609cb0..363ac1b5 100644 --- a/back/config/util.ts +++ b/back/config/util.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import got from 'got'; import iconv from 'iconv-lite'; import { exec } from 'child_process'; +import FormData from 'form-data'; export function getFileContentByName(fileName: string) { if (fs.existsSync(fileName)) { @@ -355,3 +356,61 @@ export function promiseExec(command: string): Promise { ); }); } + +export function parseHeaders(headers: string) { + if (!headers) return {}; + + const parsed: any = {}; + let key; + let val; + let i; + + headers && headers.split('\n').forEach(function parser(line) { + i = line.indexOf(':'); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + + if (!key) { + return; + } + + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + }); + + return parsed; +}; + +export function parseBody(body: string, contentType: 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded') { + if (!body) return ''; + + const parsed: any = {}; + let key; + let val; + let i; + + body && body.split('\n').forEach(function parser(line) { + i = line.indexOf(':'); + key = line.substring(0, i).trim().toLowerCase(); + val = line.substring(i + 1).trim(); + + if (!key || parsed[key]) { + return; + } + + parsed[key] = val; + }); + + switch (contentType) { + case 'multipart/form-data': + return Object.keys(parsed).reduce((p, c) => { + p.append(c, parsed[c]) + return p; + }, new FormData()); + case 'application/x-www-form-urlencoded': + return Object.keys(parsed).reduce((p, c) => { + return p ? `${p}&${c}=${parsed[c]}` : `${c}=${parsed[c]}`; + }); + } + + return parsed; +}; \ No newline at end of file diff --git a/back/data/notify.ts b/back/data/notify.ts index 6a3ccc7c..3197bb85 100644 --- a/back/data/notify.ts +++ b/back/data/notify.ts @@ -91,8 +91,8 @@ export class EmailNotification extends NotificationBaseInfo { } export class WebhookNotification extends NotificationBaseInfo { - public webhookHeaders: IncomingHttpHeaders = {}; - public webhookBody: any = {}; + public webhookHeaders: string = ''; + public webhookBody: string = ''; public webhookUrl: string = ''; public webhookMethod: 'GET' | 'POST' | 'PUT' = 'GET'; public webhookContentType: 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded' = 'application/json'; diff --git a/back/services/notify.ts b/back/services/notify.ts index 538bd19b..1c260b5c 100644 --- a/back/services/notify.ts +++ b/back/services/notify.ts @@ -6,6 +6,7 @@ import got from 'got'; import nodemailer from 'nodemailer'; import crypto from 'crypto'; import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent'; +import { parseBody, parseHeaders } from '../config/util'; @Service() export default class NotificationService { @@ -388,10 +389,12 @@ export default class NotificationService { const { webhookUrl, webhookBody, webhookHeaders, webhookMethod, webhookContentType } = this.params; - const bodyParam = this.formatBody(webhookContentType, webhookBody); + const headers = parseHeaders(webhookHeaders); + const body = parseBody(webhookBody, webhookContentType); + const bodyParam = this.formatBody(webhookContentType, body); const options = { method: webhookMethod, - headers: webhookHeaders, + headers, timeout: this.timeout, retry: 0, allowGetBody: true, diff --git a/package.json b/package.json index 5b61dae9..d6680cd4 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "express": "^4.17.3", "express-jwt": "^6.1.1", "express-urlrewrite": "^1.4.0", + "form-data": "^4.0.0", "got": "^11.8.2", "hpagent": "^0.1.2", "iconv-lite": "^0.6.3", diff --git a/src/pages/setting/notification.tsx b/src/pages/setting/notification.tsx index 885ffbc0..ec205f8b 100644 --- a/src/pages/setting/notification.tsx +++ b/src/pages/setting/notification.tsx @@ -13,15 +13,11 @@ const NotificationSetting = ({ data }: any) => { const [form] = Form.useForm(); const handleOk = (values: any) => { - const { type, webhookBody, webhookContentType } = values; + const { type } = values; if (type == 'closed') { values.type = ''; } - if (type === 'webhook') { - values.webhookHeaders = { ...parseHeaders(values.webhookHeaders) }; - values.webhookBody = parseBody(webhookBody, webhookContentType); - } request .put(`${config.apiPrefix}user/notification`, { data: { diff --git a/src/utils/index.ts b/src/utils/index.ts index 0d455aa8..9fa2a510 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -266,64 +266,5 @@ export function depthFirstSearch< } })(c); - console.log(keys); return c; } - -export function parseHeaders(headers: string) { - if (!headers) return {}; - - const parsed: any = {}; - let key; - let val; - let i; - - headers && headers.split('\n').forEach(function parser(line) { - i = line.indexOf(':'); - key = line.substring(0, i).trim().toLowerCase(); - val = line.substring(i + 1).trim(); - - if (!key) { - return; - } - - parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; - }); - - return parsed; -}; - -export function parseBody(body: string, contentType: 'application/json' | 'multipart/form-data' | 'application/x-www-form-urlencoded') { - if (!body) return ''; - - const parsed: any = {}; - let key; - let val; - let i; - - body && body.split('\n').forEach(function parser(line) { - i = line.indexOf(':'); - key = line.substring(0, i).trim().toLowerCase(); - val = line.substring(i + 1).trim(); - - if (!key || parsed[key]) { - return; - } - - parsed[key] = val; - }); - - switch (contentType) { - case 'multipart/form-data': - return Object.keys(parsed).reduce((p, c) => { - p.append(c, parsed[c]) - return p; - }, new FormData()); - case 'application/x-www-form-urlencoded': - return Object.keys(parsed).reduce((p, c) => { - return p ? `${p}&${c}=${parsed[c]}` : `${c}=${parsed[c]}`; - }); - } - - return parsed; -}; \ No newline at end of file