Nodejs api not accepting the POST method, error 405 - node.js

I already search for existing question, but none of them worked for me.
I've simple nodejs methods, on my localhosts they work fine, but when I hosted them on a server (nginx), my post method gives error of 405 (not allowed), even though I've allowed CORS
Here is my server file
var http = require('http');
var mongo = require('mongodb');
var cors = require('cors')
var express = require('express');
var app = express();
app.use(cors());
var DB = 'mongodb://localhost:27017/ClientApp';
app.use(express.json());
const clientRoutes = require('./client');
const authRoutes = require('./auth');
app.get('/api/status', (request, response) => {
// console.log(request.body);
response.json({ status: ' Server Running' });
});
app.use('/', clientRoutes);
app.use('/', authRoutes);
app.listen(3000, (resp) => {
console.log('server listening at port number: ', 3000);
});
and here is the route that is not working
app.post('/api/register', (request, response) => {
console.log('Request body: ', request.body);
mongo.connect(DB, (error, client) => {
console.log('Connect to Database successfully');
const connectedDb = client.db('ClientApp');
data = request.body;
if (data.username) {
connectedDb.collection('Users').insertOne(data, (error) => {
if (error)
console.log('Error occured while registration')
else {
response.status(200).send({ status: 'Response Received Successfully', code: 200 })
console.log('User registered successfully!');
}
})
} else {
response.status(204).send({ status: 'Please include the user details', code: 204 })
}
})
});

I see you have your app's listening port set to 3000. You will need to verify in the nginx.conf file that is the port the traffic is being set to from the reverse proxy. Depending on how things are setup, there may be an environment variable set indicating which port the app should listen to. This variable is commonly called PORT.
If the PORT environment variable is being set you can change your code like so:
app.listen(process.env.PORT || 3000, (resp) => {
console.log('server listening at port number: ', 3000);
});
In case you're not aware, using process.env.PORT || 3000 will use the value process.env.PORT if it is set. If it is falsy then 3000 will be used.
For NGINX have a look at the nginx.conf at the server entries to determine how the reverse proxy is sending traffic to backend apps.

Related

How do I create a server that can accept post requests and broadcast as a websocket server?

I am attempting to create a server that will accept a post request (coming from a flutter app) containing the name of a song. I then want the server to broadcast the name of that song to all listening clients.
I've tried a dozen ways to do this and nothing seems to work. I've tried using express and flask, but to no avail. Here's where I'm at right now, but obviously this doesn't work because I can't get the script to start both the socket server (using npm start) and api (using node index.js) at the same time. You'll also notice that I'm not currently sending a song name, just trying to send a time to start.
'use strict';
const port = process.env.PORT || 3000;
const express = require('express');
const { Server } = require('ws');
const PORT = process.env.PORT || 3000;
const INDEX = '/index.html';
const server = express()
.use((req, res) => res.sendFile(INDEX, { root: __dirname }))
.listen(PORT, () => console.log(`Listening on ${PORT}`));
const wss = new Server({ server });
wss.on('connection', (ws) => {
console.log('Client connected');
ws.on('close', () => console.log('Client disconnected'));
});
setInterval(() => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
}, 1000);
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.post('/', (req, res) => {
wss.clients.forEach((client) => {
client.send(new Date().toTimeString());
});
res.send('POST request reached server');
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})

Getting 'port already in use error' when adding socket.io to express app - happens on any port I try

As stated in the title, I'm getting 'address already in use error' when trying to add socket.io to an existing express app.
It happens on every port so the only thing I can think of is it's trying to set port 8000 twice. I don't see where, however.
Here is the error in the console.
Here is my config.js
module.exports = {
PORT: process.env.PORT || 8000,
NODE_ENV: process.env.NODE_ENV || 'development',
DATABASE_URL: process.env.DATABASE_URL || 'postgresql://postgres#localhost/quik'
}
.env
NODE_ENV=development
PORT=8000
And here is my main express app. I've tried setting PORT from process.env and directly with '8000'.
require('dotenv').config()
const morgan = require('morgan')
const cors = require('cors')
const helmet = require('helmet')
const { NODE_ENV } = require('./config')
const userRouter = require('./user/user_router')
const pinsRouter = require('./pins/pins_router')
const chatRouter = require('./chat/chat_router')
const config = require('./config')
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(config.PORT, function(){
console.log('listening on *:8000');
});
const morganOption = (NODE_ENV === 'production')
? 'tiny'
: 'common';
app.use(morgan(morganOption))
app.use(helmet())
app.use(cors())
app.use('/user_route', userRouter)
app.use('/pins_route', pinsRouter)
app.use('/chat_route', chatRouter)
app.get('/', (req, res) => {
res.send('Hello, world!')
})
app.use(function errorHandler(error, req, res, next) {
let response
if (NODE_ENV === 'production') {
response = { error: { message: 'server error' } }
} else {
console.error(error)
response = { message: error.message, error }
}
res.status(500).json(response)
})
module.exports = app
The stack trace in the error appears like you are calling app.listen() somewhere (probably from your server.js - line 13). You need to go find that code and remove it. You only want to attempt to start your same server once and your http.listen() is already starting it once.

