Receiving submitted POST file Object in server side Javascript - javascript

When user sends a multi part form with files/images selected, generally in Meteor or node.js, the server side POST url handler uses this.request or req or request object to detect whether its a POST method or any other and its headers etc but what I don't understand is, where is the actually file located at this request object and how do I retrieve it so that it can be used for image/file upload or certain manipulations at server?

node provides the querystring api to parse strings that look like:
foo=bar&baz=qux&baz=quux&corge
...which is how multi part form data is also sent. Parsing this with that api will return an object:
{ foo: 'bar', baz: ['qux', 'quux'], corge: '' }
So, you can first detect the method of the request, and if it is POST, you can attach a handler to 'data', get all the data into your own variable, and on 'end' , parse it using querystring:
var qs = require('querystring');
// your request callback function would be something like:
function (request,response){
if(request.method=='POST'){
var body = '';
request.on('data',function(data){
body += data;
//reject requests that have sent too much data (eg 2MB):
if(body.length > 2e6){
// Send HTTP status code for `Request Entity Too Large`:
response.writeHead(413);
response.end();
});
request.on('end', function(){
var form = qs.parse(body);
//use form as object
});
} // end if
} // end handler

Related

How to use superagent to send a FormData object

I am doing an API request follow by another one to a different server to which I need to pass a file.
Doing the first one is nice and easy. It looks something like this:
if (myFile) {
const data = new FormData()
data.append('myFile', myFile, myFile.name)
myFile = data
}
isomorphicFetch(`${MY_ENDPOINT}`, {
method: 'PATCH',
body: myFile
})
Now, in the server side, I need to pass this into another server. Which I am using superagent for. However I seem to be losing the file in the process. Here is what the code currently looks like:
const fileField = Object.keys(data).pop()
if (fileField === 'myFile') {
res = await request
.patch(`${MY_OTHER_ENDPOINT}`)
.send(data)
.query(query)
}
Take note that data is the body of the previous request, and the FormData object is displayed as an empty object, so I am not sure what to do from here.
On my other server, my file comes back as undefined, however if I do the request straight from the client, it goes through as expected. So how can I forward the FormData object from one server app to the other?
Files are typically posted to servers as part of a Multipart request.
Superagent supports multipart requests like so:
request
.post('/upload')
.attach('image1', 'path/to/felix.jpeg')
.attach('image2', imageBuffer, 'luna.jpeg')
.field('caption', 'My cats')
.then(callback);
Additional information can be found in their documentation:
Superagent Docs - Multipart requests
Specific to your example, you want to make sure that your server is receiving the file and then using the attach function to put the file in your request.

node.js POST callbacks not received

I am POSTing a json file to a node.js listener, and I must not fully understand how POSTs are properly constructed, because in the code below the on('data') callback is never invoked. I can see the actual json string in the body, so I can work around the lack of a callback, but it seems like I'm doing something wrong with how I generate my POST request. [Postman details further below]
// Server initialization
var server = restify.createServer();
server.use(restify.queryParser());
server.use(CookieParser.parse);
server.use(restify.bodyParser());
// Later, at the point where I register callbacks.
this.server.post('receive', function (request, respond) {
console.log('Received POST');
console.log("Headers: %s", JSON.stringify(request.headers));
console.log("Body: %s", JSON.stringify(request.body));
var body = '' ;
var filePath = './data/notes.json';
// this event is never triggered.
request.on('data', function (data) {
console.log('Data received.');
body += data;
});
request.on('end', function () {
console.log('End of POST');
fs.writeFile(filePath, body, function () {
respond.end();
});
});
});
POST details:
I'm using Postman to create a POST request, Content-Type: application/json and the putting the json string in the raw body. What will normally trigger the 'data' event in a POST request? If I ignore data events and just read from the request body, will I run into issues?
Since you're using restify.bodyParser, that middleware would have already read the request body so there isn't any more for your handler to read (hence no data events). A stream, like request, can only be read once, until it's exhausted. You can't "re-read" it.
Which also means that you can just use request.body, which should be the (parsed) result of the JSON that you're posting.
As an aside: I don't know Postman very well, but it looks like you're sending a JSON-encoded string to the server, as opposed to a JSON-encoded object.
To send the latter, I would expect that this should be the raw body data:
{"body":"this is a test"}

PUT and POST Request of .save() of Backbonejs model

How to be confirmed whether a backbonejs .save() is sending PUT request ?? I checked my server side, which is working good, there is no problem in server side. But my .save() is not working.
Here is my model of backbone
define(['underscore','backbone'],function(_,Backbone)
{
var my_model = Backbone.Model.extend(
{
urlRoot: "http://localhost/back/server_file.php/number"
});
return my_model;
});
Here is how I am using .save()
var my_data = {
id: data.id,
code: data.code
};
var My_model = new my_model();
My_model.save(my_data,
{
success: function(response)
{
alert('Yes');
},
error: function(response)
{
alert('No');
}
});
I think my .save() is sending POST request to server.
UPDATE
I think I could find out my problem. I am describing that here.
What I would like to do
I would like to send 2 parameters from backbonejs model to server side script (I am using PHP SLIM Framework). Based on those 2 parameters server side script update a record's(2 field of this record match with those 2 parameters ) another field with a static parameter at database.
What backbonejs provide (As I think )
Backbonejs has a model with id as JSON format. Backbonejs sends PUT request to server side script. Server side script just dump (update) the data(which was as JSON format,like a bundle) to the database with matching id. Serer side script would not like to look inside the data.
I am getting (from network tab of firebug) my PUT request URL is like http://localhost/back/server_file.php/number/1 (This is the id) . On the other hand I would like to get URL is like http://localhost/back/server_file.php/number/1 (id the first parameter)/456 (Second parameter).
If I am right, anyone could say how can I implement my plan??
This should work,
My_model.set(my_data);
My_model.save(null, {
wait : true,
url : "http://localhost/back/server_file.php/number/1/456",
success : function(response){
},
error : function(e){
}
});
You can debug the request being sent in network tab of Chrome Developer Tools or you can use a network tool like Fiddler to see all requests.
Refer the attached on where to see the request method being used.

Sending two objects as response to a single GET request using Express and Node.js

I have the following piece of code -
sendServer.get('/download',function(request,response){
var status="SELECT * from poetserver.download where status='0'";
console.log(status)
connection.query(status,function(error,rows){
var toSend=rows[0].id
response.sendfile('./testimages/'+toSend+'.PNG')
// var details={"pictureId":toSend}
// response.writeHead(200, { 'Content-Type': 'application/json' });
// response.send(JSON.stringify(details));
Essentially I, first, want to send a file as identified by toSend. The file is successfully sent using response.sendFile. But I also want to provide some identification of the file for the client for future responses. How do I send that too?
To send an id for the image (ressource) that you are responding with, you should use a HTTP header such as ETag. Do not try to send JSON and binary data in one response body.

After creating new instance in collection, don't do a GET request on the endpoint (backbone)

After I add a model instance to a collection, I do a POST request to add it. Then a GET request is done to get the model from the server. Is there a way to not to the GET request, only the POST request? Also, is it possible to get the success and error callback functions to respond to the success and failure of the POST request?
I want to do this because the collection has a URL that parses the JSON data that gets back, so the GET request doesn't work, but the POST request does work. I don't want to do a GET request on a endpoint that doesn't work.
The GET request is unnecessary. On the server in your POST handler you should return a JSON result back to the client representing the model. This is especially useful when there are generated fields such as an id. Then on the client in the success callback you can grab the model returned from the POST.
In the following example a new model is added to the collection if successful. I've also included the error callback which will fire if either client side validation fails or the POST fails:
var isNew = this.model.isNew();
this.model.save({}, {
success: function(model, response) {
if (isNew && this.collection) {
this.collection.add(model);
}
},
error: function(model, response) {
var errorMsg;
// Response may be string (if failed client side validation or an AJAX response (if failed server side)
if (_.isString(response))
errorMsg = response;
else
errorMsg = response.responseText;
}
});
The process you follow is indeed unnecessary. You should be using create on the collection to directly add the model, and invoke sync (the POST in this case) in the same time.
For example:
collection.create({foo: 'bar'}); or collection.create(unsaved_model);
The result of invoking create will return either the (saved) model or false if this was not successful. In addition it is possible to wait for the model to be saved before adding to the collection by doing
collection.create({foo: 'bar'}, {wait: true});
The documentation is your friend.

Categories

Resources