Search code examples
node.jstelegram-botwebhookstelegram-webhooktelegraf.js

404 error using Telegraf webhook for a bot


I'm trying to make a Telegram bot working, and I'm using Telegraf.js. I've set up a webhook by adding a subdomain to my domain name with a default Apache VirtualHost.
It's basically working but for a reason I've got a 404 error from the Telegram's webhook API info (getWebhookInfo):

{
  "ok": true,
  "result": {
    "url": "https://subdomain.domain.tld/telegraf/<chain-of-64-letters-and-numbers>",
    "has_custom_certificate": false,
    "pending_update_count": 12,
    "last_error_date": 1652692046,
    "last_error_message": "Wrong response from the webhook: 404 Not Found",
    "max_connections": 40,
    "ip_address": "XX.XX.XX.XX"
  }
}

I've noticed a suffix has been appended for a reason (I'm supplying only the subdomain URL without any path), it's probably from Telegraf.js but it seems to be causing the 404 error.

My code:

const { Telegraf } = require("telegraf");
require("dotenv").config();

// Bot initialization
const token = process.env.API_KEY;
if (token === undefined) {
    throw new Error("Token not defined!");
}

const bot = new Telegraf(token/*, {
    telegram: {
        apiRoot: "http://127.0.0.1:" // I'm planning to use tdlib/telegram-bot-api later on
    }
}*/);

// Commands handling
bot.start(ctx => {
    console.info("ok!");
    ctx.reply("Hello from bot!");
});

bot.on("text", () => console.info("text received"));

bot.command("test", ctx => ctx.reply("Working!!"));

bot.command("quit", ctx => ctx.leaveChat());

// Bot launching
bot.launch({
    webhook: {
        domain: "https://subdomain.domain.tld",
        port: 3000 // I've seen 3000 is frequently used so let's use that
    }
}).then(
    resolve => console.info(`Bot '${bot.botInfo.username}' (${bot.botInfo.id}) started successfully (${resolve || "OK"})`),
    reject => console.info(`Bot '${bot.botInfo.username}' (${bot.botInfo.id}) failed to start: ${reject}`)
);

// Graceful stop handling
process.once("SIGINT", () => bot.stop("SIGINT"));
process.once("SIGTERM", () => bot.stop("SIGTERM"));

My VirtualHost:

<VirtualHost *:443>
    ServerName subdomain.domain.tld

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Let's Encrypt
    SSLCertificateFile /etc/letsencrypt/live/domain.tld-0001/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/domain.tld-0001/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>

What am I doing wrong?


Solution

  • I forgot to add the ProxyPass on my Apache VirtualHost:

    <VirtualHost *:443>
        ServerName subdomain.domain.tld
    
        # Missing part
        ProxyPreserveHost On
        ProxyRequests Off
        AllowEncodedSlashes NoDecode
        SSLProxyEngine On
        SSLProxyCheckPeerCN Off
        ProxyPass / http://localhost:3000/
        ProxyPassReverse / http://localhost:3000/
        # End of missing part
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        # Let's Encrypt
        SSLCertificateFile /etc/letsencrypt/live/domain.tld-0001/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/domain.tld-0001/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf
    </VirtualHost>
    

    Now it's working like a charm.