Hy Guys i try to make a simple API but i would like do something thani can't cuz i just learn nodejs not long. I would like than instead the api display
Cannot Get /ROUTE
Display this
{
"code": 404,
"message": "Not found"
}
Att All routes.
My code :
var http = require("http");
var express = require('express');
var app = express();
var mysql = require('mysql');
var bodyParser = require('body-parser');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'root',
database : 'restapi',
port : '8889'
});
connection.connect(function(err) {
if (err) throw err
console.log('Congrats you are connected')
})
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
var server = app.listen(3000, "127.0.0.1", function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
app.all('/*', function(req, res, next) {
// CORS headers
res.header("Access-Control-Allow-Origin", "*"); // restrict it to the required domain
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// Set custom headers for CORS
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
if (req.method == 'OPTIONS') {
res.status(200).end();
} else {
next();
}
});
//GET Domains
app.get('/api/domains.json', function (req, res) {
console.log(req);
connection.query('select * from domain', function (error, results, fields) {
if (error) throw error;
var user = results[0];
if (user == undefined) {
res.status(404);
res.send({
code: 404,
message: "Not found"
});
} else {
res.send({
code: 200,
message: 'success',
datas: results
});
}
});
});
So its just one request for the moment but i will try to add POST, PUT and Delete, juste make a simple CRUD.
I see one thing that can affect expected behaviour. You are declaring a more general route before the most specific one.
This one is so generic, that is going to treat all requests
app.all('/*',
And this one is included in the previous one, so noone request is going to be treated here.
app.get('/api/domains.json',
Try to change the order of both routes, and tell me if it changes the behaviour.
res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
if (req.method == 'OPTIONS') {
res.status(200).end();
} else {
res.status(404);
res.send({
code: 404,
message: "Not found"
});
}
I change the conditions and it works.
Related
I'm trying to make a simple POST request but I'm getting an empty response back from the server. I've sifted through all the SO questions regarding this topic and tried the solutions posted but to no avail.
I've tried changing the request header options to use 'application/x-www-form-urlencoded' and set bodyParser in my express app as app.use(bodyParser.urlencoded({ extended: true })); but that didn't work either.
auth-service.service.ts
login(loginInfo: object) {
return this.http.post<loginInfo>(this.loginUrl, { "test": "test" })
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log('An error occured:', error.error.message);
} else {
console.log(`Backend returned code ${error.status}, ` +
`body was ${error.error}`);
}
return throwError('Something bad happened; please try again later.')
}
login.component.ts (calls the login service method)
onSubmit() {
const loginInfo = { username: this.username.value, password: this.password.value };
this.authService.login(loginInfo).subscribe(
resp => { console.log(resp); },
err => { console.log(err); }
)
}
server.js (I've defined routes here but they're not relevant)
const express = require('express');
const bodyParser = require('body-parser');
const api = require('./routes/api');
const app = express();
const port = process.env.port || 3000;
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
})
app.use(bodyParser.json());
app.use('/api', api)
app.get('/', function (req, res) {
res.send(JSON.stringify('Hello from server'));
})
app.post('/login', (req, res) => {
let userData = req.body
res.send('Request body: ' + JSON.stringify(userData));
})
app.listen(port, function () {
console.log('Server running on localhost: ' + port);
});
I'm console logging the following:
Backend returned code undefined, body was undefined
Something bad happened; please try again later.
When I try using Postman, however, I get the response I expect (i.e. Request body: {})
I'm not sure as to why a response is retrieved when done through Postman but not when done through the app.
Any help is appreciated. Thanks!
You need to set body for POST request in auth-service.service.ts:
import { HttpParams } from '#angular/common/http';
login(loginInfo: object) {
const body = new HttpParams()
.set('test', 'test');
return this.http.post<loginInfo>(this.loginUrl, body)
.pipe(
catchError(this.handleError)
);
}
try using express.json its missing
app.use(express.json());
and
app.use(bodyParser.urlencoded({
extended: true
}));
I tried about 10 different options but I cant get my POST request start working instead i have options request that is pending and never completes
server.js
var express = require('express');
var path = require('path');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
app.use(cors());
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, Accept');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
}
};
app.use(allowCrossDomain);
app.options('*', cors());
app.use(require('./routes/order-templates.js'));
app.use(require('./routes/statuses.js'));
app.use(require('./routes/fields.js'));
app.use(require('./routes/users.js'));
app.use(require('./routes/groups.js'));
app.use(require('./routes/upload.js'));
app.use(require('./routes/feedback.js'));
app.use(require('./routes/order.js'));
app.use(express.static('public'));
var mongoDB = 'mongodb://localhost/ior';
mongoose.connect(mongoDB, {
useMongoClient: true
});
app.get('*', function (request, response) {
response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})
app.listen(3000, function () {
console.log('Fired at ' + Date());
});
users.js
var express = require('express');
var router = express.Router();
var User = require('../model/user.js');
var bodyParser = require('body-parser');
var app = express();
var cors = require('cors')
var corsOptions = {
origin: 'http://188.225.82.166:3000/',
optionsSuccessStatus: 200
}
app.use(cors())
app.use(bodyParser.json());
app.options('/users/auth/', cors(corsOptions))
app.post('/users/auth/', cors(), function (req, res, next) {
User.findOne({"mail": req.body.mail, "password": req.body.password}, function (err, user) {
if (err) throw err;
if (user == undefined) {
res.send({"result": "error" })
res.sendStatus(200)
} else {
res.send({"result": "ok", "_id": user._id, "type": user.type })
}
});
})
module.exports = app
If I do
app.use(cors());
app.use(function(req, res, next) {
console.log('After CORS ' + req.method + ' ' + req.url);
next();
});
in server.js I get
After CORS GET /
After CORS GET /bundle.js
After CORS GET /bootstrap.css.map
After CORS GET /favicon.ico
And nothing prints in console after post requests is triggered.
Also worth mentioning the fact, that the problem exists only when I deploy to server with ubuntu. Locally on mac os machine everything is fine
You should use cors before bodyParser and allow it for PUT/DELETE also.
// Add cors
app.use(cors());
app.options('*', cors()); // enable pre-flight
app.use(bodyParser.json());
It may be helpful for others like me:
In the beginning I thougth it is the server side problem, but then the reason of cors error became my frontend. I was sending requests to localhost:3000/api instead of http://localhost:3000/api
That's it
For others like me scratching head for 2hrs trying to fix the POST cors issue, please also double check the options of your POST request.
For me it was a small typo of header: {...} instead of header(s): {...} in the POST options, the express server configured using cors allowing all origins responded with "Access-Control-Allow-Origin" restricted error.
Try this. In you user.js file use router.post instead of app.post.
router.post('/users/auth/', cors(), function (req, res, next) {
User.findOne({"mail": req.body.mail, "password": req.body.password}, function (err, user) {
if (err) throw err;
if (user == undefined) {
res.send({"result": "error" })
res.sendStatus(200)
} else {
res.send({"result": "ok", "_id": user._id, "type": user.type })
}
});
})
Then export router module
module.exports = router;
Also i would suggest to use bodyparser in server.js file. So you don't need to use it in every file.
After applying "cors" middleware. You should append "http://" before "localhost:". in URL
axios.get("http://localhost:8080/api/getData")
.then(function (response) {
this.items= response.data;
}).catch(function (error) {
console.log(error)
});
Get rid of the trailing slash in origin.
I am building a simple api in node and express with postgre as Db following a tutorial.I am still learning and new to this tech.I followed everything as said and gave full permission to postgre thinking about issue with my db.But when i check it with postman i am getting this error Invalid Status Code : 0
my server.js
var express = require('express');
var logger = require('morgan');
var bodyParser = require('body-parser');
var api = require('./api/index');
var app = express();
///////////////////////
// Server Middleware
///////////////////////
app.use(logger(app.get("env") === "production" ? "combined" : "dev"));
// parse application/json
app.use(bodyParser.json());
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// CORS
// This allows client applications from other domains use the API Server
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
//////////////////
// API Queries
//////////////////
app.use('/', api);
//////////////////
// Server Setup
//////////////////
app.set("env", process.env.NODE_ENV || "development");
app.set("host", process.env.HOST || "0.0.0.0");
app.set("port", process.env.PORT || 8080);
app.listen(app.get("port"), function () {
console.log('\n' + '**********************************');
console.log('REST API listening on port ' + app.get("port"));
console.log('**********************************' + '\n');
});
////////////////////
// Error Handlers
////////////////////
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status( err.code || 500 )
.json({
status: 'error',
message: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500)
.json({
status: 'error',
message: err.message
});
});
module.exports = app;
queries.js
var promise = require('bluebird');
var options ={
promiseLib : promise
};
var pgp = require('pg-promise')(options);
var connectionString = 'postgres://localhost:5432/star';
console.log(connectionString);
var db = pgp(connectionString);
function getAllStarships(req, res, next) {
db.any('SELECT * FROM starships')
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved all starships'
});
})
.catch(function (err) {
return next(err);
});
}
module.exports ={getAllStarships: getAllStarships,};
index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.status(200)
.json({
status: 'success',
message: 'Live long and prosper!'
});
});
var db = require('./queries');
router.get('/api/starships', db.getAllStarships);
module.exports = router;
Querying Db is working fine from the pgadmin editor and returning the table.
Sample DB
DROP DATABASE IF EXISTS startrek;
CREATE DATABASE startrek;
\c startrek;
CREATE TABLE starships (
ID SERIAL PRIMARY KEY,
name VARCHAR,
registry VARCHAR,
affiliation VARCHAR,
launched INTEGER,
class VARCHAR,
captain VARCHAR
);
INSERT INTO starships (name, registry, affiliation, launched, class, captain)
VALUES ('USS Enterprise', 'NCC-1701', 'United Federation of Planets Starfleet', 2258, 'Constitution', 'James T. Kirk');
Any Help Appreciated.
Thanks.
Got this..Problem was with Authentication.Modified my query.js with
var db = pgp({
host: 'localhost',
port: 5432,
database: 'star',
user: 'postgres',
password: 'pes'
});
And it worked.
In POST requests through Postman in a NodeJS API I receive empty bodies... (I receive exactly this: {}), however from automated tests it works perfectly. Actually from Postman that happends when I send it as "form" or as "raw" with "text", but if I send it as a "JSON" in raw it simply freezes in "loading..."
When I search I read about adding these 2 lines related to body parse it made it work for the tests but not for Postman:
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
The entire code is here: https://github.com/nemenosfe/TakeMe-Api
But the 3 key files are the following (simplified):
app.js:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const cors = require('cors');
const user = require('./routes/users');
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use('/users', user);
app.use(cors());
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
});
app.listen(8888, function() {
console.log("Node server running on http://localhost:8888");
});
module.exports = app;
routes/users:
"use strict"
const express = require('express'),
router = express.Router(),
/* ... many require and other code probably not relevant for the problem ... */
router
.post('/', function(req, res, next) {
console.log(`conditions: ${(!req.body)} ${(!req.body.uid)} ${(!req.body.provider)} ${JSON.stringify(req.body)}`);
// This console.log appears as follows in the console once I make the request by Postman: false true true {}
// But it receives what it shoulds with automated tests
if (!req.body || !req.body.uid || !req.body.provider) { utilsErrors.handleNoParams(res); }
else {
/* ... There is a lot of code here but it's not relevant for the problem because it doesn't even reaches this point. */
}
})
module.exports = router
tests/users:
"use strict"
let request = require('supertest-as-promised');
const api = require('../app');
/* ... Another require not relevant for the problem ... */
request = request(api);
describe('Users route', function() {
describe.only('POST /users', function() {
it("should create a new user when it doesn't exist", function(done) {
const params = {
'appkey': helperCommon.appkey,
'uid': 1,
'provider': 'providerTest',
'name': 'fakeName'
};
request
.post('/users')
.set('Accept', 'application/json')
.send(params)
.expect(201)
.expect('Content-Type', /application\/json/)
.then((res) => {
expect(res.body).to.have.property('user');
const userResponse = res.body.user;
expect(userResponse).to.have.property('uid', params.uid);
expect(userResponse).to.have.property('provider', params.provider);
expect(userResponse).to.have.property('name', params.name);
/* ... other expectectations that are not important for the problem ... */
done();
}, done)
});
});
Thanks!
Make sure your are sending the POST request In postman as a x-www-form-urlenconded
When I test my Error #404 page, I get the default "Not Found."
require('html');
var WebSocketServer = require('ws').Server
, http = require('http')
, fs = require('fs')
, express = require('express')
, app = express();
app.use(express.static(__dirname + '/public'));
var server = http.createServer(app);
server.listen(42069);
var MainServer = new WebSocketServer({server: server});
// Handle 404
app.use(function(req, res) {
res.status(404).render('/error/404.html',{title: "Error #404"});
});
However, it does work with
app.use(function(req, res) {
res.status(404).render('/error/404.html',{title: "Error #404"});
});
but I don't want to be redirected to my 404 page, I want it to be rendered on any non-existent address.
Any thoughts on how to get this to work?
Thanks!
You could try something like this after your route handling
app.get('/404', function(req, res, next){
// trigger a 404 since no other middleware
// will match /404 after this one, and we're not
// responding here
next();
});
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
});
Place this after all your middleware
app.use(function(req,res){
res.status(404);
res.render('404page',{
});
});