So I'm running a node.js server with express that has this data. Ultimately I am trying to submit close notes, from a form in my html page, to update the close notes in this data set, which is hard coded into the node server for now.
var data = [
{
inc_num: "INC0001",
close_notes: "blah"
},
{
inc_num: "INC0002",
close_notes: ""
},
]
these are the three back end http requests.
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname + '/index.html'));
});
app.put('/update/:inc_num', (req, res) => {
delete data.close_notes;
var body = req.body
data.close_notes = body.close_notes;
res.status(200).send('ACK');
});
app.get('/update', (req, res) => {
res.send(data);
});
Here is the AJAX request from the front end
$.ajax({
url: '/update/' + inc_num,
type: 'PUT',
constentType: "application/json",
data: dataPut,
success: function(){
console.log('PUT SUCCESS');
}
})
The way it is right now nothing changes at all.
I know for a fact that the front end is sending the correct data through because if I change the function in the app.put to data.push(req.body) it adds the correct information I passed into the data array. I am either not understanding something about PUT request correctly or am just messing something up in the function of the back end PUT request.
Any help is greatly appreciated!
Related
I have a to-do list app that updates a string in a mongodb database with every change in state of the to-do list - that string is parsed on reload to render the state. It works great, except when I trigger 5 or 6 state changes quickly in sequence, it hangs the page. As example, if I delete 5 tasks over the course of a couple seconds. I assume the problem is handling all those post requests, but maybe it's on the updating mongodb side? Is there a way to handle a lot of post request like that in a some sort of queue?
Client side:
function sendData(obj) {
fetch('/jsondata', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(obj),
}).catch(function (error) {
console.log(error);
});
console.log('db updated');
}
Here's the mongo side that runs when the POST request is requested from client...if it helps:
app.post('/jsondata', function (req, res) {
updateUserCache(currentUserEmail, JSON.stringify(req.body));
});
async function updateUserCache(email, newState) {
const foundUser = await user.findOne({
email: email,
});
foundUser.cachedState = newState;
const newDate = await Date.now();
foundUser.date = newDate;
await foundUser.save();
console.log('user cache has been updated');
}
It's hanging because you're never sending back a response from your backend code, and at some point the browser will stop making new connections to it.
So make sure you end the requests properly:
app.post('/jsondata', async function (req, res) {
await updateUserCache(currentUserEmail, JSON.stringify(req.body));
res.end();
});
I have made basic web apps whereby data is sent via HTTP parameters. However, I am trying to send data from client-side that contains an array (a list of ingredients for a recipe) and eventually, hopefully user uploaded image (but not worried about that for now). For this I know I need to use AJAX. I have spent hours trying to get it to work but for some reason, no POST request is being sent. The user inputs are fairly basic but here's a snippet:
<label for="method"> Method </label>
<textarea id="method" name="method">method here</textarea>
</br>
<p> add ingredients </p>
<input name="ingredient" id="ingredient" placeholder="add ingredient">
<input name="quantity" id="quantity" placeholder="#"><button id="addIngBtn" type="button">Add</button><br>
<button type="submit">submit</button>
<p> Ingredients:</p>
<ul id="ingredientListUL">
I use JQUERY to allow users to append as many ingredients as they want to the list:
$(document).ready(() => {
$("#addIngBtn").click(() => {
let ingredient = $("#ingredient").val();
let quantity = $("#quantity").val();
$("#ingredient").val(""); //reset ingredient input
$("#quantity").val("");
$("ul").append(
"<li>" + ingredient + " - " + quantity + "</li>"
);
});
})
Ingredients are built into an array and then added to a new recipe object which is the data I want to send to my server:
var ingredients = [];
$("#ingredientListUL li").each((index, element) =>
ingredients.push($(element).text())
)
var recipe = {
name: $("#name").val(),
image: $("#image").val(),
oneLiner: $("#oneLiner").val(),
method: $("#method").val(),
ingredients: ingredients
}
So far so good. I presume I am doing something wrong with these next parts. Here's the AJAX post request:
$.ajax({
url: "http://localhost:5000/recipes",
type: "POST",
dataType: "json",
data: recipe,
contentType: "application/json",
complete: function () {
console.log("process complete");
},
success: function (data) {
console.log(data);
console.log("process success");
},
error: function () {
console.log(err);
}
})
And here's my server info:
// express setup
const express = require("express");
const app = express();
const port = 5000;
// set templating engine to EJS
app.set('view engine', 'ejs');
// import route files
const recipeRoutes = require("./routes/recipes")
app.use("/recipes", recipeRoutes);
// body parser
const bodyParser = require("body-parser");
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
//--
// BASIC ROUTES
//--
app.get("/", (req, res) => res.render("landing"));
// Port
app.listen(port, () => console.log(`Server starting on port ${port}!`));
All routes, are stored in a recipe routes file, which contains the post route for this request:
// default "/" route is really "/recipes" as defined in main server file.
router.post("/", (req, res) => {
console.log(req.body.recipe);
})
The problem is that nothing appears to be sent to, or received by my server according to network tab. Even when I try to send something like:
$.post("http://localhost:5000/recipes", { test: "test" })
What am I doing wrong? Thanks.
The contentType property does not work that way. It indicates if it is URL encoded, as a multipart message, etc. Try removing it.
According to: https://api.jquery.com/jquery.ajax/ :
"If you explicitly pass in a content-type to $.ajax(), then it is
always sent to the server (even if no data is sent)"
Im trying to figure it out for past 6 hours, but Im out of ideas..
What Im trying to accomplish:
I want to display a JSON data that looks like this
movie {title: " xxxxx", seed: "number", url: "zzzzzzzzz"}
I want to display it on my Node server(via jade), but what I accomplished till now is to send it from the website to my node server via POST request using this code:
My JS script
var http = new XMLHttpRequest();
var url = "http://localhost:8080/";
var params = arr; <------ My JSON data
http.open("POST", url, true);
//Send the proper header information along with the request
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
console.log(http.responseText);
}
}
http.send(params);
After using above code in my google chrome developer tools on the website I actually have that data, I receive the JSON array in my node, here is my node code:
My app.js node server
const http = require("http");
const express = require('express');
const app = express();
const myParser = require('body-parser');
app.set('views', __dirname + '/views')
app.set('view engine', 'jade')
app.use(express.static(__dirname + '/public'))
app.use(myParser.urlencoded({ extended: false }));
app.use(myParser.json())
var allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(allowCrossDomain);
app.get('/', function (req, res, next) {
res.render('index');
})
app.get('/tl', function (req, res, next) {
res.render('tl');
})
app.post("/", function (req, res) {
response = {
first_name: req.body
};
console.log('SHOW ME BODY')
console.log(req.body);
res.send('You sent: this to Express');
});
app.listen(8080);
And this is what Im receiving in my node command prompt:
{ '[{"title":" SOME-MOVE-TITLE","seed":"NUMBER","url":"https://SOMEURLS.COM', etc. etc. etc.
And finally here is my layout.jade file
doctype
html
head
title Bolo Node Server
link(rel="stylesheet", type="text/css", href="stylesheet/style.css")
body
header
h1 My Site
block content
footer
p Running on node with Express, Jade and Stylus
And index.jade
extend layout
block content
p= 'Block content works'
script.
if req.body != undefined
div(id='data')= req.body
I really run out of ideas on how to display the json array Im receiving...help me out please
Update
My index.jade
extend layout
block content
p= 'Block content works'
div(id='data')
pre
test= jsonString
My app.js looks now like this:
app.get('/', function (req, res, next) {
res.render('index');
})
app.post("/", function (req, res) {
// Get string representation
var jsonString = JSON.stringify(req.body || {}); // use JSON.stringify(req.body || {}, null, 2) for formatted JSON
console.log(jsonString);
res.render('index', {test: jsonString});
//res.send('You sent: this to Express');
});
I see the data in my node command prompt, but I dont see it on my local website http://localhost:8080/ the div(id='data') is showing me empty.. nothing, how do I get the jsonString there?? I want it to show me the data on my local website..
**
UPDATE
**
I ended up just putting the data into the sqlite3 database and then retrieving the data via GET request and finally putting it into my jade template. I thought I can go around and not use sqlite3 but I couldnt figure out how.
When you say that you want to display the json, if you just want to see the contents of the json you can use res.json.
app.post("/", function (req, res) {
// Send back the request body if present or else, an empty object
res.json(req.body || {});
});
If you want it to be displayed inside a template, you can get a string representation of the json using JSON.stringify(req.body) and render that in your template by passing it to it as a local variable.
app.post("/", function (req, res) {
// Get string representation
var jsonString = JSON.stringify(req.body || {}); // use JSON.stringify(req.body || {}, null, 2) for formatted JSON
res.render('jsonView',{jsonString});
});
And in your template:
div(id='data')
pre
code = jsonString
You should pass the data in the template.
res.render('index', {data: 'data'});
And show it with:
data = data
p #{data}
First you should parse your incoming data, as is application/x-www-form-urlencoded. You'll need to JSON.parse req.body first and encode your response as json too
app.post("/", function (req, res) {
var response = try { JSON.parse(req.body) } catch(e) { console.error('Invalid Data') };
res.json(response || {});
});
You could also send your data as 'application/json' from you client JS and save receive a JSON directly to the req.body.
Hope it helps
UPDATE (if you want to append new data via async requests on the client)
In this post you can see the use of XmlHttpRequest with jquery $.ajax() which is basically the same concept of async requests after the DOM is rendered on your server.
Imagine the step 3 being your Jade rendered HTML
I ended up just putting the data into the sqlite3 database and then retrieving the data via GET request and finally putting it into my jade template. I thought I can go around and not use sqlite3 but I couldnt figure out how.
Here is the code
app.post("/", function (req, res) {
var jsonString = JSON.stringify(req.body || {});
db.serialize(function () {
var stmt = db.prepare("INSERT INTO movies (id, title, seed, url) VALUES (?,?,?,?)");
for (var i = 0; i < req.body.length; i++) {
var d = new Date();
var data = req.body;
var n = d.toLocaleTimeString();
stmt.run(i, req.body[i].title, req.body[i].seed, req.body[i].url);
}
stmt.finalize();
});
res.send('You sent: this to Express');
});
Retrieving the data from the database
app.get('/tl', function (req, res, next) {
db.all('select * from movies', function (err, rows) {
if (err)
return next(err);
var dataO = [];
rows.forEach(function (row) {
dataO.push(row);
})
res.render('tl', { dataO: dataO });
})
})
I'm running into a small issue with something I thought was possible.
I want to have two express routes, one GET route /post-data and one POST route /post-recieve.
The code would look something like this:
app.get('/post-data', (req, res, next) => {
//set url to '/post-recieve' and set body / headers
})
app.post('/post-recieve', (req, res, next) => {
return res.json(res.body)
})
Now, when you visit /post-data you should be instantly redirected to /post-recieve except if you look in the developer console you should see that the method for the document is POST and not a normal GET request.
Is this possible?
I know you can use a library like request to make a HTTP post request to an endpoint, but I'm talking about actually sending the user to the page via a POST request.
This feels so dumb, but it might be the only way???
function postProxyMiddleware (url, data) {
return (req, res, next) => {
let str = []
str.push(`<form id="theForm" action="${url}" method="POST">`)
each(data, (value, key) => {
str.push(`<input type="text" name="${key}" value="${value}">`)
})
str.push(`</form>`)
str.push(`<script>`)
str.push(`document.getElementById("theForm").submit()`)
str.push(`</script>`)
return res.send(str.join(''))
}
}
app.get('/mock', postProxyMiddleware('/page', exampleHeaders))
The only way to change the client's request method from GET to POST programmatically is to create a form containing hidden elements with method="post" and action="/post-receive", then using client-side JavaScript to automatically submit the form.
Any HTTP redirects in response to a GET request will also be GET.
You can use request-promise to post the data to a url. So, initiate with this function and you can get the data in the api url
const request = require('request');
const rp = require('request-promise');
let req = {
"param1" : "data1",
"param1" : "data2"
}
rp({
method: 'POST',
uri: 'http://localhost:3000/post-data/',
body: req,
json: true // Automatically stringifies the body to JSON
}).then(function (parsedBody) {
console.dir(parsedBody);
return parsedBody;
// POST succeeded...
})
.catch(function (err) {
console.log(err+'failed to post data.');
return err+'failed to post data.';
// POST failed...
});
Apologies If I get your question wrong.
i'm having a problem here.
I have this piece of code:
var controller = require('./controllers/controller');
app.post('/',
controller.create,
);
And inside that i have:
exports.create = function(req, res, next) {
res.send('test');
};
Yes, i'm using a form to make a post.
The code is not working, the console will show: Can't set headers after they sent.
But if i change the code to:
var controller = require('./controllers/controller');
app.post('/', function(req, res {
res.send('test');
});
Will work!!!!! Why is that???
UPDATE:
I don't know if maybe this is causing that, but i have this following code:
var home = require('./controllers/home');
app.get('/',
home.index
);
And inside that i have this code:
exports.index = function(req, res, next) {
var url = "someurl/"
var stringify = "";
var request = https.get(url, function(response) {
response.on('data', function(json) {
stringify += json
});
response.on('end', function() {
var json = JSON.parse(stringify);
var data = json.feed.entry;
res.render('index', {
data: data
});
});
});
};
if i pass the code of the first controller to the home controller, will work.. but i need separate.
response.on('end', function() {
var json = JSON.parse(stringify);
var data = json.feed.entry;
res.render('index', {
data: data
});
});
Here you're trying to listen for when the response ends. This event only fires when the response has been sent to the client already, including the response headers. Your call to res.render fails because the response has ended. You can't then continue to send more data to the client. Anything that happens in the "end" event handler cannot write to the response stream anymore.