Unexpected End of Input - curl JSON on Express/Node App - javascript

I have an Express/Node app that is deployed to a Heroku instance. The app has a POST api endpoint that expects a .json file, reads the data, and populates the app with the JSON data. Below is the backend code that handles the POST request:
router.route('/data')
.post(function (req, res) {
return DataUtils.storeData(req, res);
});
Utils.storeData = function (req, res) {
req.pipe(req.busboy);
req.busboy.on('file', function (fieldname, file, filename) {
file.on('data', function(data) {
var data;
try {
data = JSON.parse('' + data); // quick casting into a String
var numPersonSessionObj = data.length;
...
// etc etc...
When we try to make the request via the curl command below:
curl -H "Content-Length: 5567" -F file=#sample_data/sample_json.json
http://[heroku-instance]/api/data
The server sometimes works fine, and uploads the data, and other times, throws an "Unexpected end of input" error. It seems as though the buffer method we're using is not reading all of the data for some reason. Upon logging the data.length in the code above (i.e. the JSON), it seems as though the request fails whenever the data length is less than its supposed to be. Is there something wrong with how I'm reading in the JSON file above? Thanks--

The data event only indicates that some data was received – not that all data was received. You want to wait for the end event before parsing your JSON. See this example from the official documentation for further details: https://nodejs.org/api/stream.html#stream_api_for_stream_consumers

Content-Length must be the count of octets the response body.
if you try using the value of
data.length
rather than
Buffer.byteLength(data)

Related

GET vs POST file download using express.js - changing the REST verb results in larger and incorrect file

My situation is that in one of my services I provide many REST GET APIs to allow the downloading of files (typically xlsx).
In a new API I have a POST API which does exactly the same thing as another GET API (I've copied pasted the code line by line), except that it's using a POST instead of a GET
export async function postDownloadMyFile (
req: Request,
res: Response,
next: NextFunction
): Promise<Response> {
... // xlsx workBook creation code
const buffer = await workBook.xlsx.writeBuffer();
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', 'attachment; filename=' + 'MyFile.xlsx');
res.write(buffer, 'binary');
res.end();
return res;
}
but when the frontend client makes a request to download the file, the file comes back about twice the size than if I used a GET request and cannot be opened (presumably wrong format/buffer written out wrong).
changing the frontend and backend to use a GET (not modifying the body of the function above) 'fixes' the issue.
Are there some additional headers I'm meant to be setting?
Thanks

EDITED: Can't send POST request to Express server with Fetch API, keep getting JSON.parse error

I'm new to JavaScript, and am learning to develop with an Express server on Glitch.com. I am running into issues with my Fetch API POST request, where it keeps returning a JSON.parse error when I try to send it a JSON object.
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I plan on using the JSON object to take in input from an HTML form, and I have that data saved in string variables but cannot use it. When I test JSON.stringify and JSON.parse in the console, it logs it as
Object { some: 1 }
I am also not sure where I should be directing the URL of the Fetch API, though the Express code is saved in a folder in Glitch called "server/ex.js". Thank you in advance!
UPDATE
So it looks like I'm getting errors with my Express server, when I check the response status code it's 404. How do I find the right URL?
try this code:
var payload = {
a: 1,
b: 2
};
var data = new FormData();
data.append( "json", JSON.stringify( payload ) );
fetch("/echo/json/",
{
method: "POST",
body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })
This code above is in: Fetch: POST json data
If you started a node project, you will want to edit the server.js file to include the following codes:
app.post('/server/ex.js',function(req,res){
res.send(JSON.stringify({
'hello':'world'
}))
})
then the fetch request in client.js should return the json object
edit1) sorry, just realised it was a post request, not a get request
edit2) in order to parse the json object you sent {some:1}, you will need bodyparser package.
edit after seeing server.js:
you will need the following for server.js at the very top if it does not already:
var express = require('express')
var app = express()
in addition, it will need the code snippit above somewhere later.
I am not too sure where you are getting the next() function from, though.

Send body JSON with Postman in a POST method to execute procedure in ms sql server

I want to send a JSON (body) on Postman with POST method and receive a result.
Im a trainee and my boss asked me this. I've been looking in web for a week and didn't find. I said to him that method to receive a data is GET, but he said that GET has a limit on URL. If the stored procedure have a lot of parameters we will not receive the expected result, so a I have to use Post method.
This is my code to connect to ms sql server:
var express = require('express');
var app = express();
var sql = require('mssql');
var config = {
user: 'MY_USER',
password: 'MY_PASS',
server: 'MY_SERVER',
database: 'MY_DB'
};
Searching in google I found a way to execute a procedure with GET method. In the browser I put the value I want and I receive the result, but is not still what he wants. The code is:
app.get('/get/:pNU_EST001', function (req, res) {
//conexão com o DB
sql.connect(config, function(){
var request = new sql.Request();
request.input('pNU_EST001', req.params.pNU_EST001);
request.execute('dbo.ESTSP004_ConsultaLivrosEmprestadosAluno_XX', function(err, recordsets, returnValue, affected) {
if(err) console.log(err);
res.send(recordsets);
//res.end(JSON.stringify(recordsets)); /*--- result in JSON format ---*/
});
});
});
On Postman he showed me a example with DB2, but I couldn't see the code. On Post Method, on HEADERS it has two key:
KEY => Content-Type (value: application/json) // KEY => Accept (value: application/json)
And in his example, on BODY, he wrote a JSON like: { "pNU_EST001" : "3"} and received the related result below. That's what I need.
Express has a few other verbs to use you are using
app.get but there is also app.post if you change your code to use the latter instead it will handle a post request
app.post('/path', function (req, res) {
Then in express to get values from the POST body you get that from
req.body property
So in your case you would want to use req.body.pNU_EST001 instead of req.params.pNU_EST001

Neither Node.js PUT or POST routes are presenting the data that is being received

I tried this with a number of different modules and methods.
Even by proving the other modules do work as expected in Node by building a separate test project and testing each module individually.
Posting FROM Node's hosted router to a remote API (not TO Node's hosted API)
This problem is not one of SENDING data to an API. It must IMO a problem in the receiving API's not giving up the data it IS receiving for some reason.
I've proven the PUT or POST calls are sending the data by sending the call to http://httpbin/org. That site shows me I'm sending what I expect to be sending.
Here is how I'm sending. I can even see in the receiving API that that API is certainly getting called successfully.
-- sending -- ((Again. This shows my node.http attempt. But I get the same problem using requestjs, requestifyjs, needlejs))
router.get('/', function (req, res, next) {
var hst = req.headers.host.split(':');
var lookbackURL = 'https://' + req.headers.host + req.baseUrl;
lookbackURL = 'http"httpbin.org/put';
var dat = {
what: 'ever'
, try: 'again'
};
var bdy = JSON.stringify(dat);
var options = {
host: hst[0], port: hst[1], path: req.baseUrl, method: 'PUT'
, headers: { 'Content-Type': 'application/json' }
};
var r = nodeHttp.request(options); r.write(bdy); r.end();
res.sendStatus(200);
});
-- receiving --
router.put('/', function (req, res, next) {
console.log('r', req);
});
No matter what module or method I use, in all cases, the receiving req object doesn't contain the what or try data.
BUT in my test project the data is there as I expect it to be, in all cases.
Doing the same console.log(req); in the test project, reqestjs, requestjs, needlejs, node.http all show a proper body object.
But in this problem there isn't a body object in req.
And sending this put/post to http://httpbin.org I can see the body object is being sent.
Any ideas?
Issue found. And it was something no one on here could have gotten for the code I posted.
For reasons I will not go into I have to take body-parser out this application. This also means app.use() won't have a parser given to it.
And that means I have to deal with getting the data on my own. So I've added a req.on('data') listener to read the chunk from the call to the API.
router.put('/', function (req, res, next) {
var data = '';
req.on('data', function (chunk) {
data += chunk;
.....
});
.....
I also decided to do this as a PUT using Requestify.
This just goes to show how easy it is to become complacent and forget how things really work; the assumption of body-parser (or other things) always being there for instance. Or what it is really doing for you.
NEXT I have to figure out how to get a value out of the `req.on('data) back to the method PUTting to the API. Any tips? Appreciated.

Node JS HTTP Server request.on('data') event failure

I am working on a NodeACS app in which I have to send xml as request from Java HTTP client and to receive response after some manipulation. The Java HTTP Client is working fine so far but the issue is with Node JS file. The req.on('data'...) event is not firing in my case.
Following is the code of my JS file:
function index(req, res) {
console.log(req.headers); //Its getting printed on console
req.on('data', function (data) {
console.log("Inside 1"); //Not printed on console
....REST OF THE CODE....
});
req.on('end', function () {
res.writeHead(200);
res.end();
});
}
In the above code after getting request the index function is called and printing the output for console.log(req.headers); but as mentioned above the script is not running after that. Please help me out What am I missing in this.
For testing I have installed cURL on my system and sending POST request to server using cURL request using following command:
curl -X POST -d #output.xml http://localhost:7788/
Can you confirm you aren't consuming the body prior to this? If the body has been consumed already by another middleware like body-parser you would need to restream the body via something like connect-restreamer. If it were consumed, the data event would not be emitted.
If that checks out, check to see if the "end" event is being emitted. Could be a sign of the content-length header being set to the wrong value.

Categories

Resources