diff --git a/internal/certdeploy/deployers/sp_webhook.go b/internal/certdeploy/deployers/sp_webhook.go index 271fc744c..c53ff7304 100644 --- a/internal/certdeploy/deployers/sp_webhook.go +++ b/internal/certdeploy/deployers/sp_webhook.go @@ -43,6 +43,7 @@ func init() { WebhookData: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "webhookData", credentials.DataString), Method: credentials.Method, Headers: mergedHeaders, + Timeout: xmaps.GetInt32(options.ProviderExtendedConfig, "timeout"), AllowInsecureConnections: credentials.AllowInsecureConnections, }) return provider, err diff --git a/internal/notify/notifiers/sp_webhook.go b/internal/notify/notifiers/sp_webhook.go index db0c44128..7cacd0a64 100644 --- a/internal/notify/notifiers/sp_webhook.go +++ b/internal/notify/notifiers/sp_webhook.go @@ -43,6 +43,7 @@ func init() { WebhookData: xmaps.GetOrDefaultString(options.ProviderExtendedConfig, "webhookData", credentials.DataString), Method: credentials.Method, Headers: mergedHeaders, + Timeout: xmaps.GetInt32(options.ProviderExtendedConfig, "timeout"), AllowInsecureConnections: credentials.AllowInsecureConnections, }) return provider, err diff --git a/pkg/core/notifier/providers/webhook/webhook.go b/pkg/core/notifier/providers/webhook/webhook.go index 09ae91e3d..3f57da7dd 100644 --- a/pkg/core/notifier/providers/webhook/webhook.go +++ b/pkg/core/notifier/providers/webhook/webhook.go @@ -27,6 +27,9 @@ type NotifierProviderConfig struct { Method string `json:"method,omitempty"` // 请求标头。 Headers map[string]string `json:"headers,omitempty"` + // 请求超时(单位:秒)。 + // 零值时默认值 30。 + Timeout int32 `json:"timeout,omitempty"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } @@ -48,6 +51,9 @@ func NewNotifierProvider(config *NotifierProviderConfig) (*NotifierProvider, err SetTimeout(30 * time.Second). SetRetryCount(3). SetRetryWaitTime(5 * time.Second) + if config.Timeout > 0 { + client.SetTimeout(time.Duration(config.Timeout) * time.Second) + } if config.AllowInsecureConnections { client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/pkg/core/ssl-deployer/providers/webhook/webhook.go b/pkg/core/ssl-deployer/providers/webhook/webhook.go index 2bf1aa145..9de2d8fce 100644 --- a/pkg/core/ssl-deployer/providers/webhook/webhook.go +++ b/pkg/core/ssl-deployer/providers/webhook/webhook.go @@ -28,6 +28,9 @@ type SSLDeployerProviderConfig struct { Method string `json:"method,omitempty"` // 请求标头。 Headers map[string]string `json:"headers,omitempty"` + // 请求超时(单位:秒)。 + // 零值时默认值 30。 + Timeout int32 `json:"timeout,omitempty"` // 是否允许不安全的连接。 AllowInsecureConnections bool `json:"allowInsecureConnections,omitempty"` } @@ -49,6 +52,9 @@ func NewSSLDeployerProvider(config *SSLDeployerProviderConfig) (*SSLDeployerProv SetTimeout(30 * time.Second). SetRetryCount(3). SetRetryWaitTime(5 * time.Second) + if config.Timeout > 0 { + client.SetTimeout(time.Duration(config.Timeout) * time.Second) + } if config.AllowInsecureConnections { client.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: true}) } diff --git a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderWebhook.tsx b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderWebhook.tsx index d6d111b9c..7c288dcab 100644 --- a/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderWebhook.tsx +++ b/ui/src/components/workflow/designer/forms/BizDeployNodeConfigFieldsProviderWebhook.tsx @@ -1,5 +1,5 @@ import { getI18n, useTranslation } from "react-i18next"; -import { Form } from "antd"; +import { Form, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -51,6 +51,17 @@ const BizDeployNodeConfigFieldsProviderWebhook = () => { } /> + + + + ); }; @@ -76,6 +87,10 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) return false; } }, t("workflow_node.deploy.form.webhook_data.errmsg.json_invalid")), + timeout: z.preprocess( + (v) => (v == null || v === "" ? void 0 : Number(v)), + z.number().int(t("workflow_node.deploy.form.webhook_timeout.placeholder")).gte(1, t("workflow_node.deploy.form.webhook_timeout.placeholder")).nullish() + ), }); }; diff --git a/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProviderWebhook.tsx b/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProviderWebhook.tsx index 247f568f4..0f88205a1 100644 --- a/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProviderWebhook.tsx +++ b/ui/src/components/workflow/designer/forms/BizNotifyNodeConfigFieldsProviderWebhook.tsx @@ -1,5 +1,5 @@ import { getI18n, useTranslation } from "react-i18next"; -import { Form } from "antd"; +import { Form, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -51,6 +51,17 @@ const BizNotifyNodeConfigFieldsProviderWebhook = () => { } /> + + + + ); }; @@ -76,6 +87,10 @@ const getSchema = ({ i18n = getI18n() }: { i18n?: ReturnType }) return false; } }, t("workflow_node.notify.form.webhook_data.errmsg.json_invalid")), + timeout: z.preprocess( + (v) => (v == null || v === "" ? void 0 : Number(v)), + z.number().int(t("workflow_node.notify.form.webhook_timeout.placeholder")).gte(1, t("workflow_node.notify.form.webhook_timeout.placeholder")).nullish() + ), }); }; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 2603421ff..bbf441815 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -65,7 +65,7 @@ "access.form.acmedns_credentials.label": "ACME-DNS credentials", "access.form.acmedns_credentials.placeholder": "Please enter ACME-DNS credentials", "access.form.acmedns_credentials.tooltip": "For more information, see https://github.com/joohoi/acme-dns", - "access.form.acmedns_credentials.errmsg.json_invalid": "Please enter a valiod JSON string", + "access.form.acmedns_credentials.errmsg.json_invalid": "Please enter a valid JSON string", "access.form.acmehttpreq_endpoint.label": "Endpoint", "access.form.acmehttpreq_endpoint.placeholder": "Please enter endpoint", "access.form.acmehttpreq_endpoint.tooltip": "For more information, see https://go-acme.github.io/lego/dns/httpreq/", @@ -518,7 +518,7 @@ "access.form.webhook_headers.placeholder": "Please enter Webhook request headers", "access.form.webhook_headers.errmsg.invalid": "Please enter a valid request headers", "access.form.webhook_headers.tooltip": "Example:
Content-Type: application/json
User-Agent: certimate
", - "access.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", + "access.form.webhook_data.errmsg.json_invalid": "Please enter a valid JSON string", "access.form.webhook_data.label": "Webhook data (Optional)", "access.form.webhook_data.placeholder": "Please enter the default Webhook data", "access.form.webhook_data.help": "Notes: It can be overrided in the workflows.", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index d62db857c..958569f65 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -92,8 +92,8 @@ "workflow_node.apply.form.validity_lifetime.placeholder": "Please enter certificate's validity lifetime", "workflow_node.apply.form.validity_lifetime.help": "Notes: Not all CAs support this feature.", "workflow_node.apply.form.validity_lifetime.tooltip": "It determines the NotAfter field of the certificate in the ACME protocol. If you don't understand this option, just keep it by default.", - "workflow_node.apply.form.validity_lifetime.units.h": "Hour(s)", - "workflow_node.apply.form.validity_lifetime.units.d": "Day(s)", + "workflow_node.apply.form.validity_lifetime.units.h": "hours", + "workflow_node.apply.form.validity_lifetime.units.d": "days", "workflow_node.apply.form.acme_profile.label": "Certificate ACME profile (Optional)", "workflow_node.apply.form.acme_profile.placeholder": "Please enter certificate's ACME profile", "workflow_node.apply.form.acme_profile.help": "Notes: Not all CAs support this feature.", @@ -1002,7 +1002,10 @@ "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data", "workflow_node.deploy.form.webhook_data.help": "Notes: Leave it blank to use the default Webhook data provided by the credential.", "workflow_node.deploy.form.webhook_data.guide": "
Supported variables:
  1. ${DOMAIN}: The primary domain of the certificate (CommonName).
  2. ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
  3. ${CERTIFICATE}: The PEM format content of the certificate file.
  4. ${SERVER_CERTIFICATE}: The PEM format content of the server certificate file.
  5. ${INTERMEDIA_CERTIFICATE}: The PEM format content of the intermediate CA certificate file.
  6. ${PRIVATE_KEY}: The PEM format content of the private key file.

Please visit the credentials page for addtional notes.", - "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", + "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "Please enter a valid JSON string", + "workflow_node.deploy.form.webhook_timeout.label": "Webhook timeout (Optional)", + "workflow_node.deploy.form.webhook_timeout.placeholder": "Please enter Webhook timeout", + "workflow_node.deploy.form.webhook_timeout.unit": "seconds", "workflow_node.deploy.form.skip_on_last_succeeded.label": "Repeated deployment", "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "If the last deployment was successful, ", "workflow_node.deploy.form.skip_on_last_succeeded.suffix": " to re-deploy.", @@ -1047,7 +1050,10 @@ "workflow_node.notify.form.webhook_data.placeholder": "Please enter Webhook data", "workflow_node.notify.form.webhook_data.help": "Notes: Leave it blank to use the default Webhook data provided by the credential.", "workflow_node.notify.form.webhook_data.guide": "
Supported variables:
  1. ${SUBJECT}: The subject of notification.
  2. ${MESSAGE}: The message of notification.

Please visit the credentials page for addtional notes.", - "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", + "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "Please enter a valid JSON string", + "workflow_node.notify.form.webhook_timeout.label": "Webhook timeout (Optional)", + "workflow_node.notify.form.webhook_timeout.placeholder": "Please enter Webhook timeout", + "workflow_node.notify.form.webhook_timeout.unit": "seconds", "workflow_node.notify.form.skip_on_all_prev_skipped.label": "Silent behavior", "workflow_node.notify.form.skip_on_all_prev_skipped.prefix": "If all the previous nodes were skipped, ", "workflow_node.notify.form.skip_on_all_prev_skipped.suffix": " to notify.", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index c9a30717b..feb992b7f 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -1001,6 +1001,9 @@ "workflow_node.deploy.form.webhook_data.help": "提示:不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", "workflow_node.deploy.form.webhook_data.guide": "
支持的变量:
  1. ${DOMAIN}:证书的主域名(即 CommonName)。
  2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
  3. ${CERTIFICATE}:证书文件 PEM 格式内容。
  4. ${SERVER_CERTIFICATE}:证书文件(仅含服务器证书)PEM 格式内容。
  5. ${INTERMEDIA_CERTIFICATE}:证书文件(仅含中间证书)PEM 格式内容。
  6. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

其他注意事项请前往授权凭据页面查看。", "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", + "workflow_node.deploy.form.webhook_timeout.label": "Webhook 超时时间(可选)", + "workflow_node.deploy.form.webhook_timeout.placeholder": "请输入 Webhook 超时时间", + "workflow_node.deploy.form.webhook_timeout.unit": "秒", "workflow_node.deploy.form.skip_on_last_succeeded.label": "重复部署", "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,再次运行工作流时", "workflow_node.deploy.form.skip_on_last_succeeded.suffix": "此部署节点。", @@ -1046,6 +1049,9 @@ "workflow_node.notify.form.webhook_data.help": "提示:不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", "workflow_node.notify.form.webhook_data.guide": "
支持的变量:
  1. ${SUBJECT}:通知主题。
  2. ${MESSAGE}:通知内容。

其他注意事项请前往授权凭据页面查看。", "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", + "workflow_node.notify.form.webhook_timeout.label": "Webhook 超时时间(可选)", + "workflow_node.notify.form.webhook_timeout.placeholder": "请输入 Webhook 超时时间", + "workflow_node.notify.form.webhook_timeout.unit": "秒", "workflow_node.notify.form.skip_on_all_prev_skipped.label": "静默行为", "workflow_node.notify.form.skip_on_all_prev_skipped.prefix": "当前序申请、上传、部署等节点均已跳过执行时,", "workflow_node.notify.form.skip_on_all_prev_skipped.suffix": "此通知节点。",