XHR responseText is empty string - javascript

Html Page:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>xhr</title>
</head>
<body>
<script>
var xhr_test = new XMLHttpRequest();
xhr_test.open("GET","xhrtest",true);
xhr_test.send();
alert(xhr_test.responseText);
</script>
</body>
</html>
The main.py file:
import webapp2
from handlers import cookies,pages
application = webapp2.WSGIApplication([
('/xhr',pages.XHR),
('/xhrtest', cookies.XHRTest)
],
debug=True)
The Request handlers:
class XHRTest(webapp2.RequestHandler):
def get(self):
self.response.write('0')
and,
class XHR(webapp2.RequestHandler):
def get(self):
f = open('static/html/xhr.html','r')
self.response.write(f.read())
Now, when I hit upon the url localhost:8080/xhrtest the browser promptly shows the response 0 as the page's content.
Hitting the url localhost:8080/xhr which indirectly hits /xhrtest, pops up an empty string in the alert box (the responseText is an empty string) but checking chrome's response tab under the network tab, I can see that the request's response is 0.
So why is xhr_test.responseText not able to display the same response?

The call to send is asynchronous (you've set the 'async' parameter to true), which means that your alert is happening immediately, before the request finishes.
You should add an event-listener to xhr.onreadystatechange and use the response within that.
Changing the 'true' to 'false' would make this simple example work, but is not a good idea in the general case.
The MDN page on Ajax explains how XMLHttpRequest should be used.

Related

Removing image accessibility

I have a web page that is feed from flask a link to a picture. I have it so the image disappears after a second or two. However, if you look at the page source you can still get the picture, via finding the exact url for the picture. How do I remove access to the url or remove the picture from the url so that the user can no longer view the image after it disappears.
Html Page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function () {
var c = document.getElementById('image');
console.log(typeof(c));
setTimeout(function () {
$('#des').css('visibility', 'hidden');
}, 1750);
fs.unlink("{{ url_for('static', filename = '1l1l1lI1lIlIlIlI1IlI1II1l1.jpg') }}");
removeElement(c)
storage.clear(c);
sessionStorage.clear(c);
});
</script>
<div id="des">
<img id="image" src="{{ url_for('static', filename = '1l1l1lI1lIlIlIlI1IlI1II1l1.jpg') }}"/>
</div>
</body>
</html>
main.py
from datetime import datetime
from flask import make_response
from functools import wraps, update_wrapper
from flask import Flask, request, session, g, redirect, url_for, abort, \
render_template, flash
app = Flask(__name__) # create the application instance
app.config.from_object(__name__) # load config from this file , flaskr.py
def nocache(view):
#wraps(view)
def no_cache(*args, **kwargs):
response = make_response(view(*args, **kwargs))
response.headers['Last-Modified'] = datetime.now()
response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '-1'
return response
return update_wrapper(no_cache, view)
#app.route(r'/')
#nocache
def landingpage():
return render_template('index.html')
if __name__ == '__main__':
app.run()
First and foremost your images won't be protected if the user tries hard enough. You cannot prevent them for taking screen shots or anything of the sort.
There are several ways to help "prevent" them from getting your images:
You can load your image via ajax:
<script>
$('#my_image').attr('src', {{ url_for('image_path') }});
</script>
You can also load via an expiring hash key (database driven). So create a table with a mapping to the file name and then load the image using a route by passing in the hash key. If they try to open the image from a debugger, it can say it was expired and won't load the image.
def get_image(self, hash_key):
my_image = self.image_engine.get_image(hash_key)
if my_image.get('is_viewed') == 0:
real_key = my_image.get('real_key')
root_path = os.path.join(self.image_path, real_key)
# call a function to set the image as "viewed"
return send_from_directory(root_path, '{}.png'.format(real_key))
else:
return render_template('404.html')
Doing it like this means you can add expiration to the hash key, or even a flag that says it was already viewed and then render nothing, or a 404 if they try to load it again.
This method does require a lot more database calls, but if you are out to protect your images, you will have to look at some performance options.

OnBefore Unload is working I guess but I recieve data only 50% of times

this is the simplest code I have written and backend there is simple php api which recieves a get paramter and stores it.
<!DOCTYPE html>
<html>
<head>
<title>
test beforeunload
</title>
</head>
<body>
<script type="text/javascript">
function httpGetAsync(data){
theUrl='http://niteshchaudhry.com/ajay/api.php?name='+data;
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET",theUrl, true);
xmlHttp.send(null);
}
function fireAsap(){
var elem=document.createElement('script');
elem.src='http://niteshchaudhry.com/ajay/api.php?name='+new Date();
document.getElementsByTagName('body')[0].appendChild(elem);
}
window.onbeforeunload = function(e) {
fireAsap();
var dialogText = 'Dialog text here';
e.returnValue = dialogText;
return dialogText;
};
</script>
</body>
</html>
problem is I have observed in database which shows me 1 entry after two refresh or unloads irrespective of which function I use fireasap or httpgetAsync. can anyone explain what is wrong or what can be done to get the data every refresh or unload
Have a look at navigator.sendBeacon(), it's designed for exactly this use case.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
The problem with regular requests is that there's no guarantee that the browser actually manages to send the request before the page gets unloaded, it's done on a 'best effort' basis. navigator.sendBeacon() tells the browser to perform a request in the background, separately from the actual page instance. These requests are always POST requests so you'll have to change your server end-point to act on POST instead of GET requests.
navigator.sendBeacon() is not yet universally supported so you'll need to use a regular request as a fallback solution.

JavaScript - order of execution of <script> tags