ERR_HTTP_HEADERS_SENT node js socket connection

I am building an API that uses socket connection to interact with a server backend built in C#. This is what I have so far
const request = require('request');
const express = require('express');
const app = express();
var server = require('http').createServer(app);
var cors = require("cors");
app.use(cors());
const net = require('net');
const client = new net.Socket();
const stringToJson=require('./stringToJson')
const port = process.env.PORT;
const host = process.env.HOST;
client.keepAlive=true
client.on('close', function() {
console.log('Connection closed');
});
app.get('/getScores',function (req,res) {
let dataSend=''
client.on('data', function (data) {
console.log('Server Says : ' + data);
if(data!='ANALYSIS-ERROR'){
dataSend=stringToJson.stringToJson(data)
}
else{
dataSend=stringToJson.stringToJson('0:0.0:0.0:0.0:0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0')
}
client.destroy()
return res.send(dataSend)
});
client.connect(port, host, function () {
client.write(`GENERAL-ANALYSIS|${req.query.id}|${req.query.website}|`)
return
});
return
})
app.get('/getPlace',function (req,res) {
console.log(req.query)
request(
{ url: `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${req.query.name}+in+${req.query.city}&key=${process.env.API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: error.message });
}
return res.json(JSON.parse(body));
}
)
})
//TODO ADD 404 500 PAGES
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
server.listen(9000, () => {
console.log(`App running at http://localhost:9000`);
});
Basically it creates a connection with the server and listens for some data to be sent back. Then processes the string and sends it to the React frontend. The api calls are made by the frontend using axios
It works but if you refresh the page it throws this error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How do I fix this?
Try setting the headers as found in the documentation request.setHeader(name, value)
request.setHeader('Content-Type', 'application/json');

using domain name with expressjs on server rather than localhost

OK, so I am successfully running expressjs on windows iis server localhost:5000 and getting the expected json response using the following code...
server.js
const express = require('express');
var cors = require('cors')
const api_helper = require('./API_helper')
//const api_helper = require('./api')
const app = express();
const port = process.env.PORT || 5000;
require('ssl-root-cas/latest')
.inject()
.addFile('./root.crt')
.addFile('./****.crt')
// create a GET route
/* app.get('/express_backend', (req, res) => {
res.send({ express: 'YOUR EXPRESS BACKEND IS CONNECTED TO REACT' });
}); */
app.get('/express_backend', (req, res) => {
res.type('json')
api_helper.make_API_call('https://*my_api_server*/api/company/')
//api_helper.make_API_call('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
res.send(response)
})
.catch(error => {
res.send(error)
})
})
app.listen(port, () => console.log(`App listening on port ${port}!`))
API_helper.js
const request = require('request')
module.exports = {
/*
** This method returns a promise
** which gets resolved or rejected based
** on the result from the API
*/
make_API_call : function(url){
return new Promise((resolve, reject) => {
res.set('Content-Type', 'application/json');
request(url, { json: true }, (err, res, body) => {
if (err) reject(err)
resolve(body)
});
})
}
}
Screenshot of successful response using localhost:5000...
My question is, how would I get this to work using a domain name instead of localhost? When I use our https domain name, I get no response headers and just the raw html for server.js
Thanks.
When running on a port less than 1025, you need to run the server with escalated privileges.
If running on Windows ensure that your Command Line is running with Administrator Permissions.
With Linux:
sudo node server.js

Start a nodejs tcp server within nodejs app

My use case to start and stop a tcp server within the nodejs app that i am writing.
So I have an index.js which starts up a web server on port 3000. Using endpoints '/' and '/start', i would like to get the status of the server and start the server respectively. I would also like to display the status of the server via socket.io but that's for later.
Right now, I am getting a
TypeError: Converting circular structure to JSON
error which I think it is probably attributable to returning the server object below.
How can I start and stop the tcp server via REST endpoints?
// server.js
'use strict'
var net = require('net')
var server = false
exports.get = function() {
return server
}
exports.start = function(port, host) {
if (!server) {
server = net.createServer(handleConnection).listen(port, host)
return server
}
}
exports.stop = function() {
if (server) {
server.close(() => {
console.log(`server.close called`)
})
server = null
return server
}
}
function handleConnection(socket) {
...
}
Here is the index.js
// index.js
'use strict'
var net = require('net')
var http = require('http')
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
var addServer = require('./server')
var PORT = 3000
var HOSTNAME = '127.0.0.1'
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
var server = http.createServer(app).listen(PORT, HOSTNAME, () => {
console.log('http.createServer started')
})
app.get('/', (req, res) => {
// get addServer status
addServer.get()
res.status(200).json({ status: 'success', command: addServer.get() })
})
app.get('/start', (req, res) => {
// start addServer
addServer.start(9000, '127.0.0.1')
res.status(200).json({ status: 'success', response: '' })
})
You're trying to return server object via json.
res.status(200).json({ status: 'success', command: addServer.get() })
Try without it.
res.status(200).json({ status: 'success' })

Resources