← Назад на главную

Гайд: Интеграция n8n Chat Webhook с веб-сайтом

Полное руководство по поиску и решению проблем

Дата: 11 декабря 2025 Проект: Интеграция AI чата на openaiua.fr с n8n workflow


Содержание

  1. Начальная настройка
  2. Проблема 1: Пустой body в webhook
  3. Проблема 2: Webhook работает только 1 раз
  4. Проблема 3: Неправильный URL webhook
  5. Проблема 4: Ответ не отображается на сайте
  6. Проблема 5: SSL предупреждение в Chrome
  7. Финальная конфигурация

1. Начальная настройка

Цель

Создать работающий чат на сайте, который отправляет сообщения в n8n workflow и получает ответы от AI агента.

Архитектура

Браузер (openaiua.fr)
  → JavaScript (chat.js)
  → POST запрос
  → Caddy (reverse proxy)
  → n8n webhook
  → AI Agent (Ollama)
  → Ответ обратно в браузер

Начальный код (проблемный)

JavaScript (chat.js):

this.webhookUrl = 'https://n8n.openaiua.fr/webhook/485504f9-9cb8-4134-988b-5b856e881144/chat';

// Отправка данных
body: JSON.stringify({
    action: 'sendMessage',
    sessionId: this.sessionId,
    chatInput: message
})

Проблема: Webhook URL был старым, формат данных не совпадал с ожидаемым.


Проблема 1: Пустой body в webhook

🔍 Диагностика

Симптом: При тестировании webhook получали:

{
  "body": {},  // ← Пустой объект!
  "query": {},
  "params": {}
}

Метод обнаружения:

curl -X POST https://n8n.openaiua.fr/webhook-test/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Привет, это тест"}'

Анализ:

  1. Открыли URL в браузере → получили ошибку 404
  2. Ошибка говорила: "This webhook is not registered for GET requests"
  3. Вывод: Браузер делает GET, а webhook ждёт POST

✅ Решение

Причина: Пользователь открывал webhook URL в браузере, который отправляет GET запрос вместо POST.

Исправление: Использовать POST запрос через curl или JavaScript fetch:

# Правильный способ тестирования
curl -X POST https://n8n.openaiua.fr/webhook-test/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Тестовое сообщение"}'

Результат:

{
  "body": {
    "message": "Тестовое сообщение"  // ✅ Данные пришли!
  }
}

Проблема 2: Webhook работает только 1 раз

🔍 Диагностика

Симптом:

Метод обнаружения:

  1. Проверили логи n8n:
docker logs n8n --tail 50 | grep webhook

Вывод:

Received request for unknown webhook: The requested webhook "webhook/chat" is not registered.
  1. Проверили URL в браузере:
/webhook-test/webhook/chat  ← Тестовый URL!

✅ Решение

Причина: Использовался тестовый webhook URL (/webhook-test/), который:

Production vs Test URLs:

❌ Тестовый:    /webhook-test/webhook/chat  (работает 1 раз)
✅ Production:  /webhook/chat               (работает всегда)

Исправление в JavaScript:

// БЫЛО (неправильно):
this.webhookUrl = 'https://n8n.openaiua.fr/webhook-test/webhook/chat';

// СТАЛО (правильно):
this.webhookUrl = 'https://n8n.openaiua.fr/webhook/chat';

Важно: Workflow должен быть активирован (кнопка Active = ON в n8n)!

Файл: /home/ubuntu/projects/landing/public/js/chat.js:10


Проблема 3: Неправильный URL webhook

🔍 Диагностика

Симптом: После изменения на production URL получили:

curl -X POST https://n8n.openaiua.fr/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "тест"}'

# Ошибка:
{"code":404,"message":"The requested webhook \"POST chat\" is not registered."}

Метод обнаружения:

  1. Проверили базу данных n8n:
# Скопировали БД из контейнера
docker cp n8n:/home/node/.n8n/database.sqlite /tmp/n8n_db.sqlite

# Проверили зарегистрированные webhooks
sqlite3 /tmp/n8n_db.sqlite "SELECT * FROM webhook_entity;"

Результат:

plUL5TUpSeibV6le|webhook/chat|POST|Webhook||
  1. Попробовали разные варианты URL:
