1

I have a mini-forum app includes auth, posts, comments and gateway that passes to the package. Locally all the requests work fine. But after deployment to Heroku only GET requests work and the others fail.

The error at logs: [HPM] Error occurred while proxying request anaalamed-mini-forum.herokuapp.com/api/login to http://localhost:4000/ [ECONNRESET] (https://nodejs.org/api/errors.html#errors_common_system_errors)

It's my first step, so... thanks for helping

gateway/index.ts

import { app } from 'api-server';
import { createProxyMiddleware } from 'http-proxy-middleware';
import fetch from 'node-fetch';
import * as express from 'express';
import * as path from 'path';

app.use(['/api/comments', '/api/posts'], async function checkAuth(req, res, next) {
try {
    const response = await fetch('http://localhost:4000/api/me', { headers: { cookie: req.headers.cookie } })
    const user = await response.text();
    const setCookie = response.headers.get('set-cookie')
    if (setCookie) {
        res.append('set-cookie', setCookie);
    }
    req.headers.user = user;
} catch {
    req.headers.user = '';
}
next();
})
app.use('/api/comments', createProxyMiddleware({ target: 'http://localhost:4002', changeOrigin: true }));
app.use('/api/posts', createProxyMiddleware({ target: 'http://localhost:4001', changeOrigin: true }));
app.use(['/api/users', '/api/me', '/api/register', '/api/login', '/api/logout'], createProxyMiddleware({ target: 'http://localhost:4000', changeOrigin: true }));

// serve UI
app.use(express.static(path.resolve(__dirname, '../../ui/build')));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../../ui/build', 'index.html'));
});

app.listen(process.env.PORT || 8080, () => console.log('Gateway app is running! on Port: ', process.env.PORT))

Logs

2021-08-06T10:19:59.365861+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=61068acdbe91bb0f7145ccf3" host=anaalamed-mini-forum.herokuapp.com request_id=5f0d58d4-fd3f-495a-b86c-6494fcc8ebe1 fwd="5.29.13.122" dyno=web.1 connect=0ms service=82ms status=304 bytes=183 protocol=https
2021-08-06T10:19:59.391481+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=61069bf0be91bb0f7145ccf4" host=anaalamed-mini-forum.herokuapp.com request_id=49fbacde-0fc5-491b-81e5-1538eda0747b fwd="5.29.13.122" dyno=web.1 connect=0ms service=80ms status=304 bytes=181 protocol=https
2021-08-06T10:19:59.332485+00:00 heroku[router]: at=info method=GET path="/api/comments?entity=610689fdbe91bb0f7145ccf2" host=anaalamed-mini-forum.herokuapp.com request_id=f75eab61-bfe5-43b4-8a53-c6757ff4972c fwd="5.29.13.122" dyno=web.1 connect=1ms service=81ms status=304 bytes=183 protocol=https
2021-08-06T10:19:59.364159+00:00 app[web.1]: [start:comments] ::ffff:127.0.0.1 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61068acdbe91bb0f7145ccf3 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.366881+00:00 app[web.1]: [start:gateway] ::ffff:10.13.124.73 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61068acdbe91bb0f7145ccf3 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.388509+00:00 app[web.1]: [start:comments] ::ffff:127.0.0.1 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61069bf0be91bb0f7145ccf4 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.390036+00:00 app[web.1]: [start:gateway] ::ffff:10.15.14.173 - - [06/Aug/2021:10:19:59 +0000] "GET /api/comments?entity=61069bf0be91bb0f7145ccf4 HTTP/1.1" 304 - "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.609755+00:00 app[web.1]: [start:gateway] ::ffff:10.32.238.58 - - [06/Aug/2021:10:19:59 +0000] "GET /icon.png HTTP/1.1" 200 157694 "https://anaalamed-mini-forum.herokuapp.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:19:59.616941+00:00 heroku[router]: at=info method=GET path="/icon.png" host=anaalamed-mini-forum.herokuapp.com request_id=4b32c985-21e1-46cf-b2b6-63ece2e09e57 fwd="5.29.13.122" dyno=web.1 connect=1ms service=12ms status=200 bytes=158004 protocol=https
2021-08-06T10:21:31.302014+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=POST path="/api/login" host=anaalamed-mini-forum.herokuapp.com request_id=3ff0432f-90f0-4e71-92b3-48d21c1966f3 fwd="5.29.13.122" dyno=web.1 connect=1ms service=30000ms status=503 bytes=0 protocol=https
2021-08-06T10:21:31.310593+00:00 app[web.1]: [start:gateway] [HPM] Error occurred while proxying request anaalamed-mini-forum.herokuapp.com/api/login to http://localhost:4000/ [ECONNRESET] (https://nodejs.org/api/errors.html#errors_common_system_errors)
2021-08-06T10:21:31.321710+00:00 app[web.1]: [start:gateway] ::ffff:10.39.170.242 - - [06/Aug/2021:10:21:31 +0000] "POST /api/login HTTP/1.1" 504 - "https://anaalamed-mini-forum.herokuapp.com/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:21:31.323846+00:00 app[web.1]: [start:auth] ::ffff:127.0.0.1 - - [06/Aug/2021:10:21:31 +0000] "POST /api/login HTTP/1.1" - - "https://anaalamed-mini-forum.herokuapp.com/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"
2021-08-06T10:21:31.334977+00:00 app[web.1]: [start:auth] BadRequestError: request aborted
2021-08-06T10:21:31.334980+00:00 app[web.1]: [start:auth]     at IncomingMessage.onAborted (/app/node_modules/raw-body/index.js:231:10)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at IncomingMessage.emit (events.js:400:28)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at abortIncoming (_http_server.js:566:9)
2021-08-06T10:21:31.334981+00:00 app[web.1]: [start:auth]     at socketOnClose (_http_server.js:559:3)
2021-08-06T10:21:31.334982+00:00 app[web.1]: [start:auth]     at Socket.emit (events.js:412:35)
2021-08-06T10:21:31.334982+00:00 app[web.1]: [start:auth]     at TCP.<anonymous> (net.js:675:12)