As stated in this SO question and many other similar, the order of execution of <script>s on the page should be the same as the order in which these tags are defined in the html document.
I created a simple Java (server side) test app that allows to execute a request and wait specified period of time before returning a response (relevant code snippet at the bottom of this question). It has a simple API:
http://localhost:8080/latency?time=XXX&response=YYY
Example request that will return console.log('done') after one second (1000ms):
http://localhost:8080/latency?time=1000&response=console.log(%27done%27)
Next I created a simple index.html page (served by nginx):
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>test order</title>
</head>
<body>
<script type="text/javascript" async=false src="http://localhost:8080/latency?time=1000&response=console.log(%27done1%27)"></script>
<script type="text/javascript" async=false src="http://localhost:8080/latency?time=100&response=console.log(%27done2%27)"></script>
<script type="text/javascript" async=false src="http://localhost:8080/latency?time=10&response=console.log(%27done3%27)"></script>
<script>console.log('static script without "src" attr');</script>
</body>
</html>
According to everything I read so far I expected the order of console output to be:
done1
done2
done3
static script without "src" attr
This is what I got (Firefox 51 dev console):
This is just the opposite order of what I expected to get. Am I missing something? Is there a way to execute these scripts in the desired order (i.e. in the order they are defined in HTML)?
As a reference, the Java part on a server side:
private String latency(HttpServletRequest request) {
long millis = Long.parseLong(request.getParameter("time"));
String response = request.getParameter("response");
try {
Thread.sleep(millis);
return (response != null) ? response : "";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
async is a boolean attribute. Its value does not matter. Remove the attribute.

very simple XMLHttpRequest not working

I'm practicing XmlHttpRequest, and I'm trying to run basic Javascript that will get the data stored in a text file. Here's my Javascript:
var xml = XMLHttpRequest();
xml.open("GET", "setverfile.txt",true);
xml.send(null);
alert(xml.responseText);
And my html:
<!DOCTYPE html>
<html>
<head>
<title>XMLHttpRequest</title>
</head>
<body>
<script src="XMLHttpRequest.js" type="text/javascript"></script>
</body>
</html>
textfile:
This is a textfile resideing on a server
When I try running the code, nothing happens. What am I doing wrong?
Seems like you're missing your [onreadystatechange]
When you send an Ajax request, you need to listen for the state change.
Your code is asynchronous, hence listening for state change is required.
xml.open("GET", "setverfile.txt",true); // The true parametter is for async
If you did
xml.open("GET", "setverfile.txt",false); // The false parametter is for non async.
Then your code should work.
In my testing, it seems that all you were missing was the new keyword:
var xml = new XMLHttpRequest();

Can't do an AJAX call with Python and Django

I am still learning to do javascript and django and yesterday I tried to do a simple hello world ajax exercise.
Server logs show that python code is being called but somehow django/python does not return anything when I check the xmlhttp.responseText and responseXML in firebug.
UPDATE: I removed the checking of the http status returned so that code immediately goes to print the output from the server
<html>
<head>
<title>Javascript example 1</title>
<script type="text/javascript">
function doAjax()
{
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
alert("response text: "+xmlhttp.responseText+"\n"
+"response XML: "+ xmlhttp.responseXML);
if (xmlhttp.responseText!="") {
$("thediv").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","http://127.0.0.1/test/",true);
xmlhttp.send();
}
function $(element){
return document.getElementById(element);
}
</script>
</head>
<body>
<input type="button" value="click me" onClick=javascript:doAjax()>
<br/><br/>
<div id="thediv">
some test
</div>
</body>
</html>
my views.py
from django.http import HttpResponse
def test(request):
response_string="hello"
return HttpResponse(response_string,mimetype='text/plain')
my urls.py
from django.conf.urls.defaults import *
from project1.views import test
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()
urlpatterns = patterns('',
(r'^test/$', test)
# Example:
# (r'^project1/', include('project1.foo.urls')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
# (r'^admin/', include(admin.site.urls)),
)
UPDATE
Here is the code in action
I just tested your code. When I clicked the "click me" button, a request was indeed made to the test view. I was able to confirm this. However, unlike what you said the view is returning the HttpResponse. To verify this yourself, access the http://localhost:8000/test/ url using your web browser. See what happens.
At first blush your problem seems to be JavaScript related. I don't know what exactly is going wrong but I'll try to debug the JS code and see.
Update
I was able to confirm that the error is indeed with the JavaScript that you are using. I found two errors. First:
if (xmlhttp.readyState==4 && xmlhttp.status==0)
Shouldn't the status be 200? So I changed it to:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
Update 2
Found that I missed the $ function.
The problem is that there are two if conditions. When first evaluates to true, the contents of the div are indeed updated to "hello". However the second if (xmlhttp.responseXML!="") also evaluates to true (null is != "", hence) and wipes out the contents of the div.
Its good to use core JavaScript when learning but you should definitely use some framework such as jQuery or Prototype as you progress. Frameworks allow to keep your code concise, develop faster and also insulate you from the cross-browser compatibility issues.
Using jQuery your code would have been something like this:
<html>
<head>
<title>Javascript example 1</title>
<script type=”text/javascript” src=”http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js”></script>
<script type="text/javascript">
function doAjax()
{
$.ajax({
url: 'http://localhost:8000/test/',
success: function(data) {
$('#thediv').html(data); //jQuery equivalent of document.getElementById('thediv').innerHTML = data
}
});
}
</script>
</head>
<body>
<input type="button" value="click me" onClick="javascript:doAjax()"/>
<br/><br/>
<div id="thediv">
some test
</div>
</body>
</html>
Since jQuery provides with a default $() function, you do not need to define them in your code in case you use the framework.
Though this answer is slightly off-track, I hope it will be useful to you.

Categories