addwordform.addEventListener('submit', (event)=>{
event.preventDefault();
const formdata=new FormData(addwordform);
const word=formdata.get('addword');
const description =formdata.get('addiscription');
const worddata={
word,description,totalcount
};
console.log(worddata);
fetch(API_URL,{
method:'POST',
headers:{
'content-Type':'application/json'
},
body:JSON.stringify(worddata),
}).then(response=>response.json()).then( data =>{
console.log(data);
});
});
this is the client side javascript
here API_URL="http://localhost:3005/word"
and server side code is
const express= require('express');
const serveStatic = require('serve-static');
const datastore= require('nedb');
const app= express();
app.listen(3005,()=>{console.log("listening on :http://localhost:3005")});
app.use(serveStatic('public',{'index':['client.html']}));
const database=new datastore('database.db');
database.loadDatabase();
app.post('/word',(req,res)=>{
const data=req.body;
database.insert(data);
res.json();
});
i am using express a node framework and vanilla javascript for client side all i want is to post the data from a form that has an id=addwordform and i am using nedb a light weight database management in node
.problem with it is the worddata that i am sending from client side is not getting in the server side "req" so i cant save it in database and ultimatly i cant "res" it back ?
If you're using express version >= 4.16. Body parser comes bundled with express.
It parses incoming requests with JSON payloads and is based on body-parser.
It is not needed to use body-parser. Here is the documentation
You just have to add this code before require your routes.
app.use(express.json());
Here is the stackoverflow original post.
Here is the express release
Here is the express commit
Related
I'm just trying to pass the simplest data possible (at the moment, for test purposes) from client to server with a POST request, but I keep getting empty or undefined logs on req.body.
Server:
//jshint esversion:6
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/sandbox", {useNewUrlParser: true});
app.get("/", function(req, res){
res.render("home", {});
})
app.post("/filter", function(req, res){
console.log(req.body);
res.redirect("/");
})
app.listen(3000, function() {
console.log("Server started on port 3000");
});
Client (version 1):
var yourdata = { "name": "The pertinent data"};
console.log(document.body)
$.ajax({
url : "/filter",
type: "POST",
dataType:'text',
data : yourdata,
contentType: "application/json",
});
Client (version 2):
var payload = {data: "The pertinent data"};
var req = new XMLHttpRequest();
req.open('POST', '/filter' , true);
req.send(JSON.stringify(payload))
I added both attempts at a code client-side, but I'm happy with whichever method works. Ideally I'll eventually tap into the payload or data with req.body.payload or something, but at the moment that's just giving me an undefined.
I've looked into quite a few similar posts and usually they were missing the "app.use(bodyParser.urlencoded({extended: true}));" or "app.use(bodyParser.json());" I've tried adding and removing those, changing from true to false, still empty.
The console.log(document.body) on the client script does work, giving me the expected body on the browser console, and the server route is working too, eventually redirecting to home.
I can't see how the issue is something I'm doing wrong on the client side, but oddly enough, if I create a form, with an action to that route, and submit, it seems to send the req.body normally. E.g.:
<form class="form" action="/filter" method="post">
<input name="newName" placeholder="Name">
<button type="submit">Submit</button>
</form>
That does indeed log a JSON object e.g.: { newName: 'John'}
In case it might be relevant, the HTML is the simplest one possible, almost empty, only really doing the pertinent links.
Thanks all in advance!
You need three things:
A request body encoded in some data format
A content-type request header which says which data format you are using
Body parsing middleware that can process that data format
When you submit a form, with no enctype attribute, it will submit the data in URL encoded format with the right content type. This matches the body parsing middleware you have (bodyParser.urlencoded({extended: true})).
1, 2, and 3 are all good.
Note that it does not create a JSON object. The client produces URL encoded data. The server parses that into a JavaScript object. There is no JSON.
Client (version 1):
Here you are passing an object to jQuery so it will URL encode the data in it and would normally set the correct content type.
It is failing because you have contentType: "application/json",.
Since you are falsely claiming that you are sending JSON, bodyParser.urlencoded ignores it.
If you had a JSON body parser in place, it would error because the data is not JSON.
1 and 3 are good, but 2 is a lie.
Remove the contentType property.
Client (version 2):
Now you are JSON encoding the data, but you aren't setting the content type request header, and you don't have body parsing middleware that can handle JSON.
3 is bad, and either 1 or 2 is too.
For the server-side part of your application, you need something that moves the body of the request out of the request string itself to a clear, easy-to-read, and use variable. The express json() method (middleware) does that exactly.
Use the express JSON parser middleware as follows:
app.use(express.json())
Code:
const express = require("express");
// const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
app.use(express.json()); // 👈 here
// ... the rest of your code
Just few notes about the middleware you're using
app.use(bodyParser.urlencoded({extended: true}));
We usually use this middleware to parse the HTML forms data, in other words, it's just like the express middleware express.json(), but the difference here is that it parses the requests which have the content type of HTML forms, while the express.json() converts the ones which have the content-type of application/json.
If you're using express v +4, you don't need the bodyParser package, express has the .urlencoded() and the .json() methods built into the express package itself, you can use them just as express.json() and express.urlencoded().
Tip, you can have both middlewares, the JSON parser, and the HTML form content type parser, when the server receives a content-type JSON, the express.json() middleware will parse the request body, and if the server receives an HTML form content-type the urlencoded middleware will fire:
code example:
const express = require("express");
// const bodyParser = require("body-parser"); ❌ not needed
const mongoose = require("mongoose");
const app = express();
app.use(express.json()); // 👈 here
app.use(express.urlencoded({ extended: true })) // 👈 here
// ... the rest of your code
First a quick preface I think may be helpful: I am new to splitting my client and server into separate web apps. My previous apps have all had my server.js at the root level in my directory and the client (typically a create-react-app) in a /client folder.
What I wanted to do: Host a single express.js server on the web which multiple other web applications could make requests to.
I did the first part using an express server and aws elastic beanstalk.
server.js
require('dotenv').config()
const express = require('express');
const app = express();
const cors = require('cors');
const PORT = process.env.PORT || 5000;
const Mongoose = require('mongoose');
const { Sequelize } = require("sequelize");
//ROUTES
const APIUser = require('./routes/api/mongo/api-user');
more routes...
//INITIATE DATA MAPPING CONNECTIONS START
Mongoose.connect(
process.env.MONGO_URI,
{ useNewUrlParser: true, useUnifiedTopology: true },
console.log("connected to MongoDB")
);
const Postgres = new Sequelize(process.env.PG_CONN_STRING);
try {
Postgres.authenticate()
.then(console.log("connected to Postgres"));
} catch {
console.log("Postgres connection failed")
}
//INITIATE DATA MAPPING CONNECTIONS END
//middleware
app.use(cors())
more middleware...
//home route
app.get('/api', (req, res) => {
console.log('RECEIVED REQ to [production]/api/')
res.status(200).send('models api home').end();
})
//all other routes
app.use('/api/user', APIUser);
more route definitions...
//launch
app.listen(PORT, () => console.log(`listening on port ${PORT}`));
The log file for successful boot up on aws: https://imgur.com/vLgdaxK
At first glance it seemed to work as my postman requests were working. Status 200 with appropriate response: https://imgur.com/VH4eHzH
Next I tested this from one of my actual clients in localhost. Here is one of my react client's api util files where axios calls are made to the backend:
import { PROXY_URL } from '../../config';
import { axiosInstance } from '../util';
const axiosProxy = axios.create({baseURL: PROXY_URL}); //this was the most reliable way I found to proxy requests to the server
export const setAuthToken = () => {
const route = "/api/authorization/new-token";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route)
}
export const authorize = clientsecret => {
const route = "/api/authorization/authorize-survey-analytics-client";
console.log("SENDING REQ TO: " + PROXY_URL + route)
return axiosProxy.post(route, { clientsecret })
}
Once again it worked... or rather I eventually got it to work: https://imgur.com/c2rPuoc
So I figured all was well now but when I tried using the live version of the client the request failed somewhere.
in summary the live api works when requests are made from postman or localhost but doesn't respond when requests are made from a live client https://imgur.com/kOk2RWf
I have confirmed that the requests made from the live client do not make it to the live server (by making requests from a live client and then checking the aws live server logs).
I am not receiving any Cors or Cross-Origin-Access errors and the requests from the live client to the live server don't throw any loud errors, I just eventually get a net::ERR_CONNECTION_TIMED_OUT. Any ideas where I can look for issues or is there more code I could share?
Thank you!
Add a console.log(PROXY_URL) in your client application and check your browser console if that's logged correctly.
If it works on your local client build, and through POSTMAN, then your backend api is probably good. I highly suspect that your env variables are not being set. If PROXY_URL is an emplty string, your axios requests will be routed back to the origin of your client. But I assume they have different origins since you mention that they're separate apps.
Remember environment variables need to prefixed with REACT_APP_ and in a production build they have to be available at build time (wherever you perform npm run build)
I have this URL here: https://viacep.com.br/ws/01001000/json/ , that lets me retrieve JSON data whenever i change the given number on it(the number is unique). For example: 01001000 has its own data, and if i change it for 49140000, it will have its own data as well. What i want to do is: i want to save the JSON data into a database, and somehow cache/save the request, so if in the future i search for the same number again, it won't have to retrieve the data from the URL again.
I have this right now:
My city.routes.js where i make the request to the API:
const express = require('express');
const axios = require('axios');
const cityRouter = express.Router();
cityRouter.get('/:cep', async (request, response) => {
try {
const { cep } = request.params;
const resp = await axios.get(`https://viacep.com.br/ws/${cep}/json/`);
return response.json(resp.data);
} catch (error) {
return response.status(400);
}
});
module.exports = cityRouter;
An index.js to make easier to the server to import and use the routes:
const express = require('express');
const routes = express.Router();
const cityRoutes = require('./city.routes');
routes.use(cityRoutes);
module.exports = routes;
My server.js:
const express = require('express');
const routes = require('./routes');
const app = express();
app.use(express.json());
app.use(routes);
app.listen(3333, () => {
console.log('Server is on!');
});
I can retrieve the JSON data that i want without problems:
enter image description here
You can do this via using caching libraries or using db and indexing on based of number for faster retrieval.
My suggestion:
If you need to cache for smaller amount of time lets say week or so prefer caching libraries like redis or memcache.
There u can do something like:
await redis.set(key, JSON.stringify(data), { expiry: '1W'});
The above code varies depending on library you use. But the idea remains the same you cache the data with key(Number).
And next time before making request you first tries to get the key from cache provider.
await redis.get(key)
if above value is present you will get json string of the desired result and dont need to make the network call.
If not present you make the network call and cache the result for future use.
In case of DB approach you simply make a get request via key to the db.
But do index the key in collection or relation when initializing the structure for faster retrieval.
Sorry for this noob question, student here and still learning
I'm trying to pass the request body of a POST request from server to client. I have an Arduino sensor making post requests with sensor data to an express server. The sensor data is inside the POST request body, and I push the data to an array called 'dataArray'. This part seems to be working.
My problem is that I'm now stuck on how to pass this data from the express server to a Vue component on the client side. Should I make a new route? I'm not asking anyone to write any code for me, I'm just hoping someone could point me in the right direction or suggest something, because I'm at a loss on exactly how I should go about doing this. Thank you.
server.js
var express = require("express")
var cors = require("cors")
var bodyParser = require("body-parser")
var app = express()
var mongoose = require("mongoose")
var Users = require("./routes/Users")
var port = process.env.PORT || 5000
var dataArray = []
app.use(bodyParser.json())
app.use(cors())
app.use(bodyParser.urlencoded({ extended: true }))
const mongoURI = 'my_connection_string'
mongoose.connect(mongoURI, { useNewUrlParser: true })
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err))
app.use("/users", Users)
app.route("/api/:apikey1")
app.post("/api/:apikey1", function(request, response) {
var myData = request.body;
console.log(myData)
dataArray.push(myData)
response.send("Array Filled")
});
app.listen(port, function () {
console.log("Server is running on port: " + port)
})
If you want to keep it simple use the socket.io library.
It is available for both client and server, you can use in your Vue client too.
Also, you won't need any extra route, just in your app.post("/api/:apikey1") route, use the emit method on socket.io library to broadcast the data as it is received from the sensors
Any data flow from the server to client must be first initiated on the client side, either by polling, using WebSockets or Server-sent events.
i'm using Express to create a backend server using NodeJs. One of the functionalities of the project is to send and receive PDF files. The other routes of the backend send and receive JSON files but i want to create a route for send and receive PDF files, what can i do? What i have until now:
const express = require('express')
const app = express()
const db = require('./config/db')
const consign = require('consign')
const consts = require('./util/constants')
//const routes = require('./config/routes')
consign()
.include('./src/config/middlewares.js')
.then('./src/api')
.then('./src/config/routes.js') // my routes file
.into(app)
app.db = db // database using knex
app.listen(consts.server_port,()=>{
//console.log('Backend executando...')
console.log(`Backend executing at port: ${consts.server_port}`)
})
app.get('/',(req,res)=>{
res.status(200).send('Primary endpoint')
})
/* basically at routes.js file i'm handling http routes that manages JSON objects such as this one below:
*/
At routes.js:
// intercept http routes and pass specific funtion for handling them
module.exports =app=>{
app.route('/products')// regular JSON objects
.post(app.src.api.itensVenda.saveItem)
.get(app.src.api.itensVenda.getItems)
.put(app.src.api.itensVenda.toggleItemVisibility)
app.route('/articles')
.get(app.src.api.articles.getArticle)
.post(app.src.api.articles.saveArticle)
// the route above is the one that i want to use for sending and receive PDF files
app.route('/info')// ordinary JSON objects
.post(app.src.api.info.saveInfo)
.get(app.src.api.info.getInfo)
}