I'm trying to POST an Item to my db in my json server. I'm sending the POST request from Angular. When I do so, I get the following error:
Note: when I do the get in a the GET end point it works fine. I'm very new on the server side
POST ERROR 404:
Http failure response for http://localhost:3000/addMember: 404 Not Found
SERVER.JS
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
....
app.use(cors());
app.use(express.static('assets'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.disable('x-powered-by');
app.use(xssFilter());
app.use(nosniff());
app.set('etag', false);
app.use(
helmet({
noCache: true
})
);
app.use(
hsts({
maxAge: 15552000 // 180 days in seconds
})
);
app.use(
express.static(path.join(__dirname, 'dist/softrams-racing'), {
etag: false
})
);
app.get('/api/members', (req, res) => {
request('http://localhost:3000/members', (err, response, body) => {
if (response.statusCode <= 500) {
res.send(body);
}
});
});
// TODO: Dropdown!
app.get('/api/teams', (req, res) => {
request('http://localhost:3000/teams', (err, response, body) => {
if (response.statusCode <= 500) {
res.send(body);
}
});
});
// Submit Form!
app.post('/api/members', function(request, response) {
request.post('http://localhost:3000/members', (err, response, body) => {
if (response.statusCode <= 500) {
req.send(body);
}
});
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/softrams-racing/index.html'));
});
app.listen('8000', () => {
console.log('Vrrrum Vrrrum! Server starting!');
});
ANGULAR
addMember(memberForm: Member) {
this.http.post(`${this.api}/addMember`, memberForm).subscribe(
data => {
console.log('POST Request is successful ', data);
},
error => {
console.log('Error', error);
}
);
}
UPDATE:
in my console i see this POST /addMember 404 12.105 ms - 2 and If i go to http://localhost:3000/addMember directly in the browser I see an empty object {} and if I go here http://localhost:3000/ I see this message To access and modify resources, you can use any HTTP method GET POST PUT PATCH DELETE OPTIONS
The issue here is that you are making your POST request to a route which your JSON server does not handle. Change the URL to http://localhost:3000/members, and it should work fine!
(The routes on a json-server correspond to the elements in your db.json file.)
Try to change your code like this:
addMember(memberForm: Member) {
this.http.post(`${this.api}/api/addMember`, memberForm).subscribe(
data => {
console.log('POST Request is successful ', data);
},
error => {
console.log('Error', error);
}
);
}
From the error it is shown that your service is expecting the request at http://localhost:3000/api/addMember but your console.log shows that you are sending post request at http://locatlhost:3000/addMember
Related
I am using node.js package prom-client to try to push different custom metrics to the Prometheus Pushgateway server.
The code is working and now I am writing the test code for the functionality. I wonder whether there is a way to mock the Prometheus Pushgateway server?
I had tried to use a normal express API server (like the following)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
let data = null;
// ROUTES FOR OUR API
// =============================================================================
const router = express.Router();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
router.get('/', (req, res) => {
console.log("pushgateway server: get to '/' received");
res.json(data);
});
router.post('/', (req, res) => {
console.log("pushgateway server: post to '/' received");
console.log(req.body);
data = req.body;
res.send('POST request to the homepage');
})
app.use(router);
// API JSON BASED ERRORS
// =============================================================================
app.use((err, req, res, next) => {
if (req.xhr) {
console.error(err);
res.status(500).send({ err: 'Something failed!' });
} else {
next(err);
}
});
app.use((err, req, res, next) => { // eslint-disable-line
console.error(err);
res.status(500).send({ err: err.message });
});
// START THE SERVER
// =============================================================================
const port = 9876;
const server = app.listen(port, '0.0.0.0');
console.log(`Prometheus Pushgateway Mock Server is listening on port ${port}`);
// SHUTDOWN HANDLING
// =============================================================================
// Nodemon Signal Handling
process.once('SIGUSR2', () => {
console.log('Received kill signal, attempting gracefully close');
server.close(() => {
console.log('Closed out remaining connections');
process.kill(process.pid, 'SIGUSR2');
});
setTimeout(() => {
console.error('Timeout, forcefully shutting down');
process.kill(process.pid, 'SIGUSR2');
}, 3000);
});
module.exports = server;
but it did not work -- when I call gateway.pushAdd() on my test code, the server did not receive any post message.
Can anyone give me some hints on how to do this (mock the prometheus pushgateway server)?
There are different options out there to mock a third party http server. Here are 3:
Nock
Dyson
Stubborn
Disclaimer: I am the maintainer behind stubborn.
Nock and Dyson are the most popular ones, they have pro and cons. Stubborn is more recent and tries to cover some limitations of Nock and Dyson.
You can checkout this reddit post first comment I wrote for a comparison between the 3 solutions.
So I have solved the problem by creating a simple http server.
The following is the code of the server:
const http = require('http');
const body = [];
let text = null;
let path = null;
function createServer(port) {
return http.createServer()
.on('request', (req, res) => {
if (req.method === 'POST' || req.method === 'PUT') {
path = req.url;
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
text = Buffer.concat(body).toString();
res.end(`${req.method} success`);
}).on('error', (err) => {
console.error(err);
});
} else if (req.method === 'GET') {
res.end(JSON.stringify({ path, text }));
} else if (req.method === 'DELETE') {
path = null;
text = null;
res.end('DELETE success');
}
}).on('error', (err) => {
console.log(`Server error: ${err}`);
})
.listen(port, '0.0.0.0');
}
module.exports = (createServer);
The server accepts POST/PUT/DELETE/GET requests, to handle the pushAdd()/push()/delete() functions of the gateway to handle the metric data, as well as checking the push data on the mocked pushgateway.
Also, the request.url and the text data pushed to the server are saved and passed to the test program for verification.
The following is one of the test cases (using Mocha+Chai):
describe('Check adding custom push count metric', () => {
it('Check connection: should return - network status: 200, result contains custom count metric string', async () => {
metricInstance = promMetric.createCustomPushMetric({
name: 'test_counter',
help: 'Used to test the pushgateway for custom counter metrics',
type: 'counter',
jobName: 'custom-metric-pushgateway-counter',
groupings: { key: 'test', type: 'customMetric' },
});
await promMetric.addPushMetric(metricInstance, 0.879);
await sleep(500);
const result = await chai.request(mockPgwServer).get('/');
expect(result).to.have.status(200);
const json = JSON.parse(result.text);
expect(json.path).to.equal('/metrics/job/custom-metric-pushgateway-counter/key/test/type/customMetric');
expect(json.text).to.match(/# HELP Push_gateway_test_test_counter Used to test the pushgateway for custom counter metrics/);
expect(json.text).to.match(/# TYPE Push_gateway_test_test_counter counter/);
expect(json.text).to.match(/Push_gateway_test_test_counter 0.879/);
});
});
The "path" and "text" stored in the server when the metric is posted from the client are sent back to the client when queried and verified.
In the express app below:
Executing a POST for /push with invalid json data will cause an HTTP 400 error to be sent back to the client
Executing a POST with valid json data, but for an unknown route will cause an HTTP 404 error to be sent back to the client
Executing a POST with invalid json data for an unknown route, will cause an HTTP 400 error to be sent back to the client
What I'd like to achieve, is that in the third scenario, also the 404 would be sent. In other words, in case the route is unknown, I want that to be catched by app.post('*',(req, res, next)), which will throw the 404, and not by the generic middleware error handler, which throws a 400 json SyntaxError
Any way to achieve this?
const express = require('express');
const { handleError, ErrorHandler } = require('./helpers/error');
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.get('/', function(req, res){
res.send('Hello World');
});
app.post('/', function(req, res){
console.log(req.body.data);
res.sendStatus(200);
});
app.post('/push', function(req, res){
console.log('push API');
res.sendStatus(200);
});
app.post('*',(req, res, next) => {
console.log('Unknown route');
throw new ErrorHandler(404, 'API endpoint does not exist.');
});
app.use((err, req, res, next) => {
console.log('Middleware error handling');
handleError(err, res);
});
app.listen(3000, function(){
console.log('Server started on port 3000')
});
error.js content:
class ErrorHandler extends Error {
constructor(statusCode, message) {
super();
this.statusCode = statusCode;
this.message = message;
}
}
const handleError = (err, res) => {
const { statusCode, message } = err;
res.status(statusCode).json({
status: "error",
statusCode,
message
});
};
module.exports = {
ErrorHandler,
handleError
}
By sending a request to a non-existing route, none of your handlers are matched. Thus, your error handling middleware
app.use((err, req, res, next) => {
console.log('Middleware error handling');
handleError(err, res);
});
is executed directly. What you can do is to try to detect a Syntax/parsing error in your handleError function. Something like:
const handleError = (err, res) => {
let {statusCode, message} = err;
if (err.status === 400 && err.message.includes("Unexpected token")) {
statusCode = 404;
}
res.status(statusCode).json({
status: "error",
statusCode,
message
});
};
EDIT:
The issue can be fixed by only using the json-parser middleware for the routes you want to parse json and removing it as a general middleware for all requests:
...
//app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.post('/', express.json(), function (req, res) {
console.log(req.body.data);
res.sendStatus(200);
});
app.post('/push', express.json(), function (req, res) {
console.log('push API');
res.sendStatus(200);
});
So i am using ionic framwork to make my app and using nodeJS as my backend but i am still a noob in this and i can't seem to figure it out still after 4 days so hopefully someone could answer this problem to me and why would be appreciated.
So for my ionic client side i do this to make a http.post request
progress() {
var headers = new HttpHeaders();
headers.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json');
let options = {headers: headers};
let postData = {
username: this.username,
email: this.email,
password1: this.password1,
password2: this.password2
};
this.http.post('localhost:4000/api/users', postData, options,).subscribe(
data => {
console.log(data);
},
error => {
console.log(error);
});
}
and this is what i am doing to get the data from the server but that's not working
// Packages
let express = require('express');
var request = require('request');
var bodyParser = require('body-parser');
var cors = require('cors');
const app = express();
app.use(cors({origin: 'http://localhost:8100'}));
const port = 4000;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Whenever you enter localhost:4000/ //
app.get('/', function (req, res) {
res.send(('Server runs'));
});
app.listen(port, () => console.log(`app listening on port ${port}!`));
app.get('/api/users', (req, res) => {
res.send('api/users page');
request.get({
uri: 'http://localhost:8100/create-account'
}, function (err, res, body) {
console.log('error:', err); // Print the error if one occurred and handle it
console.log('statusCode:', res && res.statusCode); // Print the response status code if a response was received
res.send(body);
});
});
i also tried 'http://localhost:8100' & 'localhost:8100'
so someone help me
You need to add a handler for your POST request. To do this use app.post, and it looks like this
app.post('/api/users', (req, res) => {
// You can find your data here
const data = req.body;
console.log(data);
// Send back a response
res.sendStatus(200);
});
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'm implementing a simple app that simply sends some GET request to a nodeJS-express endpoint. This endpoint is returning just this:
router.get('/', (request, response) => {
response.status(500).send("Error message");
}
My app is using request to send the request like this:
request.get(BASE_URL)
.on("error", err => {
console.log(`ERROR: ${err}`)
})
.on("response", res => {
console.log(`RESPONSE: ${res.statusCode} - ${res.body}`)
});
But body is always undefined. I have tried to use:
.on("response", res => {
res.on("data", () => {
console.log(`RESPONSE: ${res.statusCode} - ${data}`)
}
});
But the data is some byte array. I just want the string message, where it is and how can I get it without using the callback syntax?
If You are using express you will need to inject the body-parser middleware for parsing the request body.
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/login', (req, res) => {
console.log(req.body); //data
})