Unable to setup Express server on HTTPS - javascript

Trying to set up my Express server on HTTPS but unable to access my api. Here is my code:
// server.js
const express = require('express');
const { readFileSync } = require('fs');
const https = require('https');
const app = express();
const key = readFileSync(
'/etc/letsencrypt/live/mydomain.com/privkey.pem',
'utf8'
);
const cert = readFileSync(
'/etc/letsencrypt/live/mydomain.com/fullchain.pem',
'utf8'
);
const ca = readFileSync(
'/etc/letsencrypt/live/mydomain.com/chain.pem',
'utf8'
);
const credentials = { key, cert, ca };
const port = 443
const server = https.createServer(credentials, app);
server.listen(port, () => console.log(`Server is running on port ${port}`));
The error I am receiving is a 502 Bad gateway on all calls to the server.
Everything worked perfectly before when I was running on HTTP like this:
const server = app.listen(8000, () => {});
Beside the URL on my site I can see the padlock icon and it says my site is secure so I believe my certifcate is valid.
Have seen a lot of similar questions posted on here and followed what I've seen in responses. I've even asked chatGPT to check my code and it doesn't see any errors. I've also tried reading my SSL keys as .env variables so I don't think the issue is an incorrect file path.
Can anybody please help me find the solution?
EDIT
Here is an example of a get request I am making to my backend using axios:
const fetchMembers = async () => {
await axios
.get(`/api/total-users`)
};
This invokes a function totalUsers with express.Router from a users file in my routes folder on the backend:
// routes/users.js
const express = require('express');
const router = express.Router();
router.get('/total-users', totalUsers);
const totalUsers = async (req, res) => {
try {
const total = await User.find().estimatedDocumentCount();
res.json(total);
} catch (err) {
console.log(err);
}
};
I am using a middleware app.use with a prefix /api and importing the users file to make a connection to my endpoints:
// server.js
const userRoutes = require('./routes/users')
app.use('/api', userRoutes)
While editing this question I tried modifying the middleware prefix to `:443/api' however this still hasn't helped.

Where is User defined inside of routes/users.js? You need to import your DB models before accessing them like this:
const total = await User.find().estimatedDocumentCount();
Otherwise, generally when running fetch('/api...), React will try to access localhost:3000/api instead of localhost:443/api.
React needs to know where to proxy requests to the backend. One way is using the http-proxy-middleware library and by defining a setupProxy.js file.
client/src/setupProxy.js
/**
* Proxy most calls to the server
* #type {Array}
*/
/* eslint-disable #typescript-eslint/no-var-requires */
const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy_urls = ['/api/*';
const target = 'https://localhost:443';
module.exports = function (app) {
proxy_urls.forEach((url) => {
app.use(url, createProxyMiddleware({ target }));
});
};

Related

trying to hide api but backend gives me error

image of the error I am trying to build nft search app that when you give adress it finds the nfts that a wallet has. but i am using alchemy and don't want to expose api key. Don't know backend, using next.js.
my backend code:
const express = require("express");
const axios = require("axios");
const dotenv = require("dotenv");
dotenv.config();
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/api", (req, res) => {
const apiKey = process.env.API_KEY;
const owner = req.query.owner;
const baseURL = `https://eth-mainnet.g.alchemy.com/nft/v2/${apiKey}/getNFTs/`;
const fetchURL = `${baseURL}?owner=${owner}`;
axios
.get(fetchURL)
.then((response) => {
res.json(response.data);
})
.catch((error) => {
res.json({ error: error.message });
});
});
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
my frontend
const fetchNFTs = async () => {
const response = await fetch(`/api?${wallet}`);
const nfts = await response.json();
setNFTs(nfts);
};
I tried chat gpt, serverless function but I failed to achieve results
Is this a separate Express server? By default Next.js runs on port 3000, and that's why you're making a GET to localhost:3000. But if your Next.js server is started, your custom Express server would pick a different port because the 3000 is going to be taken. So your const response = await fetch('/api?${wallet}'); will result in a 404 because there's no such route in your Next.js app.
You could move your function into a Next.js API handler if you want your backend and frontend to live under the same port. Also you wouldn't need to manually create the express server and take care of the dotenv since Next.js is going to take care of that for you.

I am running into the follow error: Error: Query.totalPosts defined in resolvers, but not in schema

