Problem deploying only Apollo Server to heroku - express

I am deploying an Apollo Server for my database to heroku and it is giving an application error. It is not simply show that there is a problem with the get route, it says that the application has an error and the error logs say that the app is crashing. It runs fine locally.
I have set up the procfile with: web: node app.js .
I have tried it with the procfile removed.
I have set playground and introspection to true. I saw that that could be the problem but it did not seem to help.
The port is set to process.env.PORT || 8080 .
Here is the minimal code:
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const db = require('./models');
const typeDefs = require('./data/schema');
const resolvers = require('./data/resolvers');
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: { db },
introspection: true,
playground: true,
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 8080;
app.get('/', (req, res) => {
res.send('hello');
});
app.listen(PORT, () => {
console.log(`Server is ready at ${PORT}`);
});
I am also using some other functions (trying to set up a cron process), but those are commented out.
I would expect to get the / get route to at least say hello, or for the /graphql route to display playground. I am getting neither of those options.

It turns out that I needed to add the following to package.json:
"scripts": {
"start": "app.js",
...
}
And I needed to install packages listed in the heroku logs --tail, but I have had those errors before. Writing the script start key into the package.json file is for when you are deploying your server independently of your react (or client) side.

Related

issue with server middleware when deploying nuxt-app on heroku

I'm running into an issue to deploy a nuxt-app with some serverMiddleware code on Heroku.
this is my middleware code which just launch an express app:
api/index.js
var express = require("express");
var nodemailer = require("nodemailer");
var app = express();
app.use(express.json());
app.use(
express.urlencoded({
extended: true
})
);
app.get("/", (req, res) => {
res.send("hello world");
});
app.post("/contact", async (req, res) => {
// let testAccount = await nodemailer.createTestAccount();
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "mail.exemple.net",
port: 587,
secure: false,
auth: {
user: process.env.EMAIL_USERNAME,
pass: process.env.EMAIL_PASSWORD
}
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: req.body.email,
to: "contact#email.com",
subject: "new contact",
text: req.body.message
});
res.end();
});
app.listen(process.env.PORT);
module.exports = {
path: "/api",
handler: app
};
then i registered this file into nuxt.config.js:
serverMiddleware: ["~/api/index"],
the api works perfectly in dev mode (locally).
I first deployed on heroku with the nuxt target setting set to static,
the static content was working perfectly but none of the serverMiddleware code was working (that make senses ^^).
then i switched to target: 'server' but now when i deploy i get this message from heroku:
✖ Nuxt Fatal Error
Error: Address `0.0.0.0:41828` is already in use
i'm sure that i'm missing something but can't find the solution.
just to complete my post i added this line into the package.json file:
"heroku-postbuild": "nuxt build"
and also a Procfile at the root of my app which contain:
web: nuxt start
and finally these are my heroku:config settings:
heroku config:set NPM_CONFIG_PRODUCTION=false
heroku config:set HOST=0.0.0.0
heroku config:set NODE_ENV=production
Any advice on the correct way to deploy much appreciated.

How do I force or redirect my next.js website to use https

I thought this would be a simple task, but I struggle to find a way to force my webpage to use https.
The next.js webapp lives on the heroku servers and I've set up the SSL. Both https and http version works, but how to I force or redirect the website to use the https version.
I've seen some solution using express, but nothing in my webapp are using express, is it required?
Thanks.
As of Nextjs v12, you can use middleware instead of a setting up a custom server.
Middleware is a better solution for the following reasons:
a custom server often requires additional dependencies (like express)
you give up some of the box features like automatic static optimization
Middleware can be scope to specific paths using the built in routing paradigm
Create a /pages/_middleware.ts (or .js) file with something similar to this:
import { NextFetchEvent, NextRequest, NextResponse } from 'next/server'
type Environment = "production" | "development" | "other";
export function middleware(req: NextRequest, ev: NextFetchEvent) {
const currentEnv = process.env.NODE_ENV as Environment;
if (currentEnv === 'production' &&
req.headers.get("x-forwarded-proto") !== "https") {
return NextResponse.redirect(
`https://${req.headers.get('host')}${req.nextUrl.pathname}`,
301
);
}
return NextResponse.next();
}
I also created an npm package for this.
import sslRedirect from 'next-ssl-redirect-middleware';
export default sslRedirect({});
There is a solution with an NPM library called heroku-ssl-redirect.
First off, install the library using npm i heroku-ssl-redirect.
Then, create a new server.js file with the following script.
const next = require('next');
const express = require('express');
const sslRedirect = require('heroku-ssl-redirect').default; // to make it work with 'require' keyword.
const PORT = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
// Express's middleware to automatically redirect to 'https'.
server.use(sslRedirect());
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`Server starts on ${PORT}.`);
});
});
Then, change the start script to be like this:
"scripts": {
"dev": "next",
"build": "next build",
"start": "node server.js"
}
It should work.
Note that you could replace Express with the createServer method from native Node.js's http module. But I do this with Express to simplify the syntax.
Further reading: How to setup a custom server in Next.js.

Existing Repl.it Express Mongoose app now refusing to connect to MongoDB Atlas

