I'm building a server-side rendered website with Node. I want to display a green alert box upon successfully updating data in updateSettings.js. Even though the user data (name and email) is updated on Compass correctly, I get a red alert box (error) with undefined as the message. In the browser console, I get a 'bad request' error from bundle.js.
Also, no code seems to run after the Axios PATCH request code
updateSettings.js
/* eslint-disable */
import axios from 'axios';
import { showAlert } from './alerts';
export const updateData = async (name, email) => {
try {
const res = await axios({
method: 'PATCH',
url: 'http://127.0.0.1:3000/api/v1/users/updateMe',
data: {
name,
email,
},
});
if (res.data.status === 'success') {
showAlert('success', 'Data updated successfully!');
}
} catch (err) {
showAlert('error', err.response.data.message);
}
};
Alerts.js
/* eslint-disable */
export const hideAlert = () => {
const el = document.querySelector('.alert');
if (el) el.parentElement.removeChild(el);
};
// type is 'success' or 'error'
export const showAlert = (type, msg) => {
hideAlert();
const markup = `<div class="alert alert--${type}">${msg}</div>`;
document.querySelector('body').insertAdjacentHTML('afterbegin', markup);
window.setTimeout(hideAlert, 5000);
};
Index.js
`
/* eslint-disable */
import '#babel/polyfill';
import { login, logout } from './login';
import { displayMap } from './leaflet';
import { updateData } from './updateSettings';
// DOM ELEMENTS
const leaflet = document.getElementById('map');
const loginForm = document.querySelector('.form--login');
const logOutBtn = document.querySelector('.nav__el--logout');
const updateDataForm = document.querySelector('.form-user-data');
// DELEGATION
if (leaflet) {
const locations = JSON.parse(leaflet.dataset.locations);
displayMap(locations);
}
if (loginForm)
loginForm.addEventListener('submit', (e) => {
e.preventDefault();
const password = document.getElementById('password').value;
const email = document.getElementById('email').value;
login(email, password);
});
if (logOutBtn) logOutBtn.addEventListener('click', logout);
if (updateDataForm)
updateDataForm.addEventListener('submit', (e) => {
e.preventDefault();
const name = document.getElementById('name').value;
const email = document.getElementById('email').value;
updateData(name, email);
});
`
Running the node debugger indicates that process.env.NODE_ENV is undefined but I'm using dotenv for this so it should be working just fine. In any case, the login functionality which is quite similar and uses axios runs just fine.
App.js
const path = require('path');
const express = require('express');
const morgan = require('morgan');
const rateLimit = require('express-rate-limit');
const helmet = require('helmet');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss-clean');
const hpp = require('hpp');
const cookieParser = require('cookie-parser');
// eslint-disable-next-line node/no-deprecated-api
const exp = require('constants');
const AppError = require('./utilities/appError');
const globalErrorHandler = require('./controllers/errrorController');
const tourRouter = require('./routes/tourRoutes');
const userRouter = require('./routes/userRoutes');
const reviewRouter = require('./routes/reviewRoutes');
const viewRouter = require('./routes/viewRoutes');
const app = express(); //express is a function which upon calling will add a bunch of methods to the app variable
app.set('view engine', 'pug');
app.set('views', path.join(__dirname, 'views'));
// 1.GLOBAL MIDDLEWARES
// Serving static files
// app.use(express.static(`${__dirname}/public`));
app.use(express.static(path.join(__dirname, 'public')));
// Set Security HTTP headers
app.use(helmet());
// Development logging
console.log(process.env.NODE_ENV);
if (process.env.NODE_ENV === 'development') {
// the readinng of the process only needs to happen once, and the process is the same no matter which file we're in
app.use(morgan('dev'));
}
// Limit requests from same API
const limiter = rateLimit({
max: 100,
windowMs: 60 * 60 * 1000,
message: 'Too many requests from this IP, please try again in an hour',
});
app.use('/api', limiter);
// Body parser: reading data from body into req.body
app.use(express.json({ limit: '10kb' })); //'express.json' here is middleware
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
app.use(cookieParser());
// Data sanitization against NoSQL query injection
app.use(mongoSanitize());
// Data sanitization agains XSS
app.use(xss());
// Prevent parameter pollution
app.use(
hpp({
whitelist: [
'duration',
'ratingsAverage',
'ratingsQuantity',
'maxGroupSize',
'difficulty',
'price',
],
})
);
// Test middleware
app.use((req, res, next) => {
// we have access to the requestTime property; assuming we want to display the time of the request
req.requestTime = new Date().toISOString();
next();
console.log(req.cookies);
});
// 3. ROUTES: this is where we mount our routers
// these 3 routers are actually middlewares that we mount upon the paths
app.use('/', viewRouter); //mounted right on the root URL
app.use('/api/v1/tours', tourRouter); //we've created a sub-app with this
app.use('/api/v1/users', userRouter);
app.use('/api/v1/reviews', reviewRouter);
// this router is essentially a sub-app for each resource
// the request goes into middleware and when it hits the above line of code, it will match the url, and thus the tourRouter middleware function will run
app.all('*', (req, res, next) => {
next(new AppError(`Cant find ${req.originalUrl} on this server!`, 404));
});
app.use(globalErrorHandler);
module.exports = app;
/updateMe
exports.updateMe = catchAsync(async (req, res, next) => {
// 1) Create error if user POSTs password data
if (req.body.password || req.body.passwordConfirm) {
return next(
new AppError(
'This route is not for password updates. Please use /updateMyPassword',
400
)
);
}
// 2) Filter out unwanted field names that are not allowed to be updated
const filteredBody = filterObj(req.body, 'name', 'email');
// 3) Update user document
const updatedUser = await User.findByIdAndUpdate(req.user.id, filteredBody, {
new: true,
runValidators: true,
});
res.status(400).json({
status: 'success',
data: {
user: updatedUser,
},
});
});
package.json
"scripts": {
"start": "nodemon server.js",
"start:prod": "NODE_ENV=production nodemon server.js",
"debugger": "ndb server.js",
"watch:js": "parcel watch ./public/js/index.js --out-dir ./public/js --out-file bundle.js",
"build:js": "parcel watch ./public/js/index.js --out-dir ./public/js --out-file bundle.js"
},
"author": "Dave Odipo",
"license": "ISC",
"dependencies": {
"#babel/polyfill": "^7.12.1",
"axios": "^1.1.3",
"b": "^2.0.1",
"babel": "file:../../../../../../../../polyfill",
"bcryptjs": "^2.4.3",
"cookie-parser": "^1.4.6",
"dotenv": "^16.0.2",
"express": "^4.18.1",
"express-mongo-sanitize": "^2.2.0",
"express-rate-limit": "^6.6.0",
"helmet": "3.16",
"hpp": "^0.2.3",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.13.15",
"morgan": "^1.10.0",
"nodemailer": "^6.8.0",
"pug": "^3.0.2",
"slugify": "^1.6.5",
"validator": "^13.7.0",
"xss-clean": "^0.1.1"
},
"optionalDependencies": {
"win-node-env": "^0.6.1"
},
"devDependencies": {
"eslint": "^8.23.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.6.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.8",
"parcel-bundler": "^1.12.3",
"prettier": "^2.7.1"
},
"engines": {
"node": ">=8.0.0"
}
}
Please help
Try changing res.status(400).json({ to res.status(200).json({
Related
I'm using React for testing connection to the RDS database from my local client and local server. For first few tries, my demo application works perfectly but after few tries, it seems like my code fails to make connection to the database nor wants to make connection to each other. Can anybody tell me what I could've missed in my codes?
ps. I know my code isn't clean. There may exist some unnecessary codes but please ignore them.
I have been constantly testing and I figured out the not responding cycle is getting shorter which I think the problem is related to the cache data (if that makes sense - I'm completely new to react!).
Client
import React, {useState,useEffect} from 'react';
import './App.css';
import Axios from 'axios';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
function App() {
const [title, setTitle] = useState('');
const [sAuthor, setAuthor] = useState('');
const [dateTime, setDateTime] = useState('');
const [desc, setDesc] = useState([]);
const submitButton = () => {
console.log("submit")
Axios.post('http://localhost:3001/post', {
time: dateTime,
author: sAuthor,
})
.then((response)=>{
console.log("responsed");
});
Axios.get('http://localhost:3001/get').then((response)=>
{
console.log("got");
setDesc([]);
setDesc(response.data);
enlist();
});
}
const enlist = () => {
console.log("enlist");
console.log(desc)
desc.map((val)=>{
return <h2>"STOCK NAME:"</h2>
})
}
useEffect(()=>
{
Axios.get('http://localhost:3001/get').then((response)=>
{});
},[])
useEffect(()=>
{
console.log(desc);
})
return (
<div className="App">
<h1>CRUD APPLICATION</h1>
<div className="form">
<input type = "text" name = "AI_TITLE" onChange={(e)=>{
setTitle(e.target.value)}}/>
<h3>TITLE</h3>
<input type = "text" name = "AI_AUTHOR" onChange = {(e)=>{
setAuthor(e.target.value)}}/>
<h3>STOCK NAME</h3>
<DatePicker format={"yyyy-MM-DD"} selected={dateTime} onChange={(date) => setDateTime(date)} />
<button className = "button" onClick={submitButton} >submit</button>
{desc.map((val)=>{
return (
<h1>STOCK: {val.AI_STOCKCD}</h1>
)
})}
</div>
</div>
);
}
export default App;
Server
const express = require('express');//create express server
const app = express();
const bodyParser = require('body-parser');
const mysql = require('mysql');
const cors = require('cors');
app.use(cors());
const db = mysql.createPool({
host: 'somehost',
user: 'someuser',
password: 'somepassword',
port: 0000,
database: 'smms2'
})
app.use(express.json())
app.use(express.urlencoded({extended: true}));
var author = "";
var time = "";
// recieving request from client
app.post("/post",(req, res)=>{
author = req.body.author;
time = req.body.time;
console.log(1)
console.log(author)
console.log(time)
})
// sending request to db
app.get("/get",(req, rows, fields)=>{
const sqlSelect = "SELECT * FROM ai_board WHERE UPDATE_DT > '"+time+"' AND AI_AUTHOR = '" + author+ "';";
db.query(sqlSelect, (err, result) =>{
rows.send(result);
});
})
app.listen(3001, ()=>{
console.log("running on port 3001");
})
package.json
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"devStart": "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"mariadb": "^2.5.3",
"mysql": "^2.18.1",
"nodemon": "^2.0.7"
}
}
I am trying to use Request-Promise-Native or Axios but getting error during execution. I am sharing my code. I am using dialogflow inline editior. I also try with post api but not working. I guess somewhere i am doing minor mistake. Please explain also it will help me to learn.
'use strict';
const axios = require('axios');
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
const request = require('request-promise-native');
// this is GET api using axios
function Login(agent) {
const email = agent.parameters.email;
const password = agent.parameters.password;
const baseurl = 'http://demoapi:3000/login/buyerlogin';
var data = {"email" : email,"password": password};
return axios.get(baseurl, { params:
data})
.then(result => {
console.log(result.data);
console.log(`statusCode: ${result.statusCode}`);
agent.add(result.data);
}) }
// This Get API using Request promise native
function Login(agent) {
const email = agent.parameters.email;
const password = agent.parameters.password;
const baseurl = 'http://demoapi:3000/login/buyerlogin';
var data = {"email" : email,"password": password};
var sdata = JSON.stringify(data);
const options = {
method: 'GET',
uri: baseurl,
body: JSON.parse(sdata),
json: true
};
return request(options)
.then(result => {
console.log(result.data);
console.log(`statusCode: ${result.statusCode}`);
agent.add(result.data);
});
}
Package.json file
{
"name": "dialogflowFirebaseFulfillment",
"description": "This is the default fulfillment for a Dialogflow agents using Cloud Functions for Firebase",
"version": "0.0.1",
"private": true,
"license": "Apache Version 2.0",
"author": "Google Inc.",
"engines": {
"node": "10"
},
"scripts": {
"start": "firebase serve --only functions:dialogflowFirebaseFulfillment",
"deploy": "firebase deploy --only functions:dialogflowFirebaseFulfillment"
},
"dependencies": {
"actions-on-google": "^2.2.0",
"firebase-admin": "^5.13.1",
"firebase-functions": "^2.0.2",
"dialogflow": "^1.2.0",
"dialogflow-fulfillment": "^0.6.1",
"request": "^2.88.2",
"request-promise-native": "^1.0.9",
"axios": "^0.21.1"
}
}
Please help me out. Is anything required please let me.
Thank You
I'm trying to connect to the socket server in react-native,
I'm using ngrok and it's the log when the mobile app running
HTTP Requests
-------------
POST /io/webrtc/ 400 Bad Request
GET /io/webrtc/ 200 OK
{
"code": 2,
"message": "Bad handshake method"
}
although the Web app, it works very well!
Code snippet
Server.js
const express = require('express');
let io = require('socket.io')({
path: '/io/webrtc',
});
const app = express();
const port = 8080;
//https://expressjs.com/en/guide/writing-middleware.html
app.use(express.static(__dirname + '/build'));
app.get('/', (req, res, next) => {
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
res.sendFile(__dirname + '/build/index.html');
});
const server = app.listen(port, () =>
console.log(`Example app listening on port ${port}!`)
);
io.listen(server);
const peers = io.of('/webrtcPeer');
let connectedPeers = new Map();
peers.on('connection', (socket) => {
console.log(socket.id);
socket.emit('connection-success', { success: socket.id });
connectedPeers.set(socket.id, socket);
socket.on('disconnect', () => {
console.log('disconnected!');
connectedPeers.delete(socket.id);
});
socket.on('offerOrAnswer', (data) => {
console.log('data-offer||Answer', data);
// send to other peers if any
for (const [socketID, socket] of connectedPeers.entries()) {
// don't send to self
if (socketID !== data.socketID) {
console.log('not-offerOrAnswer', socketID, data.payload.type);
socket.emit('offerOrAnswer', data.payload);
}
}
});
socket.on('candidate', (data) => {
// send candidate to the other peers if any
for (const [socketID, socket] of connectedPeers.entries()) {
// don't send to self
if (socketID !== data.socketID) {
console.log('dont_send_to_self-candidate', socketID, data.payload.type);
socket.emit('candidate', data.payload);
}
}
});
});
mobile App (React Native)
App.js
import React, {useRef, useState, useEffect} from 'react';
import {View, Dimensions, Text} from 'react-native';
import io from 'socket.io-client';
const {width, height} = Dimensions.get('window');
const App = () => {
...
const socket = useRef();
const serverIP = 'https://22997aecc45f.ngrok.io';
useEffect(() => {
socket.current = io.connect(`${serverIP}/webrtcPeer`, {
path: '/io/webrtc',
query: {},
});
socket.current.on('connection-success', (success) => {
console.log('success', success); // not logged :)
});
}, []);
return (
<View>
<Text>App</Text>
</View>
);
};
export default App;
package.json // React Native
"react": "16.13.1",
"react-native": "0.63.3",
"react-native-webrtc": "^1.84.1",
"socket.io-client": "2.3.0"
package.json // web App Reactjs
"dependencies": {
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.0",
"socket.io-client": "^3.0.1",
"web-vitals": "^0.2.4"
},
"devDependencies": {
"express": "^4.17.1",
"socket.io": "^3.0.1"
}
#Edit
The issue solved after downgrade socket server and client to 2.3.0 :)
I want to save data using mongodb query using middleware in node.js. please provide some code with example?
Try this. It works both for insert and update (upsert).
// app.js
const express = require('express');
const bodyParser = require('body-parser');
const MongoClient = require('mongodb').MongoClient;
const mongodb_url = process.env.MONGO_URL || "mongodb://localhost:27017";
const mongodb_dbname = 'test_db';
const port = process.env.PORT || 3006;
const app = express();
app.use(express.json())
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json({ extended: true}));
app.post('/api/post/:identifier', (req, res) => {
const identifier = req.params.identifier;
const content = req.body.payload;
MongoClient.connect(`${mongodb_url}`, { useNewUrlParser: true }, (err, client) => {
if (!err) {
let db = client.db(mongodb_dbname);
db.collection('posts')
.updateOne(
{ identifier: identifier },
{ $set: { content: content } },
{ upsert: true }
)
.then((output) => {
res.status(202).send({ message: "Sent"});
})
.catch((error) => {
res.status(500).send({
error_code: 500,
error_message: `Error while updating data - ${error}`
});
});
client.close();
} else {
res.status(500).send({
error_code: 500,
error_message: 'Error while connecting to database'
});
}
});
});
app.listen(port, () => {
console.log(`API bootstrapped on port ${port}...`);
});
Use the following package.json file:
{
"name": "mongo-upsert",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"mongodb": "^3.6.0"
}
}
When invoked as localhost:3006/api/post/my-post with a request body containing:
{
"payload": "Hello world"
}
This code is going to upsert a MongoDB document like:
{
"_id" : ObjectId("5f3d272cbd52c9c109ea9baa"),
"identifier" : "my-post",
"content" : "Hello world"
}
Prerequisites for the above code to work:
To have a working installation of mongodb
To have a database named test_db
To have a collection named posts
In this example, we are adding a post content, identified by an identifier, which for the sake of simplicity I have added as a path param in the POST definition.
Install dependencies using npm install.
Run the app using npm start.
Good luck.
Look into W3Schools NodeJS MongoDB.
I don't have enough rep to comment so here's an answer.
The goal is to have recored api tests. This test are kind of integration tests, they load the whole app with all its middlewares and intercepts the external http calls and records them.
In Python world exists "WebTest" and "VCRPY" for that.
The app:
'use strict';
const express = require('express');
const request = require('superagent');
var app = express();
app.get('/hammer/version', function(req, res) {
request
.get('http://httpbin.org/get')
.end(function(err, response) {
console.log(response.body);
res.status(200).json({
version: '0.1.0',
url: response.body.url
});
});
});
module.exports = app;
The test:
/* global describe, it */
'use strict';
const request = require('supertest');
const app = require('./app.js');
var path = require('path');
var tape = require('tape');
var tapeNock = require('tape-nock');
// call tapeNock with tape and an options object
var test = tapeNock(tape, {
fixtures: path.join(__dirname, 'fixtures')
});
describe('Version test', function() {
this.timeout(0);
it('test version', function(done) {
test('record_version.json', function(t) {
request(app)
.get('/hammer/version')
.expect(200, {
url: "http://httpbin.org/get",
version: '0.1.0'
})
.end(function(err, res) {
if (err) return done(err);
t.end();
done();
});
});
});
});
The "package.json":
{
"name": "remote_node_test",
"version": "1.0.0",
"description": "",
"main": "app.js",
"dependencies": {
"express": "^4.14.0",
"mocha": "^3.2.0",
"nock": "^9.0.2",
"superagent": "^3.3.1",
"supertest": "^2.0.1",
"tape": "^4.6.3",
"tape-nock": "^1.4.0"
},
"devDependencies": {
"mocha": "^3.2.0"
},
"scripts": {
"test": "mocha"
},
"author": "",
"license": "ISC"
}
The test are run with "mocha":
NOCK_BACK_MODE=record node_modules/mocha/bin/mocha
First run works, second run with "lockdown/record" does not work.
The error:
% NOCK_BACK_MODE=lockdown node_modules/mocha/bin/mocha test.js :(
Version test
TAP version 13
# details.json
1) return current version
0 passing (32ms)
1 failing
1) Version test return current version:
TypeError: Cannot read property 'status' of undefined
at Test._assertStatus (node_modules/supertest/lib/test.js:263:10)
at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
at Test.assert (node_modules/supertest/lib/test.js:171:18)
at Server.assert (node_modules/supertest/lib/test.js:131:12)
at emitCloseNT (net.js:1553:8)
at _combinedTickCallback (internal/process/next_tick.js:71:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
Recorded are all requests, but i need only to record the "external" requests, and prevent "mocking/recording" my internal logic.
If you're using mocha, you may want to look for a similar nock/nockBack helpers that are mocha-specific (https://www.npmjs.com/search?q=mocha+nock)
That being said, you may also run into problems where the HTTP call supertest makes to the app gets picked up by nockBack.
I made a little example that uses only tape to do what you're trying to accomplish:
https://github.com/Flet/tape-nock-with-supertest-example
The afterRecord and before functions defined in setup-tape-nock.js are probably the secret sauce you would need even if using some other nockBack mocha helper.
Hope this helps!
One solution seems "replay" and configuring "passThrough" of requests to my local app.
/* global describe, it */
'use strict';
const request = require('supertest');
const app = require('./app.js');
var path = require('path');
const Replay = require('replay');
Replay.fixtures = __dirname + '/fixtures/replay';
Replay.passThrough('localhost', '127.0.0.1', '0.0.0.0');
describe('Version test', function() {
this.timeout(0);
it('test version', function(done) {
request(app)
.get('/hammer/version')
.expect(200, {
url: "http://httpbin.org/get",
version: '0.1.0'
})
.end(function(err, res) {
if (err) return done(err);
done();
});
});
});