package.json at root

{
  "name": "mini-forum",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "workspaces": [
    "apps/*",
    "packages/*"
  ],
  "scripts": {
    "dev": "concurrently \"npm run dev:*\"",
    "dev:auth": "npm run dev --workspace=apps/auth",
    "dev:posts": "npm run dev --workspace=apps/posts",
    "dev:gateway": "npm run dev --workspace=apps/gateway",
    "db": "docker-compose --file ./mongo-compose.yaml up",
    "start": "node start.js",
    "start:comments": "cd apps/comments && npm start",
    "start:auth": "cd apps/auth && npm start",
    "start:posts": "cd apps/posts && npm start",
    "start:gateway": "cd apps/gateway && npm start",
    "postinstall": "node postinstall.js",
    "build": "cd apps/ui && npm install && npm run build"
  },
  "keywords": [],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "concurrently": "^6.0.2",
    "cors": "^2.8.5",
    "nodemon": "^2.0.7"
  },
  "engines": {
    "npm": "7.10.0"
  },
  "devDependencies": {
    "prettier": "2.3.1"
  }
}

start.js

const concurrently = require('concurrently');

// concurrently([{command: 'npm run start:*', env: process.env}])
concurrently([{command: 'npm run start:*'}])

So 'npm start' starts all the apps: auth, posts, comments and gateway. All the apps also have their own package.json and could start separately.

Ana
  • 11
  • 2

1 Answers1

0

What's the reason behind your createProxyMiddleware ? Once your app runs on a Heroku server, this would fail, since it's proxying the request to localhost:4002 / localhost:4001, which means the app forwards the request to another "local" service which would run on the same server instance (which they don't).

Locally for you it probably worked because you had those other service running locally while you tested your app, but those other service are not present on Heroku.

#1 Use a procfile

You can use a procfile to get multiple nodejs process running under 1 dyno. As already stated in this answer, this might look something like this :

web: node service1.js & node service2.js & node service3.js

However, as you need seperate PORTs for each of your services, this might not work for you since heroku only opens up 1 dynamically assigend PORT per dyno (available under process.env.PORT during runtime). If I'm correct this can't be changed.

#2 Use multiple apps/dynos

I believe the way it was intendent to be ( to establish a micro-service architecture ) using heroku is to create 1 app per service with at least 1 dyno each. A big PRO doing it this way would be the ability to scale each service independently from each other. And then just use the assigned subdomains to call them (app1.herokuapp.com, app2.herokuapp.com, ... ). Also you will end up having independents metrics and can update the dynos independently. Which is basically the idea behind micro services.

#3 Don't use micro-services just yet

Looking at your examples it feels like you might not need to split it up into multiple services. Think about creating a single API which might be easier to manage to begin with specially if you just starting.

turbopasi
  • 3,327
  • 2
  • 16
  • 43
  • So there is no need in createProxyMiddleware? How can I change it to make it work on Heroku? Thank you a lot! – Ana Aug 06 '21 at 11:49
  • It looks like you were trying to split up your app into multiple micro-services . If yes , you need those micro-service running as well on Heroku ... otherwise you can't reach them. Is that what you want to achieve ? – turbopasi Aug 06 '21 at 11:55
  • Yes, exactly. I need those micro-service running on Heroku – Ana Aug 06 '21 at 12:07
  • It depends on how you have this setup. Are these services seperate NodeJS/NPM projects which you start/stop independently ? Or do they all live within the same project and you just start all other services within a script for example ? You might want to share as much info as possible in your OP .... – turbopasi Aug 06 '21 at 12:40
  • I added some more info – Ana Aug 06 '21 at 14:10