I have an Express Mongoose app that used to connect to MongoDB Atlas without any problem whatsoever.
It is hosted on Repl.it
But when I checked today, it is not working.
MongooseError: The `uri` parameter to `openUri()` must be a string, got "undefined". Make sure the first parameter to `mongoose.connect()` or `mongoose.createConnection()` is a string.
Nothing has changed from last time, 21 days ago.
The packages are all the latest version.
Here is the code.
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const db = require("mongodb")
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
const port = process.env.PORT || 3000;
const uri = process.env.MONGO_URI;
mongoose.connect(uri, {
useNewUrlParser:true,
useUnifiedTopology:true,
serverSelectionTimeoutMS:6000
})
const connection = mongoose.connection;
connection.on('error', console.error.bind(console, 'connection error'));
connection.once('open', () => {
console.log("Connected successfully")
});
app.listen(port, () => {
console.log(`Server is running on port : ${port}`);
})
What could be the issue?
Any idea would be highly appreciated.
Thank you.
In repl.it, there is a 'Run' button, with a green 'Play' icon, against the project name.
You have to click on that to run the project.
For me, a 'node server.js' or 'npm start' shall not work!
This issue has been resolved.
Thank You.

Unable to find module 'server', added express to Ember-Cli app

I've added an expressJS app inside my ember app so I can provide a backend API for my ember app.
My process:
npm install express --save
I created a folder called "server" in the route of my ember application and inside that a file called "server.js".
Yesterday I had it working fine, I already had my ember app running via ember s and tested out the express app using nodemon server/server.js and checking the endpoints I created with Postman.
However this morning when I've tried to run ember s I'm given the following error:
C:\Sandbox\tsodash>ember s
version: 2.3.0-beta.2
Cannot find module 'C:\Sandbox\tsodash\server'
Error: Cannot find module 'C:\Sandbox\tsodash\server'
at Function.Module._resolveFilename (module.js:339:15)
at Function.Module._load (module.js:290:25)
at Module.require (module.js:367:17)
at require (internal/module.js:16:19)
at Project.require (C:\Sandbox\tsodash\node_modules\ember-cli\lib\models\project.js:281:12)
at Class.module.exports.Task.extend.processAppMiddlewares (C:\Sandbox\tsodash\node_modules\ember-cli\lib\tasks\server\express-server.js:115:33)
at Class.<anonymous> (C:\Sandbox\tsodash\node_modules\ember-cli\lib\tasks\server\express-server.js:220:21)
at lib$rsvp$$internal$$tryCatch (C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:1048:17)
at C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:331:11
Naturally I assumed I just needed to use modules.exports = function(){ //..expressjs code}
Full Code
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var request = require('request');
var btoa = require('btoa');
var config = require('./config');
var _ = require('lodash');
module.exports = function(){
var endPoints = config.endPoints;
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
var port = process.env.PORT || 4200;
var router = express.Router();
// middleware to use for all requests
router.use(function (req, res, next) {
// do logging
console.log('Something is happening.');
next(); // make sure we go to the next routes and don't stop here
});
router.get('/', function (req, res) {
res.json({
message: 'TSO Git Dash'
});
});
// ..
app.use('/api', router);
app.listen(port);
console.log('Magic happens on port: ' + port);
}
Still no avail.
Folder structure:
Any ideas? I'm assuming it's something simple that I've missed. But I'm stumped.
As #locks suggested in the comments, there is an express server used in mocks and fixtures. The fix was simple, I renamed the folder and the JS file to "api" and ran ember s and it worked perfectly. It seems to have been a naming conflict.

React Router, pushState with an Express Server

quick question regarding using React-Router. I'm having trouble getting my server to handle pushState (if this is the correct term). Originally, I was using a module called connect-history-api-fallback, which was a middleware that enabled me to only server up static files form my dist directory. Visiting the client www.example.com obviously worked and I could navigate throughout the site, additionally, refreshing at any route like www.example.com/about - could also work.
However, I recently added one simple API endpoint on my Express server for the React app/client to ping. The problem now is that while I can get the initial page load to work (and thus the /api/news call to work, to fetch data from a remote service), I can no longer do a refresh on any other routes. For example, now going to www.example.com/about will result in a failed GET request for /about. How can I remediate this? Really appreciate the help! PS - not sure if it matters, but I'm considering implementing Server Side Rendering later on.
import express from 'express';
import historyApiFallback from 'connect-history-api-fallback';
import config from '../config';
import chalk from 'chalk';
import fetch from 'node-fetch';
import path from 'path';
const app = express();
// FIXME: Unsure whether or not this can be used.
// app.use(historyApiFallback({
// verbose : true
// }));
//// DEVELOPMENT MODE ONLY - USING EXPRESS + HMR ////
/* Enable webpack middleware for hot module reloading */
if (config.get('globals').__DEV__) {
const webpack = require('webpack');
const webpackConfig = require('../build/webpack/development_hot');
const compiler = webpack(webpackConfig);
app.use(require('./middleware/webpack-dev')({
compiler,
publicPath : webpackConfig.output.publicPath
}));
app.use(require('./middleware/webpack-hmr')({ compiler }));
}
//// PRODUCTION MODE ONLY - EXPRESS SERVER /////
if (config.get('globals').__PROD__) {
app.use(express.static(__dirname + '/dist'));
}
//// API ENDPOINTS FOR ALL ENV ////
app.get('/api/news', function (req, res) {
fetch('http://app-service:5000/news')
.then( response => response.json() )
.then( data => res.send(data) )
.catch( () => res.sendStatus(404) );
});
// Wildcard route set up to capture other requests (currently getting undexpected token '<' error in console)
app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, '../dist', 'index.html'));
});
export default app;
Express works by implementing a series of middleware that you "plug in" in order via .use. The cool thing is your routes are also just middlware — so you can separate them out, have them before your history fallback, and then only requests that make it past your routes (e.g., didn't match any routes) will hit the fallback.
Try something like the following:
const app = express();
// ...
var routes = exprss.Router();
routes.get('/api/news', function (req, res) {
fetch('http://app-service:5000/news')
.then( response => response.json() )
.then( data => res.send(data) )
.catch( () => res.sendStatus(404) );
});
app.use(routes);
app.use(historyApiFallback({
verbose : true
}));