The closest issue I've found to mine is here. I believe I'm getting this error from how my .end() calls are set up. Here's the code we're working with:
app.get('/anihome',function(req,res){
var context = {};
function renderPage(context) {
res.render('anihome',context);
}
function addRequestToPage(text) {
context.data = text.toString('utf8');
context.info = JSON.parse(text);
return context;
}
function addAnimeToPage(text) {
context.anime = JSON.parse(text);
return context;
}
function addAnimeRequest(context) {
var options2 = {
host: 'anilist.co',
path: '/api/anime/20631?access_token=' + context.info.access_token,
method: 'GET'
};
https.request(options2, function(restRes) {
restRes.on('data',function(jsonResult) {
//context.anime = JSON.parse(jsonResult);
//console.log(JSON.parse(jsonResult));
console.log(context);
renderPage(context);
});
}).end();
}
function addHeaderRequest(context) {
var options = {
host: 'anilist.co',
path: '/api/auth/access_token?grant_type=client_credentials&client_id='
+ clientID + '&client_secret=' + secretKey,
method: 'POST'
};
https.request(options, function(restRes) {
restRes.on('data', function(jsonResult) {
context = addRequestToPage(jsonResult);
addAnimeRequest(context);
});
}).end();
}
addHeaderRequest(context);
});
I've tried setting up one of the .end()s with a callback, .end(addAnimeRequest(context));, which leaves me with a socket hang up error, so presumably something in my addAnimeRequest function is taking too long?
Is there a better way to make multiple requests to the same website with different options? I'm pretty new to Node.js.
The data event can be emitted more than once. You would need to add a listener for the end event and then pass in all of your data. Example:
https.request(options2, function(restRes) {
var buf = ''
restRes.on('data',function(jsonResult) {
//context.anime = JSON.parse(jsonResult);
//console.log(JSON.parse(jsonResult));
buf += jsonResult
});
restRes.on('end', function() {
// TODO JSON.parse can throw
var context = JSON.parse(buf)
renderPage(context)
})
}).end();
Related
I'm running a Vue script with a text box and submit button, I'm calling an api to POST what I write in the textbox to the api and to return information back from the API, I'm getting this error mentioned in the title eventhough I've written the Javascript functions in vue as it should be?
With the script I'm first setting up a new XMLHttpRequest, initiating the header and api key for both GET and POST methods. I've then created 2 functions to get the data from the textbox and send them to the API, then making another button with the other function to send back the data.
I went through this approach because I kept getting a CORS issue and the API needed me to declare an access control origin header, is there anything I've done wrong with this code? Any help would be greatly appreciated
<script>
export default {
name: 'ProperForm'
}
methods: {
StartClient: function () {
this.get = function(Url, Callback){
var aHttpRequest = new XMLHttpRequest();
aHttpRequest.onreadystatechange = function() {
if (aHttpRequest.readyState == 4 && aHttpRequest.status == 200)
Callback(aHttpRequest.responseText);
}
aHttpRequest.open("GET", Url, true);
aHttpRequest.setRequestHeader("X-Api-Key", "eVnbxBPfn01kuoJIdfgi46TiYNv8AIip1r3WbjsX");
aHttpRequest.send(null);
}
this.post = function(Url, message, Callback) {
var aHttpRequest = new XMLHttpRequest();
aHttpRequest.onreadystatechange = function() {
if (aHttpRequest.readyState == 4 && aHttpRequest.status == 200)
Callback(aHttpRequest.responseText);
}
aHttpRequest.open("POST", Url, true);
aHttpRequest.setRequestHeader("x-api-key", "eVnbxBPfn01kuoJIdfgi46TiYNv8AIip1r3WbjsX");
aHttpRequest.send(message);
}
}
var client = new StartClient();
submitData: function () {
document.getElementById('inputBox').disabled = true;
var targetInputButton = document.getElementById("inputBox").value;
var message = '{"targetInputButton":"' + targetInputButton + '"}';
client.post('https://le75bkfcmg.execute-api.eu-west-2.amazonaws.com/dev/start-trace', message, function(response) {
document.getElementById('jobId').innerHTML = response;
});
}
sendBackData: function () {
var jobId = document.getElementById("jobId").innerHTML;
var message = '{"jobId":"' + jobId + '"}';
client.post('https://le75bkfcmg.execute-api.eu-west-2.amazonaws.com/dev/check-trace', message, function(response) {
document.getElementById('report').innerHTML = response;
});
}
}
</script>
New way I wrote var client:
StartClient: function () {
var client
},
You need put your methods object inside export and split the methods to comma
<script>
export default {
name: 'name',
methods:{
foo(){
},
bar(){
}
}
}
UPD: var client = new StartClient();
defined outside the method
I'm adding a contact me section to a website. I want to be able to send the data from the forms with JS, and then receive and do something with the data with Node. I understand that there are frameworks and libraries that can handle this stuff, but I would like to build it from scratch so that I have a better understanding of what is happening.
I currently have a section of JS (see below) that is taking the form data, and sending it as a POST request to the node script, but I can't seem to wrap my head around what is happening with node, or how to receive the data with the node script. Any help in pointing me in the right direction is greatly appreciated.
const name = $(".name");
const email = $(".email");
const message = $(".message");
const submitButton = $(".submitButton");
const nameRegex = /([a-zA-Z\s-])/g;
const emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/g;
const messageRegex = /([a-zA-Z\s.,?!$%&])/gm;
const url = "../node/contactMeSubmissionHandler.js"
submitButton.click(function(){
let nameContents = name.val().match(nameRegex).join("");
let emailContents = email.val().match(emailRegex).join("");
let messageContents = message.val().match(messageRegex).join("");
// if (emailRegex.test(emailContents) == true) {
// let emailValid = emailContents;
// } else {
// console.log("Email is invalid");
// };
const data = {
email: emailContents,
name: nameContents,
message: messageContents
}
$.post(url, data, function(data, status){
console.log(`${data} and status is ${status}`);
})
})
I like to write from scratch too. Here is working code which is called from a command line to get a token.
// clientEx.js
var http = require('http');
var fs = require('fs');
const _SERVER = "dcsmail.net"; /* dcsmail.net */
// Callback function is used to deal with response
//
var callback = function (response)
{
// update stream with data
var body = '';
response.on('data', function(data) {
body += data;
});
response.on ('end', function()
{
// Data received completely.
fs.writeFileSync ("temp.lst", body, 'utf8');
// console.log ("clientEx.js received: " + body);
});
}
if ((process.argv[2] == null) || (process.argv[3] == null) || (process.argv[4] == null) || (process.argv[5] == null))
{
console.log ("clientEx.js usage:<user email> <user password> <destination> <GUID>");
}
else
{
var Ef_email = encodeURI (process.argv[2]);
var Ef_pass = encodeURI (process.argv[3]);
var Ef_dest = encodeURI (process.argv[4]);
var Ef_guid = encodeURI (process.argv[5]);
var post_data = ("f_email=" + Ef_email +
"\&" + "f_pass=" + Ef_pass +
"\&" + "f_dest=" + Ef_dest +
"\&" + "f_guid=" + Ef_guid);
// Options to be used by request
var options = {
host: _SERVER,
port: '80',
path: '/DCSM/tokenP10.php',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength (post_data)
}
};
// console.log ("clientEx.js using " + _SERVER + ":" + options.port + options.path);
// request the token from the host
try
{
var req = http.request (options, callback);
req.write (post_data);
req.end();
}
catch (error)
{
fs.writeFileSync ("temp.lst", "Host access failed\n", 'utf8');
}
}
You should be able to adapt that to your needs.
Use this code to create a server and check the log in console for different request attributes.
const http = require('http');
http
.createServer((request, response) => {
console.log(request);
response.end();
})
.listen(3000);
Make GET and POST request to http://localhost:3000/ and look for method, headers etc.
See more here and here.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
So, I have an array of some values. I'd like to send these values to www.example.com. I have to send only one value per request.
I am using for this task http.request in node.js:
var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];
function requestSender(data, callback)
{
var post = querystring.stringify({
data: data
});
var options = {
hostname: 'www.example.com',
port: 80,
path: '/upload',
method: 'POST'
};
var req = https.request(options, function(res)
{
res.setEncoding('utf-8');
res.on('data', function(data)
{
callback();
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(post);
req.end();
}
To send requests one by one I am using function, that takes an array of functions and recursively adds next function as the callback to previous:
function stack(arr)
{
var newArr = arr.slice(1);
arr[0](function()
{
if (typeof newArr[0] == 'function') stack(newArr);
});
}
And to compile all this staff into one, I am using the following code:
var functionsArr = [];
for (i in myArr)
{
functionsArr.push(function(callback)
{
var value = myArr[i];
requestSender(value, callback);
});
};
stack(functionsArr);
But actually, this does not work: all requests are sent in 1 millisecond, and after that callbacks are listening while responses are recieved. But it should not! I have put callback() in http.request(options, callback)!! How does it happen?
So my questions are:
1) How can I send http requests strictly one by one in node.js?
2) Why does not my solution work?
Check out the async library, specifically the mapSeries method.
Your callback is being called when the data is received, not when the request is finished.
I see I'm late, but anyway:
When putting a function in a loop, or recursion, variables in closures are evaluated at the time the function is executed, not when it is created. So
for (i in [1, 2, 3]) {
setTimeout(function() {
console.log(i);
}, 1000);
}
returns
3
3
3
but
for (i in [1, 2, 3]) {
setTimeout(function(i) {
return function() {
console.log(i);
};
}(i), 1000);
}
will correctly give you
1
2
3
This is why it is generally not recommended to put function definitions in a loop.
Anyway, here is corrected code for you, note it console.logs everything in correct order:
var http = require('http');
var querystring = require('querystring');
var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];
function requestSender(d, callback)
{
var post = querystring.stringify({
data: d
});
var options = {
hostname: 'www.example.com',
port: 80,
path: '/upload',
method: 'POST'
};
var req = http.request(options, function(res)
{
res.setEncoding('utf-8');
res.on('data', function(data)
{
console.log(d);
console.log(data);
callback();
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
req.write(post);
req.end();
}
function stack(arr)
{
var newArr = arr.slice(1);
arr[0](function(arg) {
return function() {
if (arg.length > 0)
stack(arg);
};
}(newArr));
}
var functionsArr = [];
for (i in myArr)
{
functionsArr.push(function(i) {
return function(callback) {
var value = myArr[i];
requestSender(value, callback);
};
}(i));
}
stack(functionsArr);
You could try something like this:
var myArr = [1,2,3,4,5,6,7,8,9,10,11,12];
var counter = -1;
function function requestSender(data)
{
var post = querystring.stringify({ data: data });
var options =
{
hostname: 'www.example.com',
port: 80,
path: '/upload',
method: 'POST'
};
var req = https.request(options, sendNextData);
req.on('error', function(e)
{
console.log('problem with request: ' + e.message);
});
req.write(post);
req.end();
}
function sendNextData()
{
if(++counter < myArr.length)
{
requestSender( myArr[ counter ] );
}
}
sendNextData();
I'm building an extension to get the POST request in Firefox. I read through the documentation for intercepting page loads and HTTP observers, but still couldn't manage to get the specific POST data on a page load (ex: data1=50&sdata2=0&data3=50).
I looked into TamperData's code, and found that they used stream.available() and stream.read(1). However, I couldn't get these commands to work with my code.
Currently my code looks like this:
var ObserverTest = {
observe: function(subject, topic, data) {
if (topic == 'http-on-modify-request') {
var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
}
if (topic == "http-on-examine-response") {
var newListener = new TracingListener();
subject.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = subject.setNewListener(newListener);
}
},
register: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.addObserver(ObserverTest, "http-on-modify-request", false);
observerService.addObserver(ObserverTest, "http-on-examine-response", false);
},
unregister: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.removeObserver(ObserverTest, "http-on-modify-request");
observerService.removeObserver(ObserverTest,"http-on-examine-response");
}
}
window.addEventListener("load", ObserverTest.register, false);
window.addEventListener("unload", ObserverTest.unregister, false);
//Helper function for XPCOM instanciation (from Firebug)
function CCIN(cName, ifaceName) {
return Cc[cName].createInstance(Ci[ifaceName]);
}
// Copy response listener implementation.
function TracingListener() {
this.originalListener = null;
this.receivedData = []; // array for incoming data.
}
TracingListener.prototype = {
onDataAvailable: function(request, context, inputStream, offset, count) {
var binaryInputStream = CCIN("#mozilla.org/binaryinputstream;1", "nsIBinaryInputStream");
var storageStream = CCIN("#mozilla.org/storagestream;1", "nsIStorageStream");
var binaryOutputStream = CCIN("#mozilla.org/binaryoutputstream;1", "nsIBinaryOutputStream");
var stream = Components.classes["#mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
stream.init(binaryInputStream);
binaryInputStream.setInputStream(inputStream);
storageStream.init(8192, count, null);
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), offset, count);
},
onStartRequest: function(request, context) {
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode)
{
// Get entire response
var responseSource = this.receivedData.join();
this.originalListener.onStopRequest(request, context, statusCode);
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
}
}
First of all, the "http-on-examine-response" and TracingListener isn't required at all. This stuff would have merit if you wanted to do something with the response, but you're after data in the request, so topic == 'http-on-modify-request' it is.
The following function (untested, but copied from one of my extensions and cleaned up a bit) demonstrates how to get post data. The function is assumed to be called from http-on-modify-request.
const ScriptableInputStream = Components.Constructor(
"#mozilla.org/scriptableinputstream;1",
"nsIScriptableInputStream",
"init");
function observeRequest(channel, topic, data) {
let post = null;
if (!(channel instanceof Ci.nsIHttpChannel) ||
!(channel instanceof Ci.nsIUploadChannel)) {
return post;
}
if (channel.requestMethod !== 'POST') {
return post;
}
try {
let us = channel.uploadStream;
if (!us) {
return post;
}
if (us instanceof Ci.nsIMultiplexInputStream) {
// Seeking in a nsIMultiplexInputStream effectively breaks the stream.
return post;
}
if (!(us instanceof Ci.nsISeekableStream)) {
// Cannot seek within the stream :(
return post;
}
let oldpos = us.tell();
us.seek(0, 0);
try {
let is = new ScriptableInputStream(us);
// we'll read max 64k
let available = Math.min(is.available(), 1 << 16);
if (available) {
post = is.read(available);
}
}
finally {
// Always restore the stream position!
us.seek(0, oldpos);
}
}
catch (ex) {
Cu.reportError(ex);
}
return post;
}
Depending on your use case, you might want to check if the us instanceof e.g. nsIMIMEInputStream or nsIStringInputStream for special handling or fast-paths...
You'd call it from your observer like:
observe: function(subject, topic, data) {
if (topic == 'http-on-modify-request') {
observeRequest(subject, topic, data);
}
},
I have this:
var MyObject = {};
MyObject.doStuff = function(someParam) {
var webdav = new Webdav("addr","port");
var handler = {
onSuccess: MyObject.Success,
onError: MyObject.Fail
}
webdav.PUT(handler, filename, options);
}
MyObject.Success = function(result) {
alert('status ' + result.status + result.statusstring);
}
I'm using exo platform javascript library for webdav access (if it matters)
The handler I'm creating will call MyObject.Success if webdav.PUT is done succesfully. How can i send the someParam to that function too?
Put in another way, after a successful or failed operation, I'm interested in doing something with the someParam, depending of the result.
This may be what you'r looking for:
javascript callback function and parameters
or maybe:
http://onemarco.com/2008/11/12/callbacks-and-binding-and-callback-arguments-and-references/
var someParam = 'foo';
var handler = {
onSuccess: function(result) {success(result, someParam);},
onError: function() { fail(); }
}
You should look into javascript objects, and try to contain the code within one scope. Something like this:
var MyObject = {
var doStuff = function(someParam) {
var webdav = new Webdav("addr","port");
var handler = {
onSuccess: function(result) {success(result, someParam);},
onError: function() { fail(); }
}
webdav.PUT(handler, filename, options);
}
var success = function(result, someParam) {
alert('status ' + result.status + result.statusstring);
}
var fail = function() {}
this.doStuff = doStuff;
}
var myObj = new MyObject();
myObj.doStuff(param);
One simple way to do it, taking advantage of JavaScript closures:
var handler = {
onSuccess: function(result) { MyObject.Success(result, someParam); },
onError: MyObject.Fail
}