5

I am trying to run multiple NodeJs server for (official) Kik Chatbots with different webhooks from one Subdomain on my webserver.

However, I am not able to do that. For one bot it works just fine. This is my setup for one working NodeJs server only:

Lets assume all webhooks are located at https://bots.mydomain.com

app.js:

'use strict';
let util = require('util');
let http = require('http');
let request = require('request');
let Bot = require('@kikinteractive/kik');
let bot = new Bot({
    username: "foo",
    apiKey:   "bar",
    baseUrl:  "https://bots.mydomain.com"
});
bot.updateBotConfiguration();

// ... code ...

let server = http.createServer(bot.incoming()).listen(process.env.PORT || 8080);

So this Nodejs server is basically listening on port 8080. Therefore, my nginx config for the site https://bots.mydomain.com looks like this:

server {
    root /var/www/bots.mydomain.com/public_html;
    index index.php index.html index.htm;
    server_name bots.mydomain.com;
    location / { proxy_pass http://localhost:8080/; } # Port 8080
}

So far so good. This works perfectly fine! But here comes the issue:

If I try to run multiple NodeJs server, by making directories in the public_html folder, lets say /bot1 and /bot2 and adapt my nginx config like that:

 server {
    root /var/www/bots.mydomain.com/public_html;
    index index.php index.html index.htm;
    server_name bots.mydomain.com;
    location /bot1 { proxy_pass http://localhost:8080/; } # Port 8080
    location /bot2 { proxy_pass http://localhost:8090/; } # Port 8090
}

and finally setting the second server to listen on port 8090 instead of 8080 and of course setting the base URL to https://bots.mydomain.com/bot1 or https://bots.mydomain.com/bot2, nothing works anymore. And by that I mean the webhooks do not pass any data to the NodeJs server. They are, however running! I know this because if I navigate to (for example) https://bots.mydomain.com while the bot is offline, I obviously receive the error 502 Bad Gateway but if the bot is online I get a timeout (which means the server is indeed listening).

Am I missing something or does Nginx just not allow multiple webhooks or proxy_passes for directories?

A workaround would be to make a subdomain for each bot, which would work (I tried). But I'd like to use sub directories rather than subdomains for the bots.

EDIT:

I noticed a strange behavior: If I set a proxy_pass for /

like: location / { proxy_pass http://localhost:8080; }

to port 8080 and set the baseurl in the bot1 script to bots.mydomain.com/bot1, Bot-1 works.

But I obviously still can't get other bots to work as well because I'm using the root (/).

Does that mean it's a problem with Kik-API's way of listening?

EDIT 2:

I checked the Nginx Log now and it seems like the Kik Wrapper tries to listen on a directory which doesn't exists. I did the following: Start the bot on port 8080 & message it. This is the log output:

https://pastebin.com/7G6TViHM

2017/04/13 09:07:05 [error] 15614#15614: *1 open() "/var/www/bots.mydomain.com/public_html/incoming" failed (2: No such file or directory), client: 107.XXX.XXX.XXX, server: bots.mydomain.com, request: "POST /incoming HTTP/1.1", host: "bots.mydomain.com"
2017/04/13 09:07:13 [error] 15614#15614: *1 open() "/var/www/bots.mydomain.com/public_html/incoming" failed (2: No such file or directory), client: 107.XXX.XXX.XXX, server: bots.mydomain.com, request: "POST /incoming HTTP/1.1", host: "bots.mydomain.com"

But I still don't know how to fix this. As a test I created the directory incoming in public_html. This returned the following in the log:

2017/04/13 09:32:41 [error] 15614#15614: *10 directory index of "/var/www/bots.mydomain.com/public_html/incoming/" is forbidden, client: 107.XXX.XXX.XXX, server: bots.mydomain.com, request: "GET /incoming/ HTTP/1.1", host: "bots.mydomain.com"

Does anyone have an idea on how to fix it?

NullDev
  • 6,739
  • 4
  • 30
  • 54

3 Answers3

1

I think your issue lies with a trailing slash in proxy_pass, which removes the /bot1 and /bot2 prefixes once passed to upstream (replacing both with mere /), so, each bot in your nodejs code has a mismatched baseUrl setting as a result (as you mention that you did change those settings appropriately to match the external URL).

-location /bot1 { proxy_pass http://localhost:8080/; } # Port 8080
-location /bot2 { proxy_pass http://localhost:8090/; } # Port 8090
+location /bot1 { proxy_pass http://localhost:8080; } # Port 8080
+location /bot2 { proxy_pass http://localhost:8090; } # Port 8090
cnst
  • 25,870
  • 6
  • 90
  • 122
  • I actually put those trailing slashes there, because another post suggested trying that since it's a proxy_pass for a subdirectory. However I noticed a strange behavior: If I set a proxy pass for `/` to port 8080 and set the baseurl in the bot1 script to `bots.mydomain.com/bot1`, it works. But I obviously still can't get other bots to work aswell because I'm using the root (`/`). – NullDev Apr 12 '17 at 10:19
  • @NullDev, the other comment suggested adding slashes in a different context (and was merely a random suggestion); please try what I said, I'm pretty sure it'll have a very high chance of working (that is, if kik is capable of doing this in the first place), because your original code 100% won't work. – cnst Apr 13 '17 at 06:35
  • I have tried what you suggested but It didn't work. Also, I wasn't talking about the comment here. An answer on another question suggested it (I can't find it right now). – NullDev Apr 13 '17 at 07:14
1

In case anyone comes across this question:

It's just not possible by Kik's API design.

When you initialize your bot with

let bot = new Bot({
    username: "foo",
    apiKey:   "bar",
    baseUrl:  "https://bots.mydomain.com"
});

this baseUrl is essentially a webhook and cannot be re-used. It has to be somewhat unique.
A possible work-around would be specifying a port directly in the base-url.

NullDev
  • 6,739
  • 4
  • 30
  • 54
0

It probably doesn't wok because your target servers get the path that includes the /bot1 and /bot2 prefix, which they may not expect.

Maybe try:

location /bot1 {
    rewrite ^/bot1/(.*)$ /$1 break;
    proxy_pass http://localhost:8080/;

}
location /bot2 {
    rewrite ^/bot2/(.*)$ /$1 break;
    proxy_pass http://localhost:8090/;
}
rsp
  • 107,747
  • 29
  • 201
  • 177