MongoDb cluster connection with React Native App - node.js

I am very new to React Native. As part of my learning i was trying to connect a Mongodb Atlas cluster to my RN App. But I am very confused in developing the code for a post request to the Mongodb cluster. I was following a tutorial to develop a sample taxi booking app. It would be great if someone helps me to understand the code.
So my server code is as follows:
var express = require("express");
var path = require("path");
var bodyParser = require("body-parser");
var index = require("./routes/index");
var bookings = require("./routes/bookings");
var app = express();
var port = 3000;
app.listen(port,function(){
console.log("Server running on port",port);
})
//views
app.set("views", path.join(__dirname,"views"));
app.set("view engine","ejs");
app.engine("html", require("ejs").renderFile);
//Body Parser MW
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}))
//Routes
app.use("/",index);
app.use("/api",bookings);
Then i have a bookings.js file as follows:
var express = require("express");
var router = express.Router();
var MongoClient = require("mongodb").MongoClient ;
var uri = "mongodb+srv://TheCarAdmin:admin0000#thecarcluster-3hqxd.mongodb.net/test?&w=majority";
router.post("/bookings",function(req,res,next){
var bookings =req.body.data;
if(!bookings.username){
res.status(400);
res.json({
error:"Bad data"
});
}
else {
MongoClient.connect(uri)
.then(client=>{
const db = client.db("TheCar");
const coll = db.collection("bookings");
coll.save(bookings,function(err,savedBooking){
if(err){
res.send(err);
}
res.json(savedBooking);
});
})
.catch(err=>console.log(err));
}
});
module.exports = router;
In my App code i have a function that handles logging the booking request to the MongoDB collection as follows:
import update from "react-addons-update";
import constants from "./actionConstants";
import Geolocation from "react-native-geolocation-service";
import {Dimensions} from "react-native";
import RNGooglePlaces from "react-native-google-places";
import request from "../../../util/request";
import calculateFare from "../../../util/fareCalaculator";
export function bookCar(){
return(dispatch,store)=>{
const payload = {
data:{
username:"eman",
pickUp:{
address :store().home.selectedAddress.selectedPickUp.address,
name : store().home.selectedAddress.selectedPickUp.name,
latitude: store().home.selectedAddress.selectedPickUp.location.latitude,
longitude: store().home.selectedAddress.selectedPickUp.location.longitude
},
dropOff:{
address :store().home.selectedAddress.selectedDropOff.address,
name : store().home.selectedAddress.selectedDropOff.name,
latitude: store().home.selectedAddress.selectedDropOff.location.latitude,
longitude: store().home.selectedAddress.selectedDropOff.location.longitude
},
fare: store().home.fare,
status:"pending"
}
}
request.post("http://172.20.10.2:3000/api")
.send(payload)
.finish((err,res)=>{
dispatch({
type : BOOK_CAR,
payload : res.body
});
console.log(err.message);
console.log(res.status);
});
};
}
So as shown above the Request is imported from the following file:
const request = require("superagent");
const defaultAjaxTimeout = 30000;
//const cookie = require("cookie");
request.Request.prototype.finish = function (callback) {
// this replaces superagent's .end() function to include our custom error handling (see above)
this.end((err,res)=>{
callback(err,res);
});
};
var requestWrapper = function(method) {
// this is here so that we can append the .timeout call to all of our ajax requests with the default value.
return function(url) {
return request[method](url)
.type("form")
.timeout(defaultAjaxTimeout);
};
};
export default {
get: requestWrapper("get"),
put: requestWrapper("put"),
post: requestWrapper("post"),
del: requestWrapper("del"),
};
When i was debugging I realised that its not getting redirected to the booking.js code to process the POST request and hence throwing error. Could anyone help me to understand how this gets redirected to bookings.js or correct me if the written code is wrong.
Thanks in advance!!!!!

Related

Cannot post request to nodejs route on ECS but can locally (404 error)

