Merge pull request #3172 from Gulianrdgd/feature-response-headers

Feature response headers
This commit is contained in:
Owen Schwartz
2026-09-21 15:16:24 -04:00
committed by GitHub
30 changed files with 290 additions and 128 deletions
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Опити за повторно", "retryAttempts": "Опити за повторно",
"expectedResponseCodes": "Очаквани кодове за отговор", "expectedResponseCodes": "Очаквани кодове за отговор",
"expectedResponseCodesDescription": "HTTP статус код, указващ здравословно състояние. Ако бъде оставено празно, между 200-300 се счита за здравословно.", "expectedResponseCodesDescription": "HTTP статус код, указващ здравословно състояние. Ако бъде оставено празно, между 200-300 се счита за здравословно.",
"customHeaders": "Персонализирани заглавия", "customRequestHeaders": "Персонализирани заглавия на заявката",
"customHeadersDescription": "Add custom headers to be sent when proxying requests. One per line in the format Header-Name: value", "customRequestHeadersDescription": "Заглавия на заявката, изпратени до целевите сървъри. По едно на ред: Заглавие-Име: стойност",
"customResponseHeaders": "Персонализирани заглавия на отговора",
"customResponseHeadersDescription": "Заглавия на отговора, върнати на клиента. По едно на ред: Заглавие-Име: стойност",
"headersValidationError": "Заглавията трябва да бъдат във формат: Име на заглавието: стойност.", "headersValidationError": "Заглавията трябва да бъдат във формат: Име на заглавието: стойност.",
"saveHealthCheck": "Запазване на проверка на здравето", "saveHealthCheck": "Запазване на проверка на здравето",
"healthCheckSaved": "Проверка на здравето е запазена", "healthCheckSaved": "Проверка на здравето е запазена",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Opakovat pokusy", "retryAttempts": "Opakovat pokusy",
"expectedResponseCodes": "Očekávané kódy odezvy", "expectedResponseCodes": "Očekávané kódy odezvy",
"expectedResponseCodesDescription": "HTTP kód stavu, který označuje zdravý stav. Ponecháte-li prázdné, 200-300 je považováno za zdravé.", "expectedResponseCodesDescription": "HTTP kód stavu, který označuje zdravý stav. Ponecháte-li prázdné, 200-300 je považováno za zdravé.",
"customHeaders": "Vlastní záhlaví", "customRequestHeaders": "Vlastní záhlaví požadavku",
"customHeadersDescription": "Záhlaví oddělená nová řádka: hodnota", "customRequestHeadersDescription": "Záhlaví požadavku odeslaná do cílů. Jedno na řádek: Název-záhlaví: hodnota",
"customResponseHeaders": "Vlastní záhlaví odpovědi",
"customResponseHeadersDescription": "Záhlaví odpovědi vrácená klientovi. Jedno na řádek: Název-záhlaví: hodnota",
"headersValidationError": "Headers must be in the format: Header-Name: value.", "headersValidationError": "Headers must be in the format: Header-Name: value.",
"saveHealthCheck": "Uložit kontrolu stavu", "saveHealthCheck": "Uložit kontrolu stavu",
"healthCheckSaved": "Kontrola stavu uložena", "healthCheckSaved": "Kontrola stavu uložena",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Forsøg igen", "retryAttempts": "Forsøg igen",
"expectedResponseCodes": "Forventede svarkoder", "expectedResponseCodes": "Forventede svarkoder",
"expectedResponseCodesDescription": "HTTP-statuskode som indikerer sund status. Hvis den bliver stående tom, regnes 200-300 som sund.", "expectedResponseCodesDescription": "HTTP-statuskode som indikerer sund status. Hvis den bliver stående tom, regnes 200-300 som sund.",
"customHeaders": "Brugerdefinerede headers", "customRequestHeaders": "Brugerdefinerede anmodnings-headers",
"customHeadersDescription": "Headers som er adskilt med linje: Overskriftsnavn: værdi", "customRequestHeadersDescription": "Anmodnings-headers som sendes til destinationerne. Én pr. linje: Header-navn: værdi",
"customResponseHeaders": "Brugerdefinerede svar-headers",
"customResponseHeadersDescription": "Svar-headers som sendes tilbage til klienten. Én pr. linje: Header-navn: værdi",
"headersValidationError": "Header skal være i formatet: header-navn: værdi.", "headersValidationError": "Header skal være i formatet: header-navn: værdi.",
"saveHealthCheck": "Gem Sundhedstjek", "saveHealthCheck": "Gem Sundhedstjek",
"healthCheckSaved": "Sundhedstjek Gemt", "healthCheckSaved": "Sundhedstjek Gemt",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Wiederholungsversuche", "retryAttempts": "Wiederholungsversuche",
"expectedResponseCodes": "Erwartete Antwortcodes", "expectedResponseCodes": "Erwartete Antwortcodes",
"expectedResponseCodesDescription": "HTTP-Statuscode, der einen gesunden Zustand anzeigt. Wenn leer gelassen, wird 200-300 als gesund angesehen.", "expectedResponseCodesDescription": "HTTP-Statuscode, der einen gesunden Zustand anzeigt. Wenn leer gelassen, wird 200-300 als gesund angesehen.",
"customHeaders": "Eigene Kopfzeilen", "customRequestHeaders": "Eigene Anfrage-Header",
"customHeadersDescription": "Header neue Zeile getrennt: Header-Name: Wert", "customRequestHeadersDescription": "Anfrage-Header, die an die Ziele gesendet werden. Eine pro Zeile: Header-Name: Wert",
"customResponseHeaders": "Eigene Antwort-Header",
"customResponseHeadersDescription": "Antwort-Header, die an den Client zurückgesendet werden. Eine pro Zeile: Header-Name: Wert",
"headersValidationError": "Header müssen im Format Header-Name: Wert sein.", "headersValidationError": "Header müssen im Format Header-Name: Wert sein.",
"saveHealthCheck": "Gesundheits-Check speichern", "saveHealthCheck": "Gesundheits-Check speichern",
"healthCheckSaved": "Gesundheits-Check gespeichert", "healthCheckSaved": "Gesundheits-Check gespeichert",
+4 -2
View File
@@ -2829,8 +2829,10 @@
"retryAttempts": "Retry Attempts", "retryAttempts": "Retry Attempts",
"expectedResponseCodes": "Expected Response Codes", "expectedResponseCodes": "Expected Response Codes",
"expectedResponseCodesDescription": "HTTP status code that indicates healthy status. If left blank, 200-300 is considered healthy.", "expectedResponseCodesDescription": "HTTP status code that indicates healthy status. If left blank, 200-300 is considered healthy.",
"customHeaders": "Custom Request Headers", "customRequestHeaders": "Custom Request Headers",
"customHeadersDescription": "Request headers sent to the downstream targets. Headers new line separated: Header-Name: value", "customRequestHeadersDescription": "Request headers sent to the downstream targets. One per line: Header-Name: value",
"customResponseHeaders": "Custom Response Headers",
"customResponseHeadersDescription": "Response headers sent back to the client. One per line: Header-Name: value",
"headersValidationError": "Headers must be in the format: Header-Name: value", "headersValidationError": "Headers must be in the format: Header-Name: value",
"saveHealthCheck": "Save Health Check", "saveHealthCheck": "Save Health Check",
"healthCheckSaved": "Health Check Saved", "healthCheckSaved": "Health Check Saved",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Intentos de Reintento", "retryAttempts": "Intentos de Reintento",
"expectedResponseCodes": "Códigos de respuesta esperados", "expectedResponseCodes": "Códigos de respuesta esperados",
"expectedResponseCodesDescription": "Código de estado HTTP que indica un estado saludable. Si se deja en blanco, se considera saludable de 200 a 300.", "expectedResponseCodesDescription": "Código de estado HTTP que indica un estado saludable. Si se deja en blanco, se considera saludable de 200 a 300.",
"customHeaders": "Cabeceras personalizadas", "customRequestHeaders": "Cabeceras de solicitud personalizadas",
"customHeadersDescription": "Nueva línea de cabeceras separada: Nombre de cabecera: valor", "customRequestHeadersDescription": "Cabeceras de solicitud enviadas a los destinos. Una por línea: Nombre-Cabecera: valor",
"customResponseHeaders": "Cabeceras de respuesta personalizadas",
"customResponseHeadersDescription": "Cabeceras de respuesta devueltas al cliente. Una por línea: Nombre-Cabecera: valor",
"headersValidationError": "Los encabezados deben estar en el formato: Nombre de cabecera: valor.", "headersValidationError": "Los encabezados deben estar en el formato: Nombre de cabecera: valor.",
"saveHealthCheck": "Guardar Chequeo de Salud", "saveHealthCheck": "Guardar Chequeo de Salud",
"healthCheckSaved": "Chequeo de Salud Guardado", "healthCheckSaved": "Chequeo de Salud Guardado",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Tentatives de réessai", "retryAttempts": "Tentatives de réessai",
"expectedResponseCodes": "Codes de réponse attendus", "expectedResponseCodes": "Codes de réponse attendus",
"expectedResponseCodesDescription": "Code de statut HTTP indiquant un état de santé satisfaisant. Si non renseigné, 200-300 est considéré comme satisfaisant.", "expectedResponseCodesDescription": "Code de statut HTTP indiquant un état de santé satisfaisant. Si non renseigné, 200-300 est considéré comme satisfaisant.",
"customHeaders": "En-têtes personnalisés", "customRequestHeaders": "En-têtes de requête personnalisés",
"customHeadersDescription": "En-têtes séparés par une nouvelle ligne: En-nom: valeur", "customRequestHeadersDescription": "En-têtes de requête envoyés aux cibles. Un par ligne : Nom-En-tête : valeur",
"customResponseHeaders": "En-têtes de réponse personnalisés",
"customResponseHeadersDescription": "En-têtes de réponse renvoyés au client. Un par ligne : Nom-En-tête : valeur",
"headersValidationError": "Les entêtes doivent être au format : Header-Name: valeur.", "headersValidationError": "Les entêtes doivent être au format : Header-Name: valeur.",
"saveHealthCheck": "Sauvegarder la vérification de l'état de santé", "saveHealthCheck": "Sauvegarder la vérification de l'état de santé",
"healthCheckSaved": "Vérification de l'état de santé enregistrée", "healthCheckSaved": "Vérification de l'état de santé enregistrée",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Tentativi di Riprova", "retryAttempts": "Tentativi di Riprova",
"expectedResponseCodes": "Codici di Risposta Attesi", "expectedResponseCodes": "Codici di Risposta Attesi",
"expectedResponseCodesDescription": "Codice di stato HTTP che indica lo stato di salute. Se lasciato vuoto, considerato sano è compreso tra 200-300.", "expectedResponseCodesDescription": "Codice di stato HTTP che indica lo stato di salute. Se lasciato vuoto, considerato sano è compreso tra 200-300.",
"customHeaders": "Intestazioni Personalizzate", "customRequestHeaders": "Intestazioni di richiesta personalizzate",
"customHeadersDescription": "Intestazioni nuova riga separate: Intestazione-Nome: valore", "customRequestHeadersDescription": "Intestazioni di richiesta inviate ai target. Una per riga: Nome-Intestazione: valore",
"customResponseHeaders": "Intestazioni di risposta personalizzate",
"customResponseHeadersDescription": "Intestazioni di risposta restituite al client. Una per riga: Nome-Intestazione: valore",
"headersValidationError": "Le intestazioni devono essere nel formato: Intestazione-Nome: valore.", "headersValidationError": "Le intestazioni devono essere nel formato: Intestazione-Nome: valore.",
"saveHealthCheck": "Salva Controllo Salute", "saveHealthCheck": "Salva Controllo Salute",
"healthCheckSaved": "Controllo Salute Salvato", "healthCheckSaved": "Controllo Salute Salvato",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "재시도 횟수", "retryAttempts": "재시도 횟수",
"expectedResponseCodes": "예상 응답 코드", "expectedResponseCodes": "예상 응답 코드",
"expectedResponseCodesDescription": "정상 상태를 나타내는 HTTP 상태 코드입니다. 비워 두면 200-300이 정상으로 간주됩니다.", "expectedResponseCodesDescription": "정상 상태를 나타내는 HTTP 상태 코드입니다. 비워 두면 200-300이 정상으로 간주됩니다.",
"customHeaders": "사용자 정의 헤더", "customRequestHeaders": "사용자 정의 요청 헤더",
"customHeadersDescription": "헤더는 새 줄로 구분됨: Header-Name: value", "customRequestHeadersDescription": "다운스트림 대상으로 전송되는 요청 헤더. 한 줄에 하나씩: 헤더-이름: 값",
"customResponseHeaders": "사용자 정의 응답 헤더",
"customResponseHeadersDescription": "클라이언트로 반환되는 응답 헤더. 한 줄에 하나씩: 헤더-이름: 값",
"headersValidationError": "헤더는 형식이어야 합니다: 헤더명: 값.", "headersValidationError": "헤더는 형식이어야 합니다: 헤더명: 값.",
"saveHealthCheck": "상태 확인 저장", "saveHealthCheck": "상태 확인 저장",
"healthCheckSaved": "상태 확인이 저장되었습니다.", "healthCheckSaved": "상태 확인이 저장되었습니다.",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Forsøk på nytt", "retryAttempts": "Forsøk på nytt",
"expectedResponseCodes": "Forventede svarkoder", "expectedResponseCodes": "Forventede svarkoder",
"expectedResponseCodesDescription": "HTTP-statuskode som indikerer sunn status. Hvis den blir stående tom, regnes 200-300 som sunn.", "expectedResponseCodesDescription": "HTTP-statuskode som indikerer sunn status. Hvis den blir stående tom, regnes 200-300 som sunn.",
"customHeaders": "Egendefinerte topptekster", "customRequestHeaders": "Egendefinerte forespørselshoder",
"customHeadersDescription": "Overskrifter som er adskilt med linje: Overskriftsnavn: verdi", "customRequestHeadersDescription": "Forespørselshoder sendt til målene. Én per linje: Header-Navn: verdi",
"customResponseHeaders": "Egendefinerte svarhoder",
"customResponseHeadersDescription": "Svarhoder sendt tilbake til klienten. Én per linje: Header-Navn: verdi",
"headersValidationError": "Topptekst må være i formatet: header-navn: verdi.", "headersValidationError": "Topptekst må være i formatet: header-navn: verdi.",
"saveHealthCheck": "Lagre Helsekontroll", "saveHealthCheck": "Lagre Helsekontroll",
"healthCheckSaved": "Helsekontroll Lagret", "healthCheckSaved": "Helsekontroll Lagret",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Herhaal Pogingen", "retryAttempts": "Herhaal Pogingen",
"expectedResponseCodes": "Verwachte Reactiecodes", "expectedResponseCodes": "Verwachte Reactiecodes",
"expectedResponseCodesDescription": "HTTP-statuscode die gezonde status aangeeft. Indien leeg wordt 200-300 als gezond beschouwd.", "expectedResponseCodesDescription": "HTTP-statuscode die gezonde status aangeeft. Indien leeg wordt 200-300 als gezond beschouwd.",
"customHeaders": "Aangepaste headers", "customRequestHeaders": "Aangepaste verzoekheaders",
"customHeadersDescription": "Kopregeleinde: Header-Naam: waarde", "customRequestHeadersDescription": "Verzoekheaders die worden doorgestuurd naar het doel. Per regel één: Header-Naam: waarde",
"customResponseHeaders": "Aangepaste antwoordheaders",
"customResponseHeadersDescription": "Antwoordheaders die worden teruggestuurd naar de client. Per regel één: Header-Naam: waarde",
"headersValidationError": "Headers moeten in het formaat zijn: Header-Naam: waarde.", "headersValidationError": "Headers moeten in het formaat zijn: Header-Naam: waarde.",
"saveHealthCheck": "Opslaan Gezondheidscontrole", "saveHealthCheck": "Opslaan Gezondheidscontrole",
"healthCheckSaved": "Gezondheidscontrole Opgeslagen", "healthCheckSaved": "Gezondheidscontrole Opgeslagen",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Próby Ponowienia", "retryAttempts": "Próby Ponowienia",
"expectedResponseCodes": "Oczekiwane Kody Odpowiedzi", "expectedResponseCodes": "Oczekiwane Kody Odpowiedzi",
"expectedResponseCodesDescription": "Kod statusu HTTP, który wskazuje zdrowy status. Jeśli pozostanie pusty, uznaje się 200-300 za zdrowy.", "expectedResponseCodesDescription": "Kod statusu HTTP, który wskazuje zdrowy status. Jeśli pozostanie pusty, uznaje się 200-300 za zdrowy.",
"customHeaders": "Niestandardowe nagłówki", "customRequestHeaders": "Niestandardowe nagłówki żądania",
"customHeadersDescription": "Nagłówki oddzielone: Nazwa nagłówka: wartość", "customRequestHeadersDescription": "Nagłówki żądania wysyłane do celów. Jeden w wierszu: Nazwa-Nagłówka: wartość",
"customResponseHeaders": "Niestandardowe nagłówki odpowiedzi",
"customResponseHeadersDescription": "Nagłówki odpowiedzi zwracane do klienta. Jeden w wierszu: Nazwa-Nagłówka: wartość",
"headersValidationError": "Nagłówki muszą być w formacie: Nazwa nagłówka: wartość.", "headersValidationError": "Nagłówki muszą być w formacie: Nazwa nagłówka: wartość.",
"saveHealthCheck": "Zapisz Kontrolę Zdrowia", "saveHealthCheck": "Zapisz Kontrolę Zdrowia",
"healthCheckSaved": "Kontrola Zdrowia Zapisana", "healthCheckSaved": "Kontrola Zdrowia Zapisana",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Tentativas de Repetição", "retryAttempts": "Tentativas de Repetição",
"expectedResponseCodes": "Códigos de Resposta Esperados", "expectedResponseCodes": "Códigos de Resposta Esperados",
"expectedResponseCodesDescription": "Código de status HTTP que indica estado saudável. Se deixado em branco, 200-300 é considerado saudável.", "expectedResponseCodesDescription": "Código de status HTTP que indica estado saudável. Se deixado em branco, 200-300 é considerado saudável.",
"customHeaders": "Cabeçalhos Personalizados", "customRequestHeaders": "Cabeçalhos de Pedido Personalizados",
"customHeadersDescription": "Separados por cabeçalhos da nova linha: Nome do Cabeçalho: valor", "customRequestHeadersDescription": "Cabeçalhos de pedido enviados para os destinos. Um por linha: Nome-Cabeçalho: valor",
"customResponseHeaders": "Cabeçalhos de Resposta Personalizados",
"customResponseHeadersDescription": "Cabeçalhos de resposta enviados de volta ao cliente. Um por linha: Nome-Cabeçalho: valor",
"headersValidationError": "Cabeçalhos devem estar no formato: Nome do Cabeçalho: valor.", "headersValidationError": "Cabeçalhos devem estar no formato: Nome do Cabeçalho: valor.",
"saveHealthCheck": "Salvar Verificação de Saúde", "saveHealthCheck": "Salvar Verificação de Saúde",
"healthCheckSaved": "Verificação de Saúde Salva", "healthCheckSaved": "Verificação de Saúde Salva",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Количество попыток повторного запроса", "retryAttempts": "Количество попыток повторного запроса",
"expectedResponseCodes": "Ожидаемые коды ответов", "expectedResponseCodes": "Ожидаемые коды ответов",
"expectedResponseCodesDescription": "HTTP-код состояния, указывающий на здоровое состояние. Если оставить пустым, 200-300 считается здоровым.", "expectedResponseCodesDescription": "HTTP-код состояния, указывающий на здоровое состояние. Если оставить пустым, 200-300 считается здоровым.",
"customHeaders": "Пользовательские заголовки", "customRequestHeaders": "Пользовательские заголовки запроса",
"customHeadersDescription": "Заголовки новой строки, разделённые: название заголовка: значение", "customRequestHeadersDescription": "Заголовки запроса, отправляемые целевым серверам. По одному в строке: Имя-Заголовка: значение",
"customResponseHeaders": "Пользовательские заголовки ответа",
"customResponseHeadersDescription": "Заголовки ответа, возвращаемые клиенту. По одному в строке: Имя-Заголовка: значение",
"headersValidationError": "Заголовки должны быть в формате: Название заголовка: значение.", "headersValidationError": "Заголовки должны быть в формате: Название заголовка: значение.",
"saveHealthCheck": "Сохранить проверку здоровья", "saveHealthCheck": "Сохранить проверку здоровья",
"healthCheckSaved": "Проверка здоровья сохранена", "healthCheckSaved": "Проверка здоровья сохранена",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "Tekrar Deneme Girişimleri", "retryAttempts": "Tekrar Deneme Girişimleri",
"expectedResponseCodes": "Beklenen Yanıt Kodları", "expectedResponseCodes": "Beklenen Yanıt Kodları",
"expectedResponseCodesDescription": "Sağlıklı durumu gösteren HTTP durum kodu. Boş bırakılırsa, 200-300 arası sağlıklı kabul edilir.", "expectedResponseCodesDescription": "Sağlıklı durumu gösteren HTTP durum kodu. Boş bırakılırsa, 200-300 arası sağlıklı kabul edilir.",
"customHeaders": "Özel Başlıklar", "customRequestHeaders": "Özel İstek Başlıkları",
"customHeadersDescription": "Başlıklar yeni satırla ayrılmış: Başlık-Adı: değer", "customRequestHeadersDescription": "Hedeflere gönderilen istek başlıkları. Satır başına bir tane: Başlık-Adı: değer",
"customResponseHeaders": "Özel Yanıt Başlıkları",
"customResponseHeadersDescription": "İstemciye geri gönderilen yanıt başlıkları. Satır başına bir tane: Başlık-Adı: değer",
"headersValidationError": "Başlıklar şu formatta olmalıdır: Başlık-Adı: değer.", "headersValidationError": "Başlıklar şu formatta olmalıdır: Başlık-Adı: değer.",
"saveHealthCheck": "Sağlık Kontrolünü Kaydet", "saveHealthCheck": "Sağlık Kontrolünü Kaydet",
"healthCheckSaved": "Sağlık Kontrolü Kaydedildi", "healthCheckSaved": "Sağlık Kontrolü Kaydedildi",
+4 -2
View File
@@ -2826,8 +2826,10 @@
"retryAttempts": "重试次数", "retryAttempts": "重试次数",
"expectedResponseCodes": "期望响应代码", "expectedResponseCodes": "期望响应代码",
"expectedResponseCodesDescription": "HTTP 状态码表示健康状态。如留空,200-300 被视为健康。", "expectedResponseCodesDescription": "HTTP 状态码表示健康状态。如留空,200-300 被视为健康。",
"customHeaders": "自定义标题", "customRequestHeaders": "自定义请求标头",
"customHeadersDescription": "头部新行分隔:头部名称:值", "customRequestHeadersDescription": "转发到目标的请求标头。每行一个:标头名称:值",
"customResponseHeaders": "自定义响应标头",
"customResponseHeadersDescription": "返回给客户端的响应标头。每行一个:标头名称:值",
"headersValidationError": "头部必须是格式:头部名称:值。", "headersValidationError": "头部必须是格式:头部名称:值。",
"saveHealthCheck": "保存健康检查", "saveHealthCheck": "保存健康检查",
"healthCheckSaved": "健康检查已保存", "healthCheckSaved": "健康检查已保存",
+4 -2
View File
@@ -1551,8 +1551,10 @@
"retryAttempts": "重試次數", "retryAttempts": "重試次數",
"expectedResponseCodes": "期望響應代碼", "expectedResponseCodes": "期望響應代碼",
"expectedResponseCodesDescription": "HTTP 狀態碼表示健康狀態。如留空,200-300 被視為健康。", "expectedResponseCodesDescription": "HTTP 狀態碼表示健康狀態。如留空,200-300 被視為健康。",
"customHeaders": "自訂 Headers", "customRequestHeaders": "自訂請求 Headers",
"customHeadersDescription": "Header 斷行分隔Header 名稱:值", "customRequestHeadersDescription": "轉發至目標的請求標頭。每行一個Header-名稱:值",
"customResponseHeaders": "自訂回應 Headers",
"customResponseHeadersDescription": "回傳給客戶端的回應標頭。每行一個:Header-名稱:值",
"headersValidationError": "Header 必須是格式:Header 名稱:值。", "headersValidationError": "Header 必須是格式:Header 名稱:值。",
"saveHealthCheck": "保存健康檢查", "saveHealthCheck": "保存健康檢查",
"healthCheckSaved": "健康檢查已保存", "healthCheckSaved": "健康檢查已保存",
+2 -1
View File
@@ -186,7 +186,8 @@ export const resources = pgTable(
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, { skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
onDelete: "set null" onDelete: "set null"
}), }),
headers: text("headers"), // comma-separated list of headers to add to the request requestHeaders: text("requestHeaders"),
responseHeaders: text("responseHeaders"),
proxyProtocol: boolean("proxyProtocol").notNull().default(false), proxyProtocol: boolean("proxyProtocol").notNull().default(false),
proxyProtocolVersion: integer("proxyProtocolVersion").default(1), proxyProtocolVersion: integer("proxyProtocolVersion").default(1),
maintenanceModeEnabled: boolean("maintenanceModeEnabled") maintenanceModeEnabled: boolean("maintenanceModeEnabled")
+2 -1
View File
@@ -202,7 +202,8 @@ export const resources = sqliteTable(
skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, { skipToIdpId: integer("skipToIdpId").references(() => idp.idpId, {
onDelete: "set null" onDelete: "set null"
}), }),
headers: text("headers"), // comma-separated list of headers to add to the request requestHeaders: text("requestHeaders"),
responseHeaders: text("responseHeaders"),
proxyProtocol: integer("proxyProtocol", { mode: "boolean" }) proxyProtocol: integer("proxyProtocol", { mode: "boolean" })
.notNull() .notNull()
.default(false), .default(false),
+18 -7
View File
@@ -261,10 +261,18 @@ export async function updatePublicResources(
resourceData.ssl == undefined || resourceData.ssl == null resourceData.ssl == undefined || resourceData.ssl == null
? true ? true
: resourceData.ssl; : resourceData.ssl;
let headers = ""; // `headers` is a deprecated alias for `requestHeaders`
if (resourceData.headers) { const mergedRequestHeaders = [
headers = JSON.stringify(resourceData.headers); ...(resourceData.headers ?? []),
} ...(resourceData.requestHeaders ?? [])
];
const requestHeaders =
mergedRequestHeaders.length > 0
? JSON.stringify(mergedRequestHeaders)
: null;
const responseHeaders = resourceData.responseHeaders?.length
? JSON.stringify(resourceData.responseHeaders)
: null;
if (resourceData.policy) { if (resourceData.policy) {
const isLicensed = await isLicensedOrSubscribed( const isLicensed = await isLicensedOrSubscribed(
@@ -403,7 +411,8 @@ export async function updatePublicResources(
? resourceData.auth["whitelist-users"].length > ? resourceData.auth["whitelist-users"].length >
0 0
: false, : false,
headers: headers || null, requestHeaders,
responseHeaders,
applyRules: applyRules:
resourceData.rules && resourceData.rules &&
resourceData.rules.length > 0, resourceData.rules.length > 0,
@@ -599,7 +608,8 @@ export async function updatePublicResources(
setHostHeader: resourceData["host-header"] || null, setHostHeader: resourceData["host-header"] || null,
tlsServerName: tlsServerName:
resourceData["tls-server-name"] || null, resourceData["tls-server-name"] || null,
headers: headers || null, requestHeaders,
responseHeaders,
maintenanceModeEnabled: maintenanceModeEnabled:
resourceData.maintenance?.enabled, resourceData.maintenance?.enabled,
maintenanceModeType: resourceData.maintenance?.type, maintenanceModeType: resourceData.maintenance?.type,
@@ -1222,7 +1232,8 @@ export async function updatePublicResources(
setHostHeader: resourceData["host-header"] || null, setHostHeader: resourceData["host-header"] || null,
tlsServerName: resourceData["tls-server-name"] || null, tlsServerName: resourceData["tls-server-name"] || null,
ssl: resourceSsl, ssl: resourceSsl,
headers: headers || null, requestHeaders,
responseHeaders,
applyRules: applyRules:
resourceData.rules && resourceData.rules.length > 0, resourceData.rules && resourceData.rules.length > 0,
pamMode: resourceData["auth-daemon"]?.pam || "passthrough", pamMode: resourceData["auth-daemon"]?.pam || "passthrough",
+3 -1
View File
@@ -326,7 +326,9 @@ export const PublicResourceSchema = z
auth: AuthSchema.optional(), auth: AuthSchema.optional(),
"host-header": z.string().optional(), "host-header": z.string().optional(),
"tls-server-name": z.string().optional(), "tls-server-name": z.string().optional(),
headers: z.array(HeaderSchema).optional(), headers: z.array(HeaderSchema).optional(), // deprecated alias for requestHeaders
requestHeaders: z.array(HeaderSchema).optional(),
responseHeaders: z.array(HeaderSchema).optional(),
rules: z.array(RuleSchema).optional(), rules: z.array(RuleSchema).optional(),
maintenance: MaintenanceSchema.optional(), maintenance: MaintenanceSchema.optional(),
"auth-daemon": AuthDaemonSchema.optional(), "auth-daemon": AuthDaemonSchema.optional(),
+6 -3
View File
@@ -96,7 +96,8 @@ export async function getTraefikConfig(
tlsServerName: resources.tlsServerName, tlsServerName: resources.tlsServerName,
setHostHeader: resources.setHostHeader, setHostHeader: resources.setHostHeader,
enableProxy: resources.enableProxy, enableProxy: resources.enableProxy,
headers: resources.headers, requestHeaders: resources.requestHeaders,
responseHeaders: resources.responseHeaders,
proxyProtocol: resources.proxyProtocol, proxyProtocol: resources.proxyProtocol,
proxyProtocolVersion: resources.proxyProtocolVersion, proxyProtocolVersion: resources.proxyProtocolVersion,
wildcard: resources.wildcard, wildcard: resources.wildcard,
@@ -225,7 +226,8 @@ export async function getTraefikConfig(
setHostHeader: row.setHostHeader, setHostHeader: row.setHostHeader,
enableProxy: row.enableProxy, enableProxy: row.enableProxy,
targets: [], targets: [],
headers: row.headers, requestHeaders: row.requestHeaders,
responseHeaders: row.responseHeaders,
proxyProtocol: row.proxyProtocol, proxyProtocol: row.proxyProtocol,
proxyProtocolVersion: row.proxyProtocolVersion ?? 1, proxyProtocolVersion: row.proxyProtocolVersion ?? 1,
path: row.path, // the targets will all have the same path path: row.path, // the targets will all have the same path
@@ -405,7 +407,8 @@ export async function getTraefikConfig(
// Handle custom headers middleware // Handle custom headers middleware
const customHeadersMiddleware = buildCustomHeadersMiddleware( const customHeadersMiddleware = buildCustomHeadersMiddleware(
resource.headers, resource.requestHeaders,
resource.responseHeaders,
resource.setHostHeader, resource.setHostHeader,
resource.resourceId resource.resourceId
); );
+57 -25
View File
@@ -1,46 +1,78 @@
import logger from "@server/logger"; import logger from "@server/logger";
function parseHeaders(
headers: string,
label: string,
resourceId: number
): { name: string; value: string }[] {
try {
return JSON.parse(headers) as {
name: string;
value: string;
}[];
} catch (e) {
logger.warn(
`Failed to parse ${label} for resource ${resourceId}: ${e}`
);
return [];
}
}
/** /**
* Build the customRequestHeaders middleware definition for a resource's * Build the custom headers middleware definition for a resource's
* custom headers + setHostHeader config. Returns null when there are no * custom request/response headers + setHostHeader config. Returns null when
* headers to set, so the caller can skip attaching the middleware. * there are no headers to set, so the caller can skip attaching the
* middleware.
*/ */
export function buildCustomHeadersMiddleware( export function buildCustomHeadersMiddleware(
headers: string | null | undefined, requestHeaders: string | null | undefined,
responseHeaders: string | null | undefined,
setHostHeader: string | null | undefined, setHostHeader: string | null | undefined,
resourceId: number resourceId: number
): { headers: { customRequestHeaders: { [key: string]: string } } } | null { ): {
const headersObj: { [key: string]: string } = {}; headers: {
customRequestHeaders?: { [key: string]: string };
customResponseHeaders?: { [key: string]: string };
};
} | null {
const requestHeadersObj: { [key: string]: string } = {};
const responseHeadersObj: { [key: string]: string } = {};
if (headers) { if (requestHeaders) {
let headersArr: { name: string; value: string }[] = []; parseHeaders(requestHeaders, "requestHeaders", resourceId).forEach(
try { (header) => {
headersArr = JSON.parse(headers) as { requestHeadersObj[header.name] = header.value;
name: string; }
value: string; );
}[];
} catch (e) {
logger.warn(
`Failed to parse headers for resource ${resourceId}: ${e}`
);
}
headersArr.forEach((header) => {
headersObj[header.name] = header.value;
});
} }
if (setHostHeader) { if (setHostHeader) {
headersObj["Host"] = setHostHeader; requestHeadersObj["Host"] = setHostHeader;
} }
if (Object.keys(headersObj).length === 0) { if (responseHeaders) {
parseHeaders(responseHeaders, "responseHeaders", resourceId).forEach(
(header) => {
responseHeadersObj[header.name] = header.value;
}
);
}
const hasRequestHeaders = Object.keys(requestHeadersObj).length > 0;
const hasResponseHeaders = Object.keys(responseHeadersObj).length > 0;
if (!hasRequestHeaders && !hasResponseHeaders) {
return null; return null;
} }
return { return {
headers: { headers: {
customRequestHeaders: headersObj ...(hasRequestHeaders && {
customRequestHeaders: requestHeadersObj
}),
...(hasResponseHeaders && {
customResponseHeaders: responseHeadersObj
})
} }
}; };
} }
@@ -133,7 +133,8 @@ export async function getTraefikConfig(
tlsServerName: resources.tlsServerName, tlsServerName: resources.tlsServerName,
setHostHeader: resources.setHostHeader, setHostHeader: resources.setHostHeader,
enableProxy: resources.enableProxy, enableProxy: resources.enableProxy,
headers: resources.headers, requestHeaders: resources.requestHeaders,
responseHeaders: resources.responseHeaders,
proxyProtocol: resources.proxyProtocol, proxyProtocol: resources.proxyProtocol,
proxyProtocolVersion: resources.proxyProtocolVersion, proxyProtocolVersion: resources.proxyProtocolVersion,
wildcard: resources.wildcard, wildcard: resources.wildcard,
@@ -275,7 +276,8 @@ export async function getTraefikConfig(
setHostHeader: row.setHostHeader, setHostHeader: row.setHostHeader,
enableProxy: row.enableProxy, enableProxy: row.enableProxy,
targets: [], targets: [],
headers: row.headers, requestHeaders: row.requestHeaders,
responseHeaders: row.responseHeaders,
proxyProtocol: row.proxyProtocol, proxyProtocol: row.proxyProtocol,
proxyProtocolVersion: row.proxyProtocolVersion ?? 1, proxyProtocolVersion: row.proxyProtocolVersion ?? 1,
path: row.path, // the targets will all have the same path path: row.path, // the targets will all have the same path
@@ -712,7 +714,8 @@ export async function getTraefikConfig(
); );
const customHeadersMiddleware = buildCustomHeadersMiddleware( const customHeadersMiddleware = buildCustomHeadersMiddleware(
resource.headers, resource.requestHeaders,
resource.responseHeaders,
resource.setHostHeader, resource.setHostHeader,
resource.resourceId resource.resourceId
); );
+9 -5
View File
@@ -53,9 +53,10 @@ async function queryInlinePolicy(resourcePolicyId: number) {
export type GetResourceResponse = Omit< export type GetResourceResponse = Omit<
NonNullable<Awaited<ReturnType<typeof query>>>, NonNullable<Awaited<ReturnType<typeof query>>>,
"headers" "requestHeaders" | "responseHeaders"
> & { > & {
headers: { name: string; value: string }[] | null; requestHeaders: { name: string; value: string }[] | null;
responseHeaders: { name: string; value: string }[] | null;
}; };
registry.registerPath({ registry.registerPath({
@@ -186,9 +187,12 @@ export async function getResource(
return response<GetResourceResponse>(res, { return response<GetResourceResponse>(res, {
data: { data: {
...returnData, ...returnData,
headers: returnData.headers requestHeaders: returnData.requestHeaders
? JSON.parse(returnData.headers) ? JSON.parse(returnData.requestHeaders)
: returnData.headers : returnData.requestHeaders,
responseHeaders: returnData.responseHeaders
? JSON.parse(returnData.responseHeaders)
: returnData.responseHeaders
}, },
success: true, success: true,
error: false, error: false,
+59 -31
View File
@@ -100,6 +100,14 @@ const updateHttpResourceBodySchema = z
"When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource." "When no shared resource policy is assigned (resourcePolicyId is null), updates the resource's inline policy. When a shared policy is assigned, this value overrides the shared policy for this resource."
), ),
headers: z headers: z
.array(z.strictObject({ name: z.string(), value: z.string() }))
.nullable()
.optional(), // deprecated alias for requestHeaders
requestHeaders: z
.array(z.strictObject({ name: z.string(), value: z.string() }))
.nullable()
.optional(),
responseHeaders: z
.array(z.strictObject({ name: z.string(), value: z.string() })) .array(z.strictObject({ name: z.string(), value: z.string() }))
.nullable() .nullable()
.optional(), .optional(),
@@ -163,12 +171,13 @@ const updateHttpResourceBodySchema = z
) )
.refine( .refine(
(data) => { (data) => {
if (data.headers) { const validHeaderName = /^[a-zA-Z0-9!#$%&'*+\-.^_`|~]+$/;
// HTTP header names must be valid token characters (RFC 7230) const allHeaders = [
const validHeaderName = /^[a-zA-Z0-9!#$%&'*+\-.^_`|~]+$/; ...(data.headers ?? []),
return data.headers.every((h) => validHeaderName.test(h.name)); ...(data.requestHeaders ?? []),
} ...(data.responseHeaders ?? [])
return true; ];
return allHeaders.every((h) => validHeaderName.test(h.name));
}, },
{ {
error: "Header names may only contain valid HTTP token characters (letters, digits, and !#$%&'*+-.^_`|~)." error: "Header names may only contain valid HTTP token characters (letters, digits, and !#$%&'*+-.^_`|~)."
@@ -176,14 +185,13 @@ const updateHttpResourceBodySchema = z
) )
.refine( .refine(
(data) => { (data) => {
if (data.headers) { const validHeaderValue = /^[\t\x20-\x7E]*$/;
// HTTP header values must be visible ASCII or horizontal whitespace, no control chars (RFC 7230) const allHeaders = [
const validHeaderValue = /^[\t\x20-\x7E]*$/; ...(data.headers ?? []),
return data.headers.every((h) => ...(data.requestHeaders ?? []),
validHeaderValue.test(h.value) ...(data.responseHeaders ?? [])
); ];
} return allHeaders.every((h) => validHeaderValue.test(h.value));
return true;
}, },
{ {
error: "Header values may only contain printable ASCII characters and horizontal whitespace." error: "Header values may only contain printable ASCII characters and horizontal whitespace."
@@ -191,16 +199,17 @@ const updateHttpResourceBodySchema = z
) )
.refine( .refine(
(data) => { (data) => {
if (data.headers) { const templatePattern = /\{\{[^}]+\}\}/;
// Reject Traefik template syntax {{word}} in names or values const allHeaders = [
const templatePattern = /\{\{[^}]+\}\}/; ...(data.headers ?? []),
return data.headers.every( ...(data.requestHeaders ?? []),
(h) => ...(data.responseHeaders ?? [])
!templatePattern.test(h.name) && ];
!templatePattern.test(h.value) return allHeaders.every(
); (h) =>
} !templatePattern.test(h.name) &&
return true; !templatePattern.test(h.value)
);
}, },
{ {
error: "Header names and values must not contain template expressions such as {{value}}." error: "Header names and values must not contain template expressions such as {{value}}."
@@ -695,13 +704,32 @@ async function updateHttpResource(
await createCertificate(domainId, fullDomain, db); await createCertificate(domainId, fullDomain, db);
} }
let headers = undefined; let requestHeaders = undefined;
if (updateData.headers) { const mergedRequestHeaders = [
headers = JSON.stringify(updateData.headers); ...(updateData.headers ?? []),
} else if (updateData.headers === null) { ...(updateData.requestHeaders ?? [])
headers = null; ];
if (
updateData.headers !== undefined ||
updateData.requestHeaders !== undefined
) {
requestHeaders =
mergedRequestHeaders.length > 0
? JSON.stringify(mergedRequestHeaders)
: null;
} }
let responseHeaders = undefined;
if (updateData.responseHeaders) {
responseHeaders = JSON.stringify(updateData.responseHeaders);
} else if (updateData.responseHeaders === null) {
responseHeaders = null;
}
updateData.headers = undefined;
updateData.requestHeaders = undefined;
updateData.responseHeaders = undefined;
if (!isLicensed) { if (!isLicensed) {
updateData.maintenanceModeEnabled = undefined; updateData.maintenanceModeEnabled = undefined;
updateData.maintenanceModeType = undefined; updateData.maintenanceModeType = undefined;
@@ -754,7 +782,7 @@ async function updateHttpResource(
const updatedResource = await db const updatedResource = await db
.update(resources) .update(resources)
.set({ ...resourceOnlyData, headers }) .set({ ...resourceOnlyData, requestHeaders, responseHeaders })
.where(eq(resources.resourceId, resource.resourceId)) .where(eq(resources.resourceId, resource.resourceId))
.returning(); .returning();
@@ -778,7 +806,7 @@ async function updateHttpResource(
const updatedResource = await db const updatedResource = await db
.update(resources) .update(resources)
.set({ ...updateData, headers }) .set({ ...updateData, requestHeaders, responseHeaders })
.where(eq(resources.resourceId, resource.resourceId)) .where(eq(resources.resourceId, resource.resourceId))
.returning(); .returning();
@@ -119,7 +119,10 @@ function ProxyResourceHttpForm({
message: t("proxyErrorInvalidHeader") message: t("proxyErrorInvalidHeader")
} }
), ),
headers: z requestHeaders: z
.array(z.object({ name: z.string(), value: z.string() }))
.nullable(),
responseHeaders: z
.array(z.object({ name: z.string(), value: z.string() })) .array(z.object({ name: z.string(), value: z.string() }))
.nullable() .nullable()
}); });
@@ -131,19 +134,21 @@ function ProxyResourceHttpForm({
ssl: resource.ssl, ssl: resource.ssl,
tlsServerName: resource.tlsServerName || "", tlsServerName: resource.tlsServerName || "",
setHostHeader: resource.setHostHeader || "", setHostHeader: resource.setHostHeader || "",
headers: resource.headers requestHeaders: resource.requestHeaders,
responseHeaders: resource.responseHeaders
}, },
mode: "onChange" mode: "onChange"
}); });
const [, formAction, saveLoading] = useActionState(onSubmit, null); const [, formAction, saveLoading] = useActionState(onSubmit, null);
const [headersValid, setHeadersValid] = useState(true); const [requestHeadersValid, setRequestHeadersValid] = useState(true);
const [responseHeadersValid, setResponseHeadersValid] = useState(true);
async function onSubmit() { async function onSubmit() {
const isValid = await form.trigger(); const isValid = await form.trigger();
if (!isValid) return; if (!isValid) return;
if (!headersValid) { if (!requestHeadersValid || !responseHeadersValid) {
toast({ toast({
variant: "destructive", variant: "destructive",
title: t("settingsErrorUpdate"), title: t("settingsErrorUpdate"),
@@ -162,7 +167,8 @@ function ProxyResourceHttpForm({
ssl: data.ssl, ssl: data.ssl,
tlsServerName: data.tlsServerName || null, tlsServerName: data.tlsServerName || null,
setHostHeader: data.setHostHeader || null, setHostHeader: data.setHostHeader || null,
headers: data.headers || null requestHeaders: data.requestHeaders || null,
responseHeaders: data.responseHeaders || null
} }
) )
.catch((err) => { .catch((err) => {
@@ -183,7 +189,8 @@ function ProxyResourceHttpForm({
ssl: data.ssl, ssl: data.ssl,
tlsServerName: data.tlsServerName || null, tlsServerName: data.tlsServerName || null,
setHostHeader: data.setHostHeader || null, setHostHeader: data.setHostHeader || null,
headers: data.headers || null requestHeaders: data.requestHeaders || null,
responseHeaders: data.responseHeaders || null
}); });
toast({ toast({
@@ -324,11 +331,11 @@ function ProxyResourceHttpForm({
<SettingsFormCell span="full"> <SettingsFormCell span="full">
<FormField <FormField
control={form.control} control={form.control}
name="headers" name="requestHeaders"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t("customHeaders")} {t("customRequestHeaders")}
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<HeadersInput <HeadersInput
@@ -337,14 +344,46 @@ function ProxyResourceHttpForm({
field.onChange field.onChange
} }
onValidityChange={ onValidityChange={
setHeadersValid setRequestHeadersValid
} }
rows={4} rows={4}
/> />
</FormControl> </FormControl>
<FormDescription> <FormDescription>
{t( {t(
"customHeadersDescription" "customRequestHeadersDescription"
)}
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</SettingsFormCell>
<SettingsFormCell span="full">
<FormField
control={form.control}
name="responseHeaders"
render={({ field }) => (
<FormItem>
<FormLabel>
{t("customResponseHeaders")}
</FormLabel>
<FormControl>
<HeadersInput
value={field.value}
onChange={
field.onChange
}
onValidityChange={
setResponseHeadersValid
}
rows={4}
/>
</FormControl>
<FormDescription>
{t(
"customResponseHeadersDescription"
)} )}
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
@@ -362,7 +401,11 @@ function ProxyResourceHttpForm({
<Button <Button
type="submit" type="submit"
loading={saveLoading} loading={saveLoading}
disabled={saveLoading || !headersValid} disabled={
saveLoading ||
!requestHeadersValid ||
!responseHeadersValid
}
form="http-settings-form" form="http-settings-form"
> >
{t("saveSettings")} {t("saveSettings")}
@@ -113,7 +113,7 @@ function ProxyResourceProtocolForm({
message: t("proxyErrorInvalidHeader") message: t("proxyErrorInvalidHeader")
} }
), ),
headers: z requestHeaders: z
.array(z.object({ name: z.string(), value: z.string() })) .array(z.object({ name: z.string(), value: z.string() }))
.nullable(), .nullable(),
proxyProtocol: z.boolean().optional(), proxyProtocol: z.boolean().optional(),
@@ -124,7 +124,7 @@ function ProxyResourceProtocolForm({
resolver: zodResolver(proxySettingsSchema), resolver: zodResolver(proxySettingsSchema),
defaultValues: { defaultValues: {
setHostHeader: resource.setHostHeader || "", setHostHeader: resource.setHostHeader || "",
headers: resource.headers, requestHeaders: resource.requestHeaders,
proxyProtocol: resource.proxyProtocol || false, proxyProtocol: resource.proxyProtocol || false,
proxyProtocolVersion: resource.proxyProtocolVersion || 1 proxyProtocolVersion: resource.proxyProtocolVersion || 1
} }
+2 -2
View File
@@ -1355,7 +1355,7 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t( {t(
"customHeaders" "customRequestHeaders"
)} )}
</FormLabel> </FormLabel>
<FormControl> <FormControl>
@@ -1379,7 +1379,7 @@ export function HealthCheckCredenza(props: HealthCheckCredenzaProps) {
</FormControl> </FormControl>
<FormDescription> <FormDescription>
{t( {t(
"customHeadersDescription" "customRequestHeadersDescription"
)} )}
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />
+2 -2
View File
@@ -733,7 +733,7 @@ export function HealthCheckFormFields({
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel> <FormLabel>
{t("customHeaders")} {t("customRequestHeaders")}
</FormLabel> </FormLabel>
<FormControl> <FormControl>
<HeadersInput <HeadersInput
@@ -750,7 +750,7 @@ export function HealthCheckFormFields({
</FormControl> </FormControl>
<FormDescription> <FormDescription>
{t( {t(
"customHeadersDescription" "customRequestHeadersDescription"
)} )}
</FormDescription> </FormDescription>
<FormMessage /> <FormMessage />