I am using multiparty. It was working fine but suddenly it is throwing error.
Error
err: { Error: stream ended unexpectedly
at Form.<anonymous> (/user_code/node_modules/multiparty/index.js:754:24)
at emitNone (events.js:91:20)
at Form.emit (events.js:185:7)
at finishMaybe (_stream_writable.js:514:14)
at endWritable (_stream_writable.js:524:3)
at Form.Writable.end (_stream_writable.js:489:5)
at onend (_stream_readable.js:511:10)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickDomainCallback (internal/process/next_tick.js:128:9) status: 400, statusCode: 400 }
Code
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
var multiparty = require('multiparty');
var http = require('http');
var util = require('util');
exports.helloWorld = functions.https.onRequest((request, response) => {
var body = "";
var POST = {};
var form = new multiparty.Form();
form.on('error', function(err) {
console.log('Error parsing form: ' + err.stack);
});
form.parse(request, function(err, fields, files) {
response.status(500).send({
message: err
});
})
});
});
The "stream ended unexpectedly" error implies the underlying TCP socket was closed before a complete multipart form was received.
As you say this was previously working you should check the server to which you are making the request for any errors which may be closing the response early. One common cause is the size of the response data being larger than accepted by the server or request/response headers.
Related
I was following this article to setup a nodejs server on my local machine (which has 16 gb memory and about 170gb free disk-space) and uploaded a 20 gb file, for the first couple of times the file got uploaded successfully, but after a while i started getting EPIPE error:
error FetchError: request to http://localhost:3200/upload failed, reason: write EPIPE
at ClientRequest.<anonymous> (/Volumes/FreeAgent GoFlex Drive/Test/multer-project/node_modules/node-fetch/lib/index.js:1455:11)
at ClientRequest.emit (events.js:327:22)
at Socket.socketErrorListener (_http_client.js:467:9)
at Socket.emit (events.js:315:20)
at emitErrorNT (internal/streams/destroy.js:100:8)
at emitErrorCloseNT (internal/streams/destroy.js:68:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
type: 'system',
errno: 'EPIPE',
code: 'EPIPE'
}
When i checked, the file got uploaded partially and was about 28mb in size. I tried uploading the file from both Postman, browser and a nodejs script, but got the same EPIPE error message. I am not sure why is this happening, googling the error message didn't help. I am not sure how to overcome this. Following is my server and client code.
// server.js
const express = require("express"); // Express Web Server
const busboy = require("connect-busboy"); // Middleware to handle the file upload https://github.com/mscdex/connect-busboy
const path = require("path"); // Used for manipulation with path
const fs = require("fs-extra");
const app = express(); // Initialize the express web server
app.use(
busboy({
highWaterMark: 2 * 1024 * 1024 // Set 2MiB buffer
})
); // Insert the busboy middle-ware
const uploadPath = path.join(__dirname, "uploads/"); // Register the upload path
fs.ensureDir(uploadPath); // Make sure that he upload path exits
/**
* Create route /upload which handles the post request
*/
app.route("/upload").post((req, res, next) => {
req.pipe(req.busboy); // Pipe it trough busboy
req.busboy.on("file", (fieldname, file, filename) => {
console.log(`Upload of '${filename}' started`);
// Create a write stream of the new file
const fstream = fs.createWriteStream(path.join(uploadPath, filename));
// Pipe it trough
file.pipe(fstream);
// On finish of the upload
fstream.on("close", () => {
console.log(`Upload of '${filename}' finished`);
res.send("ok");
});
});
});
/**
* Serve the basic index.html with upload form
*/
app.route("/").get((req, res) => {
res.writeHead(200, { "Content-Type": "text/html" });
res.write(
'<form action="upload" method="post" enctype="multipart/form-data">'
);
res.write('<input type="file" name="fileToUpload"><br>');
res.write('<input type="submit">');
res.write("</form>");
return res.end();
});
const server = app.listen(3200, function() {
console.log(`Listening on port ${server.address().port}`);
});
and my client code is:
// client.js
const fs = require("fs");
const FormData = require("form-data");
const fetch = require("node-fetch");
var formdata = new FormData();
formdata.append(
"file",
fs.createReadStream("/Users/phantom007/My Documents/35gb.myfile")
);
var requestOptions = {
method: "POST",
body: formdata,
redirect: "follow"
};
fetch("http://localhost:3200/upload", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log("error", error));
Answering my own question.
After strugging for a long time i figured out that this error was coming because the number of bytes getting written on the same is larger than the number of bytes sent to the server, so in my client code, i changed
this
fs.createReadStream("/Users/phantom007/My Documents/35gb.myfile")
to this
fs.createReadStream("/Users/phantom007/My Documents/35gb.myfile", { highWaterMark: 2 * 1024 * 1024 })
This app is to get small piece of data from open weather map through api, app.js:
const express = require("express");
const https = require('https');
const app = express();
app.get("/", function (req, res) {
const url = "https://api.openweathermap.org/data/2.5/weather?q=Khartoum&appid=d244334364579178494bb3c4528e218b&units=metric"
https.get(url, function (response) {
response.on("data", function (data) {
const weatherData = JSON.parse(data);
res.write(weatherData.weather[0].description);
res.write(weatherData.weather[0].id);
res.send();
});
});
});
app.listen("3000", function () {
console.log("runnign on port 3000.");
});
the error that triggered in terminal when I reloaded the page:
_http_outgoing.js:671
throw new ERR_INVALID_ARG_TYPE('first argument',
^
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer. Received type number (804)
at write_ (_http_outgoing.js:671:11)
at ServerResponse.write (_http_outgoing.js:636:15)
at IncomingMessage.<anonymous> (/home/foola/Desktop/appBrewery/WeatherProject/app.js:18:17)
at IncomingMessage.emit (events.js:315:20)
at IncomingMessage.Readable.read (_stream_readable.js:512:10)
at flow (_stream_readable.js:985:34)
at resume_ (_stream_readable.js:966:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
code: 'ERR_INVALID_ARG_TYPE'
So what's the wrong here exactly?
mybe weatherData.weather[0].id is a number type likely integer?
try
res.write(weatherData.weather[0].id+'');
As the error message indicated, res.write accepts buffer or string only, weatherData.weather[0].id is of type int/number, therefore you might want to stringify it first before passing it to res.write.
res.write(weatherData.weather[0].id.toString())
I used Node.js and Express for the first time to make an API and I am having some issues.
I'm using Node.JS 13.11.0 and Express 4.17.1.
When I try to access 127.0.0.1:4008/api/nbhbdm and append parameters, I receive this error.
_http_outgoing.js:535
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:535:11)
at ServerResponse.header (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/express/lib/response.js:267:15)
at exports.XMLHttpRequest.httpRequest.onreadystatechange (/Users/zihangu/Desktop/TZG API/nbhbdm/app.js:28:17)
at exports.XMLHttpRequest.dispatchEvent (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:591:25)
at setState (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:610:14)
at IncomingMessage.<anonymous> (/Users/zihangu/Desktop/TZG API/nbhbdm/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:440:13)
at IncomingMessage.emit (events.js:315:20)
at IncomingMessage.Readable.read (_stream_readable.js:508:10) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Process exited with code 1
The following is my code.
const express = require('express');
const app = express();
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",'3.2.1');
res.header("Content-Type", "application/json;charset=utf-8");
next();
});
app.get('/api/nbhbdm',function(req,res,err){
console.log(req.query);
var keyword = encodeURI(encodeURI(req.query.keyword));
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "https://suo.im/api.htm?&key=000000000000&expireDate=2030-03-31&url=https://abcdef.cn/?s=" + keyword, true);
httpRequest.send();
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var result = httpRequest.responseText;
console.log(result);
res.json({"status":"ok","slink":result,"nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
}
else{
res.json({"status":"error","slink":"connection error","nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
}
}
})
var server = app.listen(4008, '127.0.0.1', function(){
var host = server.address().address;
var port = server.address().port;
console.log("Server running at http://%s:%s", host, port);
})
I have seen Error: Can't set headers after they are sent to the client, but I don't think I have tried to send multiple responses to the same request.
Can I know where my code went wrong?
I have seen Error: Can't set headers after they are sent to the client, but I don't think I have tried to send multiple responses to the same request.
You have, you just didn't notice it.
The onreadystatechange event is triggered four times (1-4), one time
for each change in the readyState.
Source: https://www.w3schools.com/js/js_ajax_http_response.asp
Every time onreadystatechange is triggered and the readyState isn't 4 or the status isn't 200, you try and send a response to the client with res.json(). Since you cannot send several responses to the same request, you get thrown an error.
You'd need your onreadystatechange callback to disregard any readystate that isn't 4, and then act depending on the status of the request:
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState !== 4)
return;
if (httpRequest.status == 200) {
var result = httpRequest.responseText;
console.log(result);
res.json({"status":"ok","slink":result,"nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
}
else{
res.json({"status":"error","slink":"connection error","nlink":https://abcdef.cn/?s=" + encodeURI(req.query.keyword)});
}
}
const User = require('../models/users')
const mongoose = require('mongoose')
here i am importing mongoose and user Schema it works for me
module.exports = {
checkAuthenticated:(req,res,next)=>{ // Check User Authentication
if(req.isAuthenticated()){
return next()
}
res.redirect('/login')
}
}
// If your checkAuthenticated Function is in a different File So make sure you have imported User Schema and Mongoose
I have seen related questions on stack overflow as well as other websites and no solution worked out for me. I am working on a something which makes a get request. I am using expressjs and for get request i am using https module. The api from where I am making a get request is https://api.rootnet.in/covid19-in/stats/latest . I confirmed that it returns a json object. The code is:
const express = require('express');
const app = express();
const https = require('https');
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:true}));
app.use(bodyParser.json());
app.get('/', function(req, res){
const URL = 'https://api.rootnet.in/covid19-in/stats/latest';
https.get(URL, function(response){
response.on('data', function(data){
console.log(JSON.parse(data));
});
});
});
app.listen(3000, function(){
console.log("server started");
});
the output i am getting is:
server started
undefined:1
{"success":true,"data":{"summary":{"total":343091,"confirmedCasesIndian":335359,"confirmedCasesForeign":48,"discharged":180013,"deaths":9900,"confirmedButLocationUnidentified":7684},"unofficial-summary":[{"source":"covid19india.org","total":344015,"recovered":180331,"deaths":9920,"active":153721}],"regional":[{"confirmedCasesIndian":41,"confirmedCasesForeign":0,"discharged":33,"deaths":0,"loc":"Andaman and Nicobar Islands","totalConfirmed":41},{"confirmedCasesIndian":6456,"confirmedCasesForeign":0,"discharged":3316,"deaths":88,"loc":"Andhra Pradesh","totalConfirmed":6456},{"confirmedCasesIndian":91,"confirmedCasesForeign":0,"discharged":7,"deaths":0,"loc":"Arunac
SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at IncomingMessage.<anonymous> (C:\Users\sasmit\Desktop\covid 19\testapp.js:15:24)
at IncomingMessage.emit (events.js:315:20)
at IncomingMessage.Readable.read (_stream_readable.js:506:10)
at flow (_stream_readable.js:1006:34)
at resume_ (_stream_readable.js:987:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
seems like it is not able to parse the entire file.
It's because the response is sent in chunks. After each chunk the data event is emitted. But it doesn't mean the response is fully sent. To make sure the reponse is complete, you need to use end event and parse the reponse then:
const URL = 'https://api.rootnet.in/covid19-in/stats/latest';
let result = '';
https.get(URL, function(response){
response.on('data', function(data){
result += data;
});
response.on('end', function() {
console.log(JSON.parse(result));
});
});
When you try to parse it as JSON it is converted to a string, which is empty, So, you can give this a try
app.get('/', function(req, res){
var URL = 'https://api.rootnet.in/covid19-in/stats/latest';
https.get(URL, function(res){
var json = '';
res.on('data', function(data){
json += data;
});
res.on('end', function(){
var response = JSON.parse(json);
console.log(" JSON Parserd ", response.success);
});
}).on('error', function(e){
console.log("Error occured while parsing ", e);
});
});
I am new in NodeJS, and I am working an an example:
function test(req,res){
var path = urls[Math.floor(Math.random()*urls.length)];
console.log("try to redirect to:"+path);
http.get(path,function(res_server){
//how to send the data from res_server to res
});
}
And the urls is an array of url.
I wonder how can I send the data from the res_server to the original client response?
BTW, the url maybe http or https.
update
var urls=["url1","url2","url3"];
var path = urls[Math.floor(Math.random()*urls.length)]; // find an random item from the array
update:2
Fine, this is the complete simple test script:
var http=require("http");
http.createServer(function(req, res1) {
var url = 'http://www.google.com.hk/images/srpr/logo11w.png';
var hp=require("http");
hp.get(url, function(res2) {
res2.pipe(res1);
});
}).listen(3000);
It works, but if you change http://www.google.com.hk/...logo..png to https:/www.google.....png
It will throw error:
http.js:1840
throw new Error('Protocol:' + options.protocol + ' not supported.');
^
Error: Protocol:https: not supported.
at Object.exports.request (http.js:1840:11)
at Object.exports.get (http.js:1847:21)
at Server.<anonymous> (C:\Users\maven\Desktop\t.js:6:6)
at Server.EventEmitter.emit (events.js:98:17)
at HTTPParser.parser.onIncoming (http.js:2108:12)
at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:121:23)
at Socket.socket.ondata (http.js:1966:22)
at TCP.onread (net.js:525:27)
Change var http = require('http'); to var http = require('https');
I do not fully understand your example. Looks strange to me. However best would be to pipe the request response into the server response:
http.createServer(function(req, res1) {
var path = url.format({
protocol: 'http:',
host: 'www.google.com'
});
http.get(path, function(res2) {
res2.pipe(res1);
});
}).listen(3000);