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.
Related
I am intercepting an XMLHttpRequest and preventing it from making a network call.
There are third-party scripts that I want to prevent from performing retries when the XHR doesn't respond, and therefore I'd like to mimic a response with an OK status (i.e. readyState = 4). Is there a way to make this happen?
(function(XHR) {
var open = XHR.prototype.open;
var send = XHR.prototype.send;
var abort = XHR.prototype.abort;
XHR.prototype.open = function(method, url, async, user, pass) {
this._url = url;
open.call(this, method, url, async, user, pass);
};
XHR.prototype.send = function(data) {
var url = this._url;
try {
var canSend = checkCanSend(url);
if (!canSend) {
// TODO respond with OK status
this.abort();
} else {
send.call(this, data);
}
} catch (err) {
console.error(err);
}
}
XHR.prototype.abort = function() {
console.log('aborted ' + this._url);
abort.call(this);
}
})(XMLHttpRequest);
I am very new with node js and decided to learn how to secure api keys, i've looked everywhere but can't find a example. But i found some that suggest the only way is to do a server side api request.
I am using openweathermap api for this code, i get the expected data back as a response in chrome network tab but i have questions regarding it.
How do i use the response data (e.g getting the current weather, temp) ?
Is this the proper way on doing a server side api request in node.js?
http.createServer(function(req, res) {
if (req.url === '/') {
res.writeHead(200, {"Content-Type": "text/html"});
fs.createReadStream(__dirname + '/index.html').pipe(res);
} else if (req.url === '/getweather') {
var weatherApiURL = 'https://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=<API KEY>';
request(weatherApiURL, function (error, response, body) {
if (error) {
res.writeHead(500, 'Weather API request failed', {'content-type': 'text/plain'});
res.end();
} else {
res.writeHead(200, {'content-type': 'application/json'});
res.end(body);
}
});
} else {
res.end('not found')
}
}).listen(8080);
Front:
function requestWeatherData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getweather', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
console.log(this.responseText);
};
xhr.send();
};
Thank you in advanced!!
Part 1: How to use the data.
The first thing you'll want to do is to check whether the request succeeded
if (this.status !== 200) {
// The request did not work.
throw new Error('Cannot use data.');
}
Once the requset status has been verified you need to 'parse' the response.
const weatherData = JSON.parse(this.responseText);
// Lets see the js object:
console.log(weatherData);
Now you can do whatever you need with the data.
The full example:
function requestWeatherData() {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getweather', true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
if (this.status !== 200) {
// The request did not work.
throw new Error('Cannot use data.');
}
const weatherData = JSON.parse(this.responseText);
// Lets see the js object:
console.log(weatherData);
};
xhr.send();
};
Part 2: Is there a proper way of doing this?
Now, I don't not know enough about this to say definitely, however, here are some concerns that you may want to think about.
Most APIs have rate limits, meaning you probably want to try to 'cache' the requests somewhere to reduce the need to 'poll' the APIs
Other people could use your exposed url in their application.
Writing all of the routes as you are currently will become a real headache for larger applications, I can recommend express from experience for small to medium applications.
I already tried getting the file with this Code, the problem is, the code works with http requests but not with https request (which is what i need)
function isThere(url) {
var req = new XMLHttpRequest(); // XMLHttpRequest object
try {
req.open("HEAD", url, false);
req.send(null);
return req.status == 200 ? true : false;
} catch (er) {
return false;
}
}
function setUser() {
var user = document.getElementById("userName").value;
if (isThere("https://dev.sentinex.de/ulogv2/" + user) == true) {
alert("File exists!");
} else {
alert("File doesn't exist!");
}
}
Does anyone know how i can change the code to work with HTTPS Requests or how i could rewrite it so that i could get HTTPS Requests?
PS: I am just requesting from my own domain - so no other domains for requests are needed.
Please posts the domain of the resource that executes the code.
If you are on Http. You must use a bypassSecurityTrust
I am new to node.js and trying to use my basic API and call the correct router.get function in my route file.
I have a basic clientside javascript for the ajax post:
console.log("main.js loaded");
var form = document.getElementById('addUserForm');
form.addEventListener("submit", function(event){
event.preventDefault();
var username = document.getElementById('username').value;
var fd = new FormData();
fd.append('username', username);
window.ajaxCall.call("POST", "localhost:3000/api/users/add", fd, function(responseText){
// var response = JSON.parse(responseText);
console.log(response);
});
});
In this client side javascript I am using a custom xmlhttprequest library - I will provide the code below the whole question ( maybe the error for node js is there )
** UPDATE ** When I change the ajax call url to : /api/users/add or http://localhost:3000/api/users/add I get the following error : POST http://localhost:3000/api/users/add 404 (Not Found)
Here is my route file :
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/users', function(req, res) {
var Users = require('../models/users'); // inkludiert das Users model
var data; // undefined data variable
Users.getData(function(err, result) { // ruft die getData Funktion vom Users Model auf
// TODO: Error handling.
data = result;
render(data); // ruft die render Funktion auf und übergibt das Resultobjekt
});
function render(data){
res.send(data);
}
});
router.get('/api/users/add', function(req, res){
console.log(req,res);
});
module.exports = router;
All I am trying to do is to call the router.get('api/users/add'... function in order to continue working with my api.
Now when I try to do that with my clientside javascript ajax call I get following error:
XMLHttpRequest cannot load localhost:3000/api/users/add. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
When I inspect the error it shows that the error occurs on my window.ajax call in the js file as well as in the callback function in my library.
Here is the necessary library code:
window.ajaxCall = {
call: function(RequestType, pathToFile, data, cb){
var ajax = null;
if(window.XMLHttpRequest){ //Google Chrome, Mozilla Firefox, Opera, Safari,...
ajax = new XMLHttpRequest();
}else if(window.ActiveXObject){ // Internet Explorer
try{
ajax = new ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch(e){
try{
ajax = new ActiveXObject("Msxml2.XMLHTTP.3.0");
}
catch(e){}
}
}
if(ajax!=null){
ajax.open(RequestType, pathToFile, true);
typeof data == "string" || typeof data == "array" ? ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded") : "" ;
ajax.onreadystatechange = function() {
if (ajax.readyState == 4) {
if(this.status == 200){
cb(ajax.responseText);
}
}
}
ajax.send(data);
}
},
abort: function(){
ajax.abort();
}
}
Add the protocol to your ajax call.
window.ajaxCall.call("POST", "http://localhost:3000/api/users/add", fd, function(responseText){
// var response = JSON.parse(responseText);
console.log(response);
});
Now, for the 404 part, your routes is expecting a get, but you are sending a post, change the router as follows:
router.post('/api/users/add', function(req, res){
console.log(req,res);
});
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!