I’ve been having an issue with deploying my nodejs App on AWS ECS Fargate. Running the app locally on my device with nodemon or building the app and running the build file is successful and I can ping my routes using postman. The issue happens when I deploy this same exact code on AWS; using postman, to do a POST request, I get a 404 error. Please note, I'm running a Node:14 container.
For reference, my nodejs code is structured in a way where there’s a main route.js file containing all routes, then there are specific route files, for example listingRoute.js, contains all the sub-routes then there are controllers (.js files) containing all the logic where I export the function and tie it with the route in the listingRoute.js example.
Here's what my main Route.js file looks like:
const express = require('express');
const error = require('../Middleware/error');
const listingRoute = require('../Routes/listingRoute');
module.exports = function (app) {
//Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false , limit : '20mb' }));
app.use('/listing', listingRoute);
//The final middleware to be called in case of an unhandled error.
app.use(error);
process.on('uncaughtException', function(err) {
// Handle the error safely
console.log(err)
})
};
My listingRoute file
const express = require("express");
const route = express.Router();
const listingController = require("../Controllers/listingController");
require('dotenv').config();
route.post("/create", listingController.createListing)
route.post("/update", listingController.updateListing)
route.post("/read", listingController.getListing)
route.post("/delete", listingController.deleteListing)
...
...
...
...
...
route.post("/getMostPopular" , listingController.getMostPopular)
route.post("/getByCategory" , listingController.getByCategory)
route.post("/getAllTOS" , TOSController.getTOSByListing)
route.post("/getTOS" , TOSController.getTOSByID)
route.post("/updateTOS" , TOSController.updateTOS)
route.post("/deleteTOS" , TOSController.deleteTOS)
route.post("/createTOS" , TOSController.createTOS)
route.post("/getListingsByIDs" , listingController.getListingsByIDs)
route.post("/cacheImagesNewCDN" , listingController.cacheImagesNewCDN)
module.exports = route;
My listingController file
const listingModel = require('../Models/listingModel');
const moment = require('moment')
const axios = require('axios');
var fs = require('fs');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
var fs = require('fs');
//tested
const createListing =async (req, res) => {
try {
//some logic here
}
catch (err) {
console.log(err)
return res.status(500).json({ error: err.message });
}
}
const updateListing = async (req, res) => {
try {
//some logic here
}
catch (err) {
return res.status(500).json({ error: err.message });
}
}
module.exports = {
getListing,
updateListing,
deleteListing,
createListing,
listingwithViews,
advertisedListings,
filterListings,
pressedOnBookNow,
cacheImages,
recommendListings,
getCacheMetaData,
addIndoorAmenity,
missingFromFilter,
adjustCreativeStudios,
listingsToCSV,
getAllListing,
getDiscountedListings,
addRevenueToListings,
getMostPopular,
getByCategory,
getListingsByIDs,
cacheImagesNewCDN,
getOwnersPhones
}
All the routes starting from getMostPopular till the end of the list give an error 404 not found although I have done the same procedure to all of them. Any ideas why this is happening? If you feel this isn't enough information to help diagnose, let me know and i'd be happy to provide more details. You're help would be beyond appreciated, thanks!

How do i fill my parameter req.body with axios (Vue.js) to my Express.js server