# Вариант 1:
curl https://n8n.openaiua.fr/webhook/chat  # ❌ 404

# Вариант 2 (догадка - двойной префикс):
curl https://n8n.openaiua.fr/webhook/webhook/chat  # ✅ РАБОТАЕТ!

✅ Решение

Причина: В n8n узле Webhook path указан как webhook/chat, но n8n автоматически добавляет префикс /webhook/:

Path в узле:     webhook/chat
n8n добавляет:   /webhook/
Итоговый URL:    /webhook/webhook/chat  ← Двойной префикс!

Исправление в JavaScript:

// БЫЛО:
this.webhookUrl = 'https://n8n.openaiua.fr/webhook/chat';

// СТАЛО (правильный URL):
this.webhookUrl = 'https://n8n.openaiua.fr/webhook/webhook/chat';

Файл: /home/ubuntu/projects/landing/public/js/chat.js:10

Проверка:

curl -X POST https://n8n.openaiua.fr/webhook/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello from test"}'

# Ответ:
{"text":"Hello! How can I assist you today?"}  # ✅ Работает!

Проблема 4: Ответ не отображается на сайте

🔍 Диагностика

Симптом:

Метод обнаружения:

  1. Проверили что возвращает webhook:
curl -X POST https://n8n.openaiua.fr/webhook/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "test"}'

# Ответ:
{"text":"Hello! How can I assist you today?"}
  1. Посмотрели код JavaScript:
// В коде проверялось:
if (data.message) {
    return data.message;  // ❌ Поле "message" не существует!
} else if (data.output) {
    return data.output;   // ❌ Поле "output" не существует!
} else {
    return 'Получен ответ от AI агента.';  // ← Попадали сюда
}
  1. Реальная структура ответа:
{
  "text": "Hello! How can I assist you today?"
}

Проблема: JavaScript искал поля message, output, response, но n8n возвращал text.

✅ Решение

Исправление в JavaScript:

// БЫЛО:
const data = await response.json();

if (data.message) {
    return data.message;
} else if (data.output) {
    return data.output;
} else if (data.response) {
    return data.response;
} else if (typeof data === 'string') {
    return data;
} else {
    return 'Получен ответ от AI агента.';  // ← Fallback
}

// СТАЛО:
const data = await response.json();

if (data.text) {                    // ← Добавлена проверка первой!
    return data.text;
} else if (data.message) {
    return data.message;
} else if (data.output) {
    return data.output;
} else if (data.response) {
    return data.response;
} else if (typeof data === 'string') {
    return data;
} else {
    return JSON.stringify(data);    // ← Показываем весь JSON для отладки
}

Файл: /home/ubuntu/projects/landing/public/js/chat.js:74-87

Результат: ✅ Ответ от AI теперь корректно отображается на сайте!


Проблема 5: SSL предупреждение в Chrome

🔍 Диагностика

Симптом:

Метод обнаружения:

  1. Проверили сертификат:
echo | openssl s_client -connect n8n.openaiua.fr:443 -servername n8n.openaiua.fr 2>&1 | \
  grep "Verify return code"

# Результат:
Verify return code: 0 (ok)  # ✅ Сертификат валидный
  1. Проверили security headers:
curl -I https://n8n.openaiua.fr | grep -i "strict-transport\|x-frame\|x-content"

# Результат: (пусто) ← Отсутствуют security headers!
  1. Проверили логи n8n в docker-compose.yml:
environment:
  - N8N_PROTOCOL=http          # ❌ HTTP вместо HTTPS!
  - WEBHOOK_URL=https://...    # ✅ Правильно, но недостаточно

Проблема:

  1. n8n внутри контейнера работал по HTTP (mixed content)
  2. Отсутствовали security headers в reverse proxy (Caddy)

✅ Решение

Часть 1: Исправление n8n конфигурации

# Файл: /home/ubuntu/projects/n8n/docker-compose.yml

environment:
  # БЫЛО:
  - N8N_PROTOCOL=http

  # СТАЛО:
  - N8N_PROTOCOL=https
  - N8N_EDITOR_BASE_URL=https://n8n.openaiua.fr

  # Остальное без изменений:
  - WEBHOOK_URL=https://n8n.openaiua.fr/
  - N8N_TRUST_PROXY=true

Перезапуск:

cd /home/ubuntu/projects/n8n
docker compose down
docker compose up -d

Часть 2: Добавление Security Headers в Caddy

# Файл: /etc/caddy/Caddyfile

# БЫЛО:
n8n.openaiua.fr {
    reverse_proxy localhost:5678
}

# СТАЛО:
n8n.openaiua.fr {
    # Security headers для совместимости с Chrome
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
        -Server
    }

    reverse_proxy localhost:5678
}

# То же самое для основного сайта:
openaiua.fr, www.openaiua.fr {
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
        -Server
    }

    reverse_proxy localhost:3001
}

Применение изменений:

sudo cp /tmp/Caddyfile.new /etc/caddy/Caddyfile
sudo systemctl reload caddy

Проверка:

curl -I https://n8n.openaiua.fr | grep -i "strict-transport"

# Результат:
strict-transport-security: max-age=31536000; includeSubDomains; preload  # ✅

Решение для Chrome: После изменений нужно очистить кеш в Chrome:

  1. Открыть DevTools (F12)
  2. Application → Clear Storage → Clear site data
  3. Обновить страницу (Ctrl+Shift+R)

Финальная конфигурация

Файловая структура

/home/ubuntu/projects/
├── landing/
│   ├── public/
│   │   ├── index.html
│   │   └── js/
│   │       └── chat.js           ← Основной файл чата
│   ├── server.js                 ← Express сервер (порт 3001)
│   └── package.json
│
├── n8n/
│   └── docker-compose.yml        ← n8n конфигурация
│
└── /etc/caddy/
    └── Caddyfile                 ← Reverse proxy конфигурация

1. JavaScript Chat Client

Файл: /home/ubuntu/projects/landing/public/js/chat.js

class ChatBot {
    constructor() {
        this.chatForm = document.getElementById('chatForm');
        this.chatInput = document.getElementById('chatInput');
        this.chatMessages = document.getElementById('chatMessages');
        this.sessionId = this.generateSessionId();

        // ✅ Правильный production webhook URL
        this.webhookUrl = 'https://n8n.openaiua.fr/webhook/webhook/chat';

        this.init();
    }

    async sendToN8N(message) {
        try {
            const response = await fetch(this.webhookUrl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                // ✅ Правильный формат данных
                body: JSON.stringify({
                    message: message
                })
            });

            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            const data = await response.json();

            // ✅ Правильная обработка ответа (проверяем data.text первым!)
            if (data.text) {
                return data.text;
            } else if (data.message) {
                return data.message;
            } else if (data.output) {
                return data.output;
            } else if (data.response) {
                return data.response;
            } else if (typeof data === 'string') {
                return data;
            } else {
                return JSON.stringify(data);
            }
        } catch (error) {
            console.error('N8N Error:', error);
            throw error;
        }
    }
}

Ключевые моменты:

2. n8n Docker Configuration

Файл: /home/ubuntu/projects/n8n/docker-compose.yml

version: '3.8'

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "5678:5678"
    environment:
      - GENERIC_TIMEZONE=Europe/Kiev
      - N8N_HOST=0.0.0.0
      - N8N_PORT=5678

      # ✅ HTTPS конфигурация (исправлено!)
      - N8N_PROTOCOL=https
      - N8N_EDITOR_BASE_URL=https://n8n.openaiua.fr

      - NODE_ENV=production
      - N8N_SECURE_COOKIE=false
      - N8N_GIT_NODE_DISABLE_BARE_REPOS=true

      # ✅ Webhook URL
      - WEBHOOK_URL=https://n8n.openaiua.fr/
      - N8N_TRUST_PROXY=true

      - EXECUTIONS_TIMEOUT=3600
      - EXECUTIONS_TIMEOUT_MAX=7200
    volumes:
      - n8n_data:/home/node/.n8n
    networks:
      - default
      - ai-stack_llm-net

volumes:
  n8n_data:

networks:
  default:
  ai-stack_llm-net:
    external: true

Перезапуск после изменений:

cd /home/ubuntu/projects/n8n
docker compose down
docker compose up -d

3. Caddy Reverse Proxy

Файл: /etc/caddy/Caddyfile

# n8n subdomain with automatic HTTPS
n8n.openaiua.fr {
    # ✅ Security headers для Chrome
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
        -Server
    }

    reverse_proxy localhost:5678
}

