I am testing ways to use a PhantomJS server with Python's Requests library.
The GET and POST requests work as expected and I can get the PhantomJS server to request any page I want and put the results to the console, but I can not figure out how to send the page content back using response.write(page.content). The request object has no text, content or usable raw content. The only way to get response.write() to work as expected is to hardcode the response content. If I add keep-alive to true the request functions hangs.
Here is my server.js
var webserver = require('webserver').create();
page = require('webpage').create();
var service = webserver.listen(8080, function(request, response) {
if (request.method == 'POST') {
console.log(request.post);
var content = '';
page.open(request.post, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
response.statusCode = 200;
response.write('Page not responding.');
} else {
content = page.content;
response.statusCode = 200;
response.write(content);
}
})
} else {
response.statusCode = 200;
console.log(request.method == 'GET' );
response.write('No URL provided');
}
response.closeGracefully();
});
The Python code is straightforward:
import requests
response = requests.post('http://127.0.0.1:8080, data='http://python.org')
The connection needs to be closed after sending data back: response.close();
Also I'd suggest using a variable in POST request, cause response.post is actually an object.
var webserver = require('webserver').create();
page = require('webpage').create();
var service = webserver.listen(8080, function(request, response) {
if (request.method == 'POST') {
var url = request.post.url;
console.log(url);
var content = '';
page.open(url, function (status) {
if (status !== 'success') {
console.log('FAIL to load the address');
response.statusCode = 200;
response.write('Page not responding.');
response.close();
} else {
content = page.content;
response.statusCode = 200;
response.write(content);
response.close();
}
})
} else {
response.statusCode = 200;
console.log(request.method == 'GET' );
response.write('No URL provided');
respone.close();
}
});
Then POST with url variable:
import requests
response = requests.post('http://127.0.0.1:8080, data = {'url':'http://python.org'})
Related
When dealing with GET requests, should I be using request.on()?
For instance, in my main.js,
var http = require('http');
var dispatcher = require('./public/javascript/dispatcher.js');
var serverPort = 8124;
http.createServer(function (request, response) {
dispatcher.deal(request, response);
}).listen(serverPort);
and in dispatcher.js, I have
module.exports = {
deal: function(request, response) {
if(request.method === "GET") { // WITHIN THIS BLOCK
var get = require('./get.js');
// Pass data to the appropriate function
get.do(request, response);
} else if(request.method === "POST") {
var qs = require('querystring');
var requestBody = '';
request.on('data', function(data) {
requestBody += data;
});
request.on('end', function() {
var formData = qs.parse(requestBody);
var post = require('./post.js');
// Pass data to the appropriate function
post.doing(request, response, formData);
});
}
} // End deal
} // End exports
So to expand on my initial question and the code I've posted, the program works fine without the request.on(). My guess is that since there's no data to wait for from a GET request, there's no need for a require.on('end', ...). Any clarifications, recommendations, or suggestions are welcome!
I am trying to understand why an ajax response would be sent when outside of a function, but not within the function. The response object is accessible within the function, but it will not send the actual response. What would cause this type of behaviour?
app.post('/login', urlencodedParser, function(req, res){
if (!req.body) return res.sendStatus(400);
var password = JSON.stringify(req.body.password);
var username = JSON.stringify(req.body.username);
//res.send('Invalid'); //This sends a response
login.login(username, password,function(err,content) {
if(err){res.send('Invalid');} //This does not send a response
else {
agent_valid = content[0].valid;
if (agent_valid === 0)
{
console.log(agent_valid); //agent_valid is appearing as 1 or 0
console.log(res); //res exists and is written to console
res.send('Invalid'); //This does not send a response
}
if (agent_valid === 1)
{
res.send('Valid'); //This does not send a response
}
}
});
});
This is the javascript sending the post request:
ajaxRequest.send(JSON.stringify({username:username, password:password}));
ajaxRequest.onreadystatechange = function() {
if(this.readyState == 4 && this.responseText == 'Invalid') {
window.alert(this.responseText)
};
if(this.readyState == 4 && this.responseText !='Invalid'){
window.alert(this.responseText)
};
}
I am new at node.js, so please be patient :)
What I need to do:
load from url Ids of users
Hit another url for every ID
What am I doing wrong?
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function (data, response) {
if (data.status == 'OK') {
users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response){
console.log(data);
});
});
}
});
The value of users is: [1,2,4,5,7,...]
Nothing in forEach is executing, why?
There is no status in data nor response so it never go inside the if block. To handle errors with node-rest-client, you have to listen to the error event:
var http = require('http');
var Client = require('node-rest-client').Client;
var client = new Client();
url = 'http://example.com/api/get-users';
client.get(url, function(data, response) {
// if there is an error, this function is not executed
var users = data.users;
users.forEach(function(item) {
newUrl = 'http://example.com/generateStats/' + item;
client.get(newUrl, function(data, response) {
console.log(data);
});
});
}).on('error', function(err) {
console.log('something is wrong: ' + err.code);
});
There is a response.statusCode though, it returns an http code like 200.
I think you need something like async
Check this answer: simplest-way-to-wait-some-asynchronous-tasks-complete-in-javascript
I've been having trouble trying to issue a CORS request via the XDomainRequest object in IE8. For my code, I need to send a POST request with some data to a server which then passes that data along through several other services. I've gotten the server to respond to and process requests and data coming from all other browsers, both by using jQuery's ajax method and by using vanilla javascript and the XMLHttpRequest object. However, after reading Mozilla's CORS documentation, Microsoft's XDomainRequest documentation, and quite a few blog posts and stack overflow questions about the latter, I can't seem to get the XDomainRequests to work. Here is the code for the XDomainRequest I'm trying to make:
Creating the request:
if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE8 & 9.
xhr = new XDomainRequest();
console.log('Generated XDomainRequest');
xhr.onprogress = function() {console.log('Progress');};
xhr.ontimeout = function() {console.log('ontimeout');};
xhr.onerror = function() {console.log('Error');};
xhr.onload = function() {console.log('Success');};
xhr.open(method, url);
console.log('Open XDomainRequest');
}
And then sending the request (which is done in another function):
if (typeof XDomainRequest != 'undefined') {
console.log('XDomainRequest');
setTimeout(function () {
console.log('Sending request');
data = 'foo=bar&baz=bat';
xhr.send(data);
}, 0);
}
I'm aware that the request can not be sent across different protocols, and I can confirm that the request is being made from HTTPS to HTTPs. However, when running the code, I receive an error generated by the XDomainRequest's error handler. When testing a GET request from a Windows XP IE8 virtual machine on virtual box, I also get an error generated by the request's error handler, but unfortunately, no indication of what failed. I know that XDomainRequest is only able to send data if the content type is of 'text/plain' and that is the type of data I have been testing it with. The relevant server code is here:
For an OPTIONS request:
var http = require('http');
var url = require('url');
var request = require('request');
var AWS = require('aws-sdk');
var path = require('path');
var fs = require('fs');
function checkOrigin(request) {
/* Function to determine if origin is greenlit for CORS
* #param request is the http request being made to the server.
* #return returns whether origin matches parent domain.
*/
var acceptableDomain = new RegExp("some_url.com");
if (acceptableDomain.test(request.headers.origin)) {
return request.headers.origin;
} else {
return null;
}
}
.
. // Unrelated code between these functions //
.
if (request.method === 'OPTIONS') {
console.log('!OPTIONS');
var headers = {};
headers["Access-Control-Allow-Origin"] = checkOrigin(request);
headers["Access-Control-Allow-Methods"] = "POST, OPTIONS";
headers["Access-Control-Allow-Credentials"] = true;
headers["Access-Control-Max-Age"] = '86400'; // 24 hours
headers["Vary"] = 'Origin';
headers["Access-Control-Allow-Headers"] = "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept";
response.writeHead(200, headers);
response.end();
}
For a GET request:
if (request.method === 'GET') {
console.log("Request received!");
var fileType = {
"html": "text/html",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"png": "image/png",
"js": "application/javascript",
"css": "text/css"};
var fileName = "some_script.js";
var filePath = path.join(process.cwd(), fileName);
var ext = fileType[fileName.split(".")[1]];
var fileStream = fs.createReadStream(filePath);
console.log(ext);
response.writeHead(200, {'content-type':ext});
fileStream.pipe(response);
//Maybe need return here?
}
For a POST request:
if (request.method == 'POST'
&& (contenttype != undefined)
&& ((contenttype.indexOf('application/json') != -1)
|| (contenttype.indexOf('application/x-www-form-urlencoded') != -1)
|| (contenttype.indexOf('text/plain')!= -1))) {
var message = '';
var body = "";
console.log("Post received!");
if((contenttype.indexOf('application/json') != -1)
|| contenttype.indexOf('application/x-www-form-urlencoded') != -1) {
// Once the request posts data, we begin parsing that data and add it to 'body.'
request.on('data', function (chunk) {
var parsedChunk = JSON.parse(chunk);
body += parsedChunk;
});
request.on('end', function () {
console.log('Data:' + body.replace(/,/g, '\n'));
});
} else {
message = 'POST Received';
response.write(message);
}
response.writeHead(200, {'content-length': message.length,
'Access-Control-Allow-Origin': checkOrigin(request),
'Access-Control-Allow-Headers': "X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept",
'Access-Control-Allow-Methods': "POST, OPTIONS",
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': '86400',
'Vary':'Origin',
'content-type': 'text/plain'});
//response.write('POST Received');
response.end();
Does anyone have any ideas as to what might be going wrong when making the XDomainRequest? Let me know if there's any other information I can include that might help!
Hi all I am trying to turn caching off by
Adding a random value to the query string component of the URL sent with the request message.
I have a server that sends the etag as a string to my client and I want to make sure no caching is going on I already setRequestHeaders but i'm also supposed to add an http request similar to POST /message?x=0.123456789 HTTP/1.1
this is my client code
<html>
<header><title>This is title</title></header>
<body>
<span id="ajaxButton" style="cursor: pointer; text-decoration: underline">
Make a request
</span>
<script type="text/javascript">
(function() {
var httpRequest;
var x= Math.random();
document.getElementById("ajaxButton").onclick = function() { makeRequest('http://localhost:5000/'); };
function makeRequest(url) {
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
try {
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e) {
try {
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) {}
}
}
if (!httpRequest) {
alert('Giving up :( Cannot create an XMLHTTP instance');
return false;
}
httpRequest.onreadystatechange = alertContents;
httpRequest.open('GET', url, true);
//httpRequest.setRequestHeader("pragma", "no-cache");
//httpRequest.setRequestHeader("Cache-Control", "no-cache", "no-store");
httpRequest.send();
}
function alertContents() {
if (httpRequest.readyState === 4) {
if (httpRequest.status === 200) {
var etagString = httpRequest.responseText;
alert(etagString);
} else {
alert('There was a problem with the request.');
}
}
}
})();
</script>
</body>
</html>
edit for adding errors
XMLHttpRequest cannot load http://localhost:5000/?_0.1909303846769035. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
using node.js I run the server using main.js which is
var http = require('http');
var domain = require('domain');
var root = require('./root'); // do I have to replace root w/ message
var image = require('./image'); // for better readability?
function replyError(res) {
try {
res.writeHead(500);
res.end('Server error.');
} catch (err) {
console.error('Error sending response with code 500.');
}
};
function replyNotFound(res) {
res.writeHead(404);
res.end('not found');
}
function handleRequest(req, res) {
console.log('Handling request for ' + req.url);
if (req.url === '/') {
root.handle(req, res);
}
if (req.url === '/image.png'){
image.handle(req, res);
}
else {
replyNotFound(res);
}
}
var server = http.createServer();
server.on('request', function(req, res) {
var d = domain.create();
d.on('error', function(err) {
console.error(req.url, err.message);
replyError(res);
});
d.run(function() { handleRequest(req, res)});
});
function listen(){
server.listen(5000);
}
root.init(listen);
and inside root.js is
var http = require('http');
var response = require('./response');
var body;
var etag;
exports.handle = function(req, res) {
if (req.headers['if-none-match'] === etag) {
console.log('returning 304');
return response.replyNotModified(res);
}
res.writeHead(200, {'Content-Type': 'text/plain',
'Content-Length': body.length,
"Access-Control-Allow-Origin":"*",
"Access-Control-Allow-Headers":"X-Requested-With",
'ETag' : etag
});
res.end(body);
}
exports.init = function(cb) {
require('fs').readFile('app.html', function(err, data) {
if (err) throw err;
etag = response.generateETag(data); //
body = etag;
console.log("init");
cb();
});
}
/*function generateETag(buffer) {
var shasum = require('crypto').createHash('sha1');
shasum.update(buffer, 'binary');
return shasum.digest('hex');
console.log(shasum.digest('hex'));
}
var replyNotModified = function(res) {
res.writeHead(304);
res.end();
};*/
the errors are in
So, the error that you're getting is to do with cross-origin resource sharing, which has nothing to do with caching or query strings. It looks like you're trying to make AJAX calls from a file:// url, which you can't do.
If you serve the page in question from your Node.js app, that message should go away.
If you can't do that, set up that app to send CORS headers. You can read about CORS in detail at MDN, but the short version is that you need to send a header that looks like this (where otherdomain.com is where the Web page is hosted):
Access-Control-Allow-Origin: http://otherdomain.com
Note that you'll still have to serve the page over HTTP; to my knowledge you can't do AJAX at all from a page loaded via a file:// URL.
You could add '_=' + new Date().getTime(); to the query string of the url. Since it isn't clear whether the url already has a query string attached to it, it's hard to give a more complete answer. It'd be either url += '?_=' + new Date().getTime(); or url += '&_=' + new Date().getTime();.
I'll leave this answer here because it seems to answer the question that the OP was asking. But the solution to the problem the OP was experiencing is Adam Brenecki's answer below.