Im trying to send a connect call to my api from my vue (i use vue.js),
but when i get the object req.body in my back, the object is empty
I've read this : Axios post request.body is empty object
but it didn't help me
(it works from Postman with the body filled and the option x-www-form-encoded)
i got this got from my Vue :
My vue service.js
import Axios from 'axios';
class APIClient {
constructor () {
this.client = Axios.create({
baseURL: 'http://localhost:8080'
});
}
async connect () {
const params = new URLSearchParams();
params.append('mail', 'test');
params.append('pwd', 'mypwd');
return await this.client.get('/api/user/auth', params);
}
and i got this in my back :
index.ts :
import express from "express";
var cors = require('cors');
import "reflect-metadata";
var bodyParser = require('body-parser')
const http = require('http');
const MainRouter = require('./routes/main_router');
let port = 8080;
const server = express();
server.use(cors({origin: true}))
server.use(bodyParser.json());
server.use(bodyParser.urlencoded({extended: true}))
let mainRouter = new MainRouter(server);
const httpServer = http.createServer(server);
httpServer.listen(port);
console.log('Server is listening');
and the main_router.ts
import express from 'express';
import mysql from "promise-mysql";
export default class MainRouter {
public server: express.Express;
constructor (server: express.Express) {
super();
this.server = server;
this.server.get("/api/user/auth", async (req: any, res: any) => {
if (req.body) //the req.body is equal to {} instead of {mail: 'test', ...
return res.json(await this.userManager.getUserByCredidentials(req.body));
else return res.json([])
});
}
}
module.exports = MainRouter;
I don't know if i have something to add in my express server or in my vue with axios ?
You are passing the mail and pwd as GET parameters and not at the request body. You can access the using req.query, but ....
You should avoid sending creds as parameters of the url with GET, use the body and POST instead. For more information see this post.
Here is an example:
return await this.client.post('/api/user/auth', {
mail: "test",
pwd: "mypwd"
});
and of course do not forget to change this.server.get("/api/user/auth",... to this.server.post("/api/user/auth",...

Can't find the data that's sended by using Ajax in the request object (Nodejs)

I send a data object as in the code;
var xhttp = new XMLHttpRequest();
var dataset;
function data () {
dataset = {
"name" : document.getElementsByName("name")[0].value,
"pass" : document.getElementsByName("pass")[0].value,
"email" : document.getElementsByName("email")[0].value,
"birthday" : document.getElementsByName("birthday")[0].value,
"agree" : false
}
if(document.getElementById("signupcheck").className.search("active") > -1) dataset.agree = true
xhttp.open("POST", "/example", true);
xhttp.send(dataset);
}
And I try to get that data on NodeJs as in the code;
var express = require("express");
var app = express();
var router = express.Router();
app.use(express.static('public'));
app.get("/",function(req,res){
res.sendFile(__dirname + "/index.html");
console.log(__dirname);
})
app.post("/example", function(req,res) {
console.log(req.body)
})
var server = app.listen(8000,function(){
})
Ajax is working because I can see the req object on the console when I initialize the function. But the req object is so huge that doesn't fit into the terminal.
I can't find the data I send. How can I get the data?
So I think the issue is with your request.
After running it locally I get:
TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be of type string or an instance of Buffer or ArrayBuffer. Received an instance of Object
After taking a look at the documentation it confirms this https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/send
Could you try this?
xhttp.send(JSON.stringify({dataset: dataset}))
or you could update your dataset object to
const dataset = {
dataset: {
name: document.getElementsByName('name')[0].value,
pass: document.getElementsByName('pass')[0].value,
email: document.getElementsByName('email')[0].value,
birthday: document.getElementsByName('birthday')[0].value,
agree: false,
},
}
and keep
xhttp.send(dataset)
Add the express json middleware so that you can access the body.
const express = require('express')
const app = express()
const router = express.Router()
app.use(express.json())
console.log(req.body.dataset)

Not getting expected results from included files in Nodejs

I'm not getting expected results by including files in Nodejs. Here is my code:
Service Route File
const express = require('express');
const router = express.Router();
const path = require('path');
const config = require('../config');
const serviceAdapter = require('./serviceAdapter');
module.exports = (preRequestPath, serviceBaseUrl) => {
console.log("On server start", preRequestPath)
router.post('/*', (req, res) => {
console.log("On request", preRequestPath)
const axiosHttp = serviceAdapter(serviceBaseUrl);
axiosHttp.post(preRequestPath+req.path, req.body).then(resp => {
res.send(resp.data)
}).catch(err => {
res.status(404).sendFile(path.join(__dirname + '/../404.html'));
});
});
return router;
}
Main Server File
const express = require('express');
const userApiService = require('./routes/userService');
const userAdminService = require('./routes/userService');
app.use('/api/user_service/', userApiService("/api", config.userServiceUrl) );
app.use('/admin/user_service/', userAdminService("/admin", config.userServiceUrl) );
var server = app.listen(3000, function(){
console.log('Server listening on port 3000');
});
module.exports = server;
Expecting Console Result:
On server start /api
On server start /admin
On request /api (when hitting http://baseurl.com/api/<anything>)
On request /admin (when hitting http://baseurl.com/admin/<anything>)
But Getting Console Output as:
On server start /api
On server start /admin
On request /api (when hitting http://baseurl.com/api/<anything>)
On request /api (when hitting http://baseurl.com/admin/<anything>)
Both the time, returning /api path.
Can anyone tell me why is it happening and what's the solution?
You're creating only one router in userService.js (the first file). It's created once before the function so you really only end up with one router. The first time you require it the router gets created, but the second time you require it Node knows it was already loaded and it's not re-initialized. You should be creating a different router for each case like this:
const express = require('express');
// const router = express.Router(); <-- don't do it here
const path = require('path');
const config = require('../config');
const serviceAdapter = require('./serviceAdapter');
module.exports = (preRequestPath, serviceBaseUrl) => {
const router = express.Router(); // <--- create a new router for each case
console.log("On server start", preRequestPath)
router.post('/*', (req, res) => {
console.log("On request", preRequestPath)
const axiosHttp = serviceAdapter(serviceBaseUrl);
axiosHttp.post(preRequestPath+req.path, req.body).then(resp => {
res.send(resp.data)
}).catch(err => {
res.status(404).sendFile(path.join(__dirname + '/../404.html'));
});
});
return router;
}
Also in your main server file you only need to require it once. It's just a function to create the service so you don't need 2 different variables holding that function. So you can initialize both using the one function like this:
// const userApiService = require('./routes/userService');
// const userAdminService = require('./routes/userService');
const service = require('./routes/userService');
app.use('/api/user_service/', service("/api", config.userServiceUrl) );
app.use('/admin/user_service/', service("/admin", config.userServiceUrl) );

No output from Node app

I am trying to run a simple node application using nide modules and testing it using the Advance Rest Client.
The console is not showing any error.
But I am not getting anything in the output.
While running this on ARC, I am getting : Cannot /GET data
Text version of the code:
MainFile:
var express = require('express');
//var morgan = require('morgan');
var bodyparser = require('body-parser');
var hostname = 'localhost';
var port = '3000';
var app = express();
//app.use(morgan('dev'));
var dishRouter = express.Router();
dishRouter.use(bodyparser.json());
var allDishes = require('./dishRouter');
//For all dishes
dishRouter.route('/dishes')
.get(allDishes.dishesGet)
.delete(allDishes.dishesDelete)
.post(allDishes.dishesPost)
;
//For specific dishesDelete
dishRouter.route('/dishes/:dishid')
.get(allDishes.dishSpecificGet)
.delete(allDishes.dishSpecificDelete)
.put(allDishes.dishSpecificPut)
;
app.listen(port,hostname,function(){
console.log('server runing properly');
});
dishRouter file:
console.log('in dishrouter file');
module.exports.dishesGet = function(req,res,next){
console.log('inside GET');
res.end('Will be displaying all the dishes');
};
module.exports.dishesDelete = function(req,res,next){
res.end('Will delete all the dishes');
};
module.exports.dishesPost = function(req,res,next){
res.end('will add the new dishes');
};
module.exports.dishSpecificGet = function(req,res,next){
res.end('displaying the specific dish :'+req.params.dishid);
};
module.exports.dishSpecificDelete = function(req,res,next){
res.end('Will delete the specific dish with id : '+req.params.dishid);
};
module.exports.dishSpecificPut = function(req,res,next){
res.write('will update the specific dish :'+req.params.dishid);
res.end('Updating the dish with values as name : '+req.body.name);
};
According to body-parser docs
Looks like your router is a bit broken here:
dishRouter.use(bodyParser.json())
Try switching this to:
app.use(bodyParser.json())
And I can recommend creating router in the file, where you write handlers and just export router.
UPDATE:
Here is what you forgot:
app.use(dishRouter)
When calling express.Router() you're just creating an instance of the router, but you have to connect it to the express application instance.

Resources