I am running into the error: Error: Query.totalPosts defined in resolvers, but not in schema. I have been looking for a solution but am unable to find a work around or a solution.
my server.js:
const express = require('express')
const {ApolloServer} = require('apollo-server-express');
const http = require('http');
const path = require('path');
const {fileLoader, mergeTypes} = require('merge-graphql-schemas');
require('dotenv').config();
// //resolvers`enter code here
const resolvers = {
Query: {
totalPosts: () => 42,
me: () => 'Gaia'
}
};
const typeDefs = mergeTypes(fileLoader(path.join(__dirname, './typeDefs')));
async function startApolloServer(typeDefs, resolvers){
const apolloServer = new ApolloServer({typeDefs, resolvers});
const app = express();
// typeDefs
// const typeDefs = mergeTypes(fileLoader(path.join(__dirname, './typeDefs')));
await apolloServer.start();
//this method connects Apollo server to a specific HTTP framework ie: express
apolloServer.applyMiddleware({app, path: '/graphql'});
apolloServer.applyMiddleware({ app });
const httpserver = http.createServer(app);
// rest endpoint
app.get('/rest', function(req, res) {
res.json({
data: 'hit rest endpoint'
});
});
app.listen(process.env.PORT, function() {
console.log(`Server running at http://localhost:${process.env.PORT}`);
console.log(`Graphql server running at http://localhost:${process.env.PORT}${apolloServer.graphqlPath}`);
});
};
startApolloServer(typeDefs, resolvers);
Your field totalPosts exist in typeDef ?
As documentation said in step 3, https://www.apollographql.com/docs/apollo-server/getting-started/ , you have to define your graphql schema for use it.
Every GraphQL server (including Apollo Server) uses a schema to define the structure of data that clients can query. In this example, we'll create a server for querying a collection of books by title and author.
You should type something like this :
type Query {
totalPost: Int
me: String
}
And, when i build a graphql api on nest.js, schema file automaticly build. I guess, it's same way with express.
Did you try to setup your api following this doc : https://www.apollographql.com/docs/apollo-server/v2/integrations/middleware
typeDef look like automaticly resolve and push to a schema file. You may re-load your serve when it's should be update.
const express = require('express');
const { ApolloServer } = require('apollo-server-express');
const { typeDefs, resolvers } = require('./schema');
async function startApolloServer() {
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
});
await server.start();
server.applyMiddleware({ app });
app.use((req, res) => {
res.status(200);
res.send('Hello!');
res.end();
});
await new Promise(resolve => app.listen({ port: 4000 }, resolve));
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`);
return { server, app };
}

How can I deploy an app in which I am using express.js and puppeteer? (smth like an REST API)

Before anything, its my first question on stackoverflow, so im sorry if something isnt
correct.
Here is my repository: https://github.com/Ellisarm/FLASH
Details about the app:
in index.js file i am using express and i am importing from scrapers.js and meciuri&ids.js 2 functions in which i am scraping 2 arrays. Each functions is used with either app.post or app.get. I assigned a path also to them.
So basically, i want to enter on a http and get some data from there, data which is scraped thanks to puppeteer.
I've tried to deploy the application on heroku, but i didnt recieve the data, i have errors. I've made a lot of research before questioning this...
THIS is my index.js file
const express = require('express')
const cors = require('cors')
const scrapeProduct = require('./scrapers.js')
const scrapeProductSecond = require('./meciuri&ids.js')
const app = express()
const port = 8081
app.use(cors())
app.use(express.json())
app.post('/puppeteer', async (req, res) => {
const cote = await scrapeProduct(req.body.url)
console.log(cote);
res.status(201).send(cote)
})
app.get('/', async(req, res) =>{
const {echipeAcasa} = await scrapeProductSecond()
const {echipeDeplasare} = await scrapeProductSecond()
const {theIds} = await scrapeProductSecond()
console.log(typeof echipeAcasa, typeof echipeDeplasare, typeof theIds);
console.log( echipeAcasa, echipeDeplasare, theIds);
res.status(201).send([echipeAcasa, echipeDeplasare, theIds])
})
app.listen(process.env.PORT || port, ()=> console.log("Example app listening on port " + port))
I would appreciate even a link where i can research more or even a idea... thanks

Auto update ssl node.js

is there any way to make the node.js server update automatically with the new certificates generated by let's encrypt every 3 months without restarting the service?
My server has a hosting panel that auto manages the certificates, so I can't use the certbot manually.
Currently I have a cron that runs monthly and restarts the server to take the new changes, but sometimes the certificate changes a few days before and my sites and apis stop working until my server restarts. It doesn't seem to me the most optimal solution.
const fs = require("fs");
const https = require("https");
const express = require("express");
const helmet = require("helmet");
var cors = require("cors");
const API = require("./index.js");
const hostname = "ENV.HOSTAME";
const httpsPort = ENV.PORT;
const httpsOptions = {
cert: fs.readFileSync("CERT-PATH"),
ca: fs.readFileSync("CA-PATH"),
key: fs.readFileSync("CA-KEY"),
};
const app = express();
app.use(helmet());
app.use(cors());
const httpsServer = https.createServer(httpsOptions, app);
// Parse URL-encoded bodies (as sent by HTML forms)
//app.use(express.urlencoded());
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.get("/", function (req, res) {
res.redirect("HOSTNAME");
});
app.post("API-ROUTE", async function (req, res) {
const response = await API(req);
if (response != "Error") {
res.status(200).send(response);
} else {
res.status(500).json({ message: "Server Error" });
}
});
httpsServer.listen(httpsPort, hostname);
nodejs uses http service and nginx for reverse proxy. When the certificate is updated, there is no need to restart the whole service. Executing nginx -s reload works for me.

receive 404 error from post request: postman

I am trying to make a post request from postman but I'm receiving a 404 error: SyntaxError: Unexpected token n in JSON at position 4<br> at JSON.parse.
I have added the Content-Type: application/json header and defined the json body in the raw tab.
This is the url: http://localhost:8000/api/signup.
I can't make this post request nor can I access the application in the browser as I receive cannot GET /api/signup.
How can I fix this?
controllers/user.js
const User = require('../models/user')
const { errorHandler } = require("../helpers/dbErrorHandler")
exports.signup = (req, res) => {
console.log("req.body", req.body)
// signs up new user
const user = new User(req.body)
user.save((err, user) => {
if(err) {
return res.status(400).json({
err: errorHandler(err)
})
}
res.json({
user
})
})
}
app.js
const express = require('express')
const mongoose = require('mongoose')
const morgan = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
require('dotenv').config()
// import routes
const userRoutes = require('./routes/user')
// app
const app = express()
// connect db - first arg is url (specified in .env)
mongoose.connect(process.env.DATABASE, {
useNewUrlParser: true,
useCreateIndex: true
}).then(() => console.log('DB connected'))
// middlewares
app.use(morgan('dev'))
app.use(bodyParser.json())
// used to save users credentials
app.use(cookieParser())
// routes middleware
app.use('/api', userRoutes)
const port = process.env.PORT || 8000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
models/user.js
const mongoose = require('mongoose')
const crypto = require('crypto')
const uuidv1 = require('uuid/v1')
const userSchema = new mongoose.Schema ({
...
}, {timestamps: true})
userSchema.methods = {
encryptPassword: function(password) {
if (!password) return '';
// hashes password
try {
return crypto.createHmac('sha1', this.salt)
.update(password)
.digest('hex')
} catch (err) {
return ''
}
}
}
module.exports = mongoose.model("User", userSchema)
routes/user.js
const express = require('express')
const router = express.Router()
const { signup} = require('../controllers/user')
router.post('/signup', signup)
module.exports = router
404 means NOT Found,
May be your URL or Method is wrong
Here is what you can try to diagnose:
Check if server is running
Check the port and URL you are accessing.
Check the postman method POST and URL.
Check the route, routes file and match it with postman URL
This seems like two different issues, for the POST request, the error seems like there is an invalid string in your JSON payload that your application cannot read and parse.
The second one is mainly due to the route is not found, without looking at your ./routes/user file, it seems like there are two possibilities:
You have a nested route of /user/.... If that is the case, try accessing your api via /api/user/signup instead of /api/signup
You did not create a GET route for you signup path. Normally signup is a POST path instead of GET.
It would be best if you can provide the source code of ./routes/user.js for us to properly answer this.
404 error is an HTTP status code that means that the page you were trying to reach on a website couldn't be found on their server. To be clear, the 404 error indicates that while the server itself is reachable, the specific page showing the error is not.
Make sure that your indexing is correct and your local server is running properly.

Categories