# Main website - Node.js landing page
openaiua.fr, www.openaiua.fr {
    # ✅ Security headers
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "SAMEORIGIN"
        Referrer-Policy "strict-origin-when-cross-origin"
        -Server
    }

    reverse_proxy localhost:3001
}

Применение изменений:

sudo systemctl reload caddy

4. n8n Workflow Structure

Workflow Name: n8n_express Status: Active ✅

Узлы:

  1. Webhook

    • Path: webhook/chat
    • Method: POST
    • Response Mode: lastNode
  2. Extract Data (Set node)

    • Извлекает: {{ $json.body.message }}
    • Сохраняет в: userMessage
  3. AI Agent (LLM Chain)

    • Model: Ollama (gpt-oss:120b-cloud)
    • Memory: Window Buffer Memory
  4. Respond

    • Возвращает результат AI агента

Важно: Workflow должен быть активирован (кнопка Active)!


Чек-лист для отладки

Если webhook не работает:

# 1. Проверить что n8n запущен
docker ps | grep n8n

# 2. Проверить логи n8n
docker logs n8n --tail 50

# 3. Проверить зарегистрированные webhooks в БД
docker cp n8n:/home/node/.n8n/database.sqlite /tmp/n8n_db.sqlite
sqlite3 /tmp/n8n_db.sqlite "SELECT * FROM webhook_entity;"

# 4. Проверить что workflow активен
sqlite3 /tmp/n8n_db.sqlite "SELECT id, name, active FROM workflow_entity;"

# 5. Тест webhook через curl
curl -X POST https://n8n.openaiua.fr/webhook/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "test"}'

# 6. Проверить SSL сертификат
echo | openssl s_client -connect n8n.openaiua.fr:443 -servername n8n.openaiua.fr | \
  grep "Verify return code"

# 7. Проверить security headers
curl -I https://n8n.openaiua.fr | grep -i "strict-transport"

Если ответ не приходит на сайт:

// 1. Откройте DevTools (F12) в браузере
// 2. Перейдите на вкладку Console
// 3. Отправьте сообщение в чат
// 4. Проверьте что выводится в консоли

// Должны увидеть:
// - POST запрос на webhook URL
// - Статус 200 OK
// - JSON ответ с данными

// 5. Если ошибка CORS:
// - Проверьте что n8n_PROTOCOL=https
// - Перезапустите n8n: docker compose restart

Полезные команды

Управление сервисами

# n8n
docker compose -f /home/ubuntu/projects/n8n/docker-compose.yml restart
docker logs n8n --tail 100 -f

# Caddy
sudo systemctl reload caddy
sudo systemctl status caddy
journalctl -u caddy -f

# Landing page
cd /home/ubuntu/projects/landing
ps aux | grep "node.*server.js"
kill <PID>  # если нужно перезапустить
node server.js &

Тестирование

# Тест webhook
curl -X POST https://n8n.openaiua.fr/webhook/webhook/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "Hello"}' \
  -v

# Тест с кириллицей (используйте --data-binary)
curl -X POST https://n8n.openaiua.fr/webhook/webhook/chat \
  -H "Content-Type: application/json; charset=utf-8" \
  --data-binary '{"message": "Привет"}'

# Проверка SSL
curl -I https://n8n.openaiua.fr

# Проверка DNS
dig n8n.openaiua.fr

Итоговая статистика

Проблем найдено и решено: 5

  1. ✅ Пустой body в webhook (GET вместо POST)
  2. ✅ Webhook работает только 1 раз (тестовый URL)
  3. ✅ Неправильный URL (двойной префикс)
  4. ✅ Ответ не отображается (неправильное поле в JSON)
  5. ✅ SSL предупреждение в Chrome (отсутствие security headers)

Измененные файлы: 3

  1. /home/ubuntu/projects/landing/public/js/chat.js
  2. /home/ubuntu/projects/n8n/docker-compose.yml
  3. /etc/caddy/Caddyfile

Результат: Полностью рабочий AI чат на сайте 🎉


Финальные URLs


Дополнительные ресурсы


Автор: Claude Sonnet 4.5 Дата создания: 11 декабря 2025 Версия: 1.0