Are cross-domain ajax requests possible without server consenting? - javascript

I understand the notion of the same-origin policy and the reasons for it, and I understand that cross-domain requests are possible with CORS. But I'd like to know if it's in any way possible, however unconventional it may be, to communicate with a server cross-domain when that server does not return the "Access-Control-Allow-Origin" header in responses.
I'm not trying to attack anything. I just want to legitimately login to a web application (I don't own the web app) from a remote domain and trigger some selected functionality that will result in retrieving some data.
Could someone tell me if this is even possible and how I might go about it. If it's not possibe to do an ajax call directly, then maybe even embed a hidden iframe containing the target web app in my own site and manipulate it somehow?

you can use yahoo query language for getting arround that :D
heres an extended jquery ajax function for dooing so
jQuery.ajax = function (e) {
function o(e) {
return !r.test(e) && /:\/\//.test(e)
}
var t = location.protocol,
n = location.hostname,
r = RegExp(t + "//" + n),
i = "http" + (/^https/.test(t) ? "s" : "") + "://query.yahooapis.com/v1/public/yql?callback=?",
s = 'select * from html where url="{URL}" and xpath="*"';
return function (t) {
var n = t.url;
if (/get/i.test(t.type) && !/json/i.test(t.dataType) && o(n)) {
t.url = i;
t.dataType = "json";
t.data = {
q: s.replace("{URL}", n + (t.data ? (/\?/.test(n) ? "&" : "?") + jQuery.param(t.data) : "")),
format: "xml"
};
if (!t.success && t.complete) {
t.success = t.complete;
delete t.complete
}
t.success = function (e) {
return function (t) {
if (e) {
e.call(this, {
responseText: t.results[0]
}, "success")
}
}
}(t.success)
}
return e.apply(this, arguments)
}
}(jQuery.ajax);
this will send the request to yql which has the correct accept-headers, and yql will return the content of the url requested even if it does not have the correct headers

Related

API data over http in site served over https, script has "mixed content" error

I've written a JS script that consumes data from an http API (endpoint for the GET request: http://api.open-notify.org/iss-now.json). I intend to use it in a page hosted on github pages (which makes use of the https protocol).
Now that it is online I see in the console that this data can't be used in-browser because of the mixed active content error: Blocked loading mixed active content “http://api.open-notify.org/iss-now.json”.
I can't apply this solution because I'm not making use of a server.js file (my content is served by github). I wanted to try this other solution but it requires opening the adapter page in another tab, which just isn't viable.
I'm trying this workaround but https://cors-anywhere.herokuapp.com/http://api.open-notify.org/iss-now.json returns an error (Missing required request header. Must specify one of: origin,x-requested-with). If anyone know how to add headers to the loadJSON method please tell me, I can't find anything in its documentation. I'm not exactly at ease with the syntax of fetch, so when I try it:
var response = fetch("https://cors-anywhere.herokuapp.com/http://api.open-notify.org/iss-now.json", {
headers: {
Origin: window.location.protocol + '//' + window.location.host
}
});
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
var json = response.json();
return(json);
} else {
alert("HTTP-Error: " + response.status);
}
I get to add the "origin" header, only to find myself with a
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at
https://cors-anywhere.herokuapp.com/http://api.open-notify.org/iss-now.json.
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
Which as far as I understand can only be corrected server-side.
The github page of cors-anywhere encourages to implement their solution in your own script, by adding this snippet:
(function() {
var cors_api_host = 'cors-anywhere.herokuapp.com';
var cors_api_url = 'https://' + cors_api_host + '/';
var slice = [].slice;
var origin = window.location.protocol + '//' + window.location.host;
var open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
var args = slice.call(arguments);
var targetOrigin = /^https?:\/\/([^\/]+)/i.exec(args[1]);
if (targetOrigin && targetOrigin[0].toLowerCase() !== origin &&
targetOrigin[1] !== cors_api_host) {
args[1] = cors_api_url + args[1];
}
return open.apply(this, args);
};
})();
but I wouldn't know how to implement it, I haven't succeeded integrating it in my code for now.
My code is a bit of a mess right now but I can show you this much:
// global functions for the Tracker sample
function getData() {
// var promise = fetch("http://api.open-notify.org/iss-now.json");
loadJSON("http://api.open-notify.org/iss-now.json", gotData, 'jsonp');
}
function gotData(data) {
background(img)
displaySample()
// this will allow you to see the raw data live in your browser console
//console.log(data.iss_position.latitude);
//console.log(data.iss_position.longitude);
posX = (parseFloat(data.iss_position.latitude * latConst) + translateX)
posY = (parseFloat(data.iss_position.longitude * lonConst)* -1 + translateY)
console.log(posX);
console.log(posY);
fill(250, 50, 50, 90);
ellipse(posX, posY, 10, 10);
}
function draw() {
// case tracker
if (selectedSample === 1) {
translateX = boxSizeWidth / 2;
translateY = boxSizeHeight / 2;
latConst = boxSizeWidth / 360;
lonConst = boxSizeHeight / 180;
if (t === 0) {
getData()
}
}
I also tried finding an https API giving the same data (latitude and longitude of the ISS in real time) but I can't seem to find any for now, and finding a workaround would be interesting anyway.
You could use fetch like this:
fetch("https://cors-anywhere.herokuapp.com/http://api.open-notify.org/iss-now.json", {
headers: { Origin: window.location.host }
})
.then(res => res.json())
.then(res => {
console.log(res);
// gotData(res);
})
.catch(err => {
console.log(err);
});

How Django and JavaScript work together for running Python script?

I am wondering how to accomplish the below with Django:
Consider a function in JavaScript:
$('#button').click(function(){
var rand_val = Math.random();
// here some code sends this rand_val to a Python script in Django app
// as seen below, script is run and generates result
alert('This is the result ' + result);
})
The script in the Django app:
def my_func(rand_val):
# result = (some operations with rand_val)
return result
The Python script will be run in Django virtual environment.
With a button click, run a Python script and show the result on the page.
You can send the data with ajax get,
var url = "url_to_my_func_view/" + rand_val
$.get( url, function( data ) {
alert( "Data Loaded: " + data );
});
You will need to return your result as bytes or JSON using HttpResponse or JsonResponse.
Edit:
If you need to send back user input (as the OP explained in the comments), then you are better off with GET or POST params. In JS you would do like so,
var url = 'url_to_my_func_view/'
$.get( url, {'user_val': rand_val}, function( data ) {
alert( "Data Loaded: " + data );
});
Then in your view you would catch those params like so,
def my_func(request):
user_val = request.GET['user_val']
return user_val
Notice that your function receives a request!
Hope this helps!
To perform form submission through Ajax, need to use some specific code snippets. I am adding the details source code so, you might find these helpful!
The code in JavaScript file:
//The functions below will create a header with csrftoken for Ajax based submission in Django application
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function sameOrigin(url) {
// test that a given url is a same-origin URL
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
// Send the token to same-origin, relative URLs only.
// Send the token only if the method warrants CSRF protection
// Using the CSRFToken value acquired earlier
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
// Ajax setup end
$('#button').click(function(e){
var rand_val = Math.random();
$.post('/my_func/', { rand_val: rand_val }, function(data){
return false;
});
e.preventDefault();
});
In views.py:
def my_func(request):
response = {}
if request.method == 'POST':
rand_val = request.POST.get('rand_val')
# result = (some operations with rand_val)
return result
In urls.py: Django v2.x
from django.contrib import admin
from django.urls import path, include
import APP_NAME.views
urlpatterns = [
path('my_func/', APP_NAME.views.my_func),
]
Expecting the code will work for you!

Same domain AJAX calls being redirected by 3rd party authentication

In our asp.net core application, I need to make an AJAX call to an IIS 8.0 Server.
The server URL is protected by CA SiteMinder SSO.
When I make Get requests using AJAX I get the desired response. But on the contrary, whenever a Put or Post request is made, I get a 302 response and the url which suggests SiteMinder is requesting credentials.
I was of the opinion, that as long as a User is authenticated by SiteMinder, then requests made to the same domain from the same browser session would not explicitly require users credentials.
As far as I can see, SiteMinder is requesting user credentials even when the user has been authenticated and the requests (PUT & POST) are being made to the same domain.
CA SiteMinder provides a cookie (HttpOnly), which I believe is used to authenticate requests made to the server. I can confirm that the SiteMinder cookie is being included in the requests headers.
My question is why does SiteMinder treat GET and POST/Put requests differently? Or is there any way I can make my POST/PUT request work(without getting a redirect from SiteMinder) with Siteminder using the XHR?
Here is the link to function that makes the XHR request.
function fixRecords() {
_buildingId = ($("input:hidden[id='buildingIdModal']").val());
_roomNo = $("#roomNoModal").val();
if ((_roomNo === "" || _roomNo == null) && _suggestedRoomNo) {
_roomNo = document.getElementById("roomNoModal").value;
}
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status.toString() == 200) {
var message = "Record updated sucessfully.";
var jsonResponse = JSON.parse(this.responseText);
console.log(jsonResponse);
_roomNo = jsonResponse.roomNo;
_buildingId = jsonResponse.building;
_runId = jsonResponse.runId;
var _prevRoomId = _roomId;
_roomId = jsonResponse.roomId;
_recId = jsonResponse.recordId;
message = jsonResponse.comment;
_valid = jsonResponse.valid;
_suggestion = '<div class="glyphicon glyphicon-alert text-info">' + jsonResponse.suggestion+'</div>';
_suggestedRoomId = jsonResponse.suggestedRoomId;
_suggestedRoomNo = jsonResponse.suggestedRoomNo;
var _protocol = jsonResponse.protocol;
var _invAcct = jsonResponse.account;
var _pi = jsonResponse.pi;
displayInformationInFixModal(message + _suggestion, null);
$('#fixModal').on('show.bs.modal', inflateModal(message, _buildingId, _cageId, _roomId, _roomNo, _recId, _runId, _frequencyId, _frequencyType, _valid, _suggestedRoomId, _suggestedRoom, _suggestion, _protocol, _pi, _invAcct));
$('#fixModal').modal('show').on("hide", function () {
$('#fixModal').modal('hide');
});
//document.write(this.responseText);
}
$('#showLoadingImage').modal('hide');
return false;
};
if (_roomNo == null || _roomNo.trim()===''|| _roomNo==="Room Num Unknown") {
alert("Please enter a valid Room No.");
var message = "Please enter a valid Room No.";
$('#fixModal').on('show.bs.modal', populateModalMessage(message));
$('#fixModal').modal('show').on("hide", function () {
$('#fixModal').modal('hide');
});
}
if (_recId <=0) {
xhttp.open("POST", "/FileUploads/InsertFixRecordToDB?BuildingId=" + _buildingId );
}
else {
xhttp.open("PUT", "/FileUploads/FixARecord?BuildingId=" + _buildingId );
}
$('#showLoadingImage').modal('show');
$('#showLoadingImage').css('zIndex', 1500);
xhttp.send();
}
If the SiteMinder cookie is HttpOnly then it explicitly will not be sent by the ajax engine. That's what HttpOnly means.
Separately, SiteMinder (now called CA SSO) definitely distinguishes between different HTTP methods, so the SiteMinder rules can be different for GET POST and PUT. Your SiteMinder admin will need to check the rules applicable for your application to make sure they specifically cover GET POST and PUT (PUT especially is often not included).
HTH!

Using XMLHttpRequest() PUT with GAE Python

I am currently trying to write some Javascript to interact with an API that I deployed on GAE (using Python) using XMXMLHttpRequest(). I've had no issue getting a GET, however the PUT is giving me a lot of trouble.
Interestingly, I have no issue touching the PUT request from a test HTTP site (https://www.hurl.it/), however I receive a status value of 0 every time I try from my own Javascript code. Below are snippets of my GAE and Javascript code.
(NOTE - I must use a "put" for this call as a requirement.)
Any guidance would be appreciated!
GAE (Server):
def put(self):
# Save variables for update
cardkey = self.request.get('key', default_value=None)
ident = self.request.get('ident', default_value=None)
brand = self.request.get('brand', default_value=None)
year = self.request.get('year', default_value=None)
player = self.request.get('player', default_value=None)
# If card key is provided then update card
if cardkey:
# Get card
card_to_update = ndb.Key(db_models.Card, int(cardkey)).get()
if ident:
card_to_update.ident = ident
if brand:
card_to_update.brand = brand
if year:
card_to_update.year = year
if player:
card_to_update.player = player
# Save changes and print update to requester
card_to_update.put()
card_dict_format = card_to_update.to_dict()
self.response.write(json.dumps(card_dict_format))
return
# If card key is not provided send error
else:
self.response.write('key not provided. must provide key for update.')
return
And the Javascript from my webpage:
<script>
window.onload = function()
{
var myRequest = new XMLHttpRequest();
var url = 'http://cs496-assignment3-mastrokn.appspot.com/updatecard';
var param = 'key=5636318331666432';
myRequest.open('put', url);
myRequest.onreadystatechange = function()
{
if ((myRequest.readyState == 4) && (myRequest.status == 200))
{
// var myArr = JSON.parse(myRequst.responseText);
// myFunction(myArr);
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
}
myRequest.send(param);
}
</script>
First, your onreadystatechange() handler should look like this:
myRequest.onreadystatechange = function()
{
if (myRequest.readyState == 4) //Don't do anything until the readyState==4
{
if(myRequest.status == 200) //Check for status==200
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else //All other status codes
{
document.getElementById("viewCards").innerHTML =
'readyState='
+ myRequest.readyState
+ ' status='
+ myRequest.status
+ ' status text='
+ myRequest.statusText;
}
}
}
Then, from the docs:
If you end up with an XMLHttpRequest having status=0 and
statusText=null, it means that the request was not allowed to be
performed. It was UNSENT.
To see what went wrong, check the javascript console in your browser for an error, e.g.:
[Error] XMLHttpRequest cannot load
http://cs496-assignment3-mastrokn.appspot.com/updatecard. Origin
http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
(4.htm, line 0)
When I run the code above and send the XMLHttpRequest to my own local server, the PUT request succeeds with a status code of 200.
Lastly, I have doubts about the server code you posted because I don't know of any framework where you return None from a request handler--rather you return some string or a response object. Yet, using other means to make a PUT request to your url returns a 200 status code. Is that really your server code? What framework are you using?

Using XMLHttpRequest to get words from another website

As of current I am learning to use JavaScript to create web applications. I have just finished developing a hangman game (code will be provided later on). I have used an array of words to get a random word to play with. But as a next step I want to use an XMLHttpRequest to get a random word from a separate website, I was wondering if someone could point me towards a tutorial or give me some information on how to start!
Thanks in advance!
<script type="text/javascript">
var myWords = new Array("first", "hello", "goodbye", "random", "word", "last");
var item = myWords[Math.floor(Math.random() * myWords.length)];
var length = item.length;
var guessedLetters = "";
var error = 0;
function partialWords(item, letters) {
var returnLetter = "";
for (i = 0; i < item.length; i++) {
if (letters.indexOf(item[i]) !== -1) {
returnLetter = returnLetter + item[i];
} else {
returnLetter = returnLetter + '_';
}
}
return returnLetter;
}
function load() {
var input = document.getElementById("hangmanID").value;
var myWords2 = (item.indexOf(input) >= 0);
if (myWords2 === false) {
console.log("That letter is not in the word");
document.getElementById("hangmanID").value = "";
document.getElementById("error").innerHTML = "That letter was wrong!";
document.getElementById("success").innerHTML = "";
error++;
if (error > 0) {
document.getElementById('hangmanImg').innerHTML = "<img src='assets/" + error + ".png'>";
} else {
document.getElementById('hangmanImg').innerHTML = "No Errors yet!";
}
} else {
console.log("That letter is correct");
var string = item.indexOf(input, 0);
console.log(string);
document.getElementById("hangmanID").value = "";
document.getElementById("success").innerHTML = "That letter was right!";
document.getElementById("error").innerHTML = "";
}
guessedLetters = guessedLetters + input;
document.getElementById('hangman').innerHTML = partialWords(item, guessedLetters);
document.getElementById("lettersUsed").innerHTML = guessedLetters;
}
</script>
UPDATE:
PLEASE NOTE THAT I AM ALLOWED TO USE JSONP
Due to same-origin-policy, XMLHttpRequest is not normally allowed to fetch data from other domains. There are work-arounds such as CORS or using a proxy on your domain or using an embedded flash or java applets.
However, JSONP is a different story. That's because JSONP does not technically return data. JSONP returns a javascript file. As such, getting data using JSONP simply requires you to add a script tag to your page:
<script src="http://other.server.com/path/to/jsonp/data"></script>
To do it programmatically:
var jsonp = document.createElement('script');
jsonp.src = "http://other.server.com/path/to/jsonp/data";
document.body.appendChild(jsonp);
The problem with this is that script tags don't return anything. To solve this, the JSONP protocol passes a function name to the server so that the server will wrap that function around the JSON data.
For example, if your regular JSON data looks like this:
{"result":"something"}
The JSONP equivalent would look something like this:
callback({"result":"something"})
So, to take the original example, our new code would now be:
function processResult (obj) {
console.log(obj);
}
var jsonp = document.createElement('script');
jsonp.src = "http://other.server.com/path/to/jsonp/data?jsonp=processResult";
document.body.appendChild(jsonp);
Notice how we're passing the name of the function to handle the return value in the query param of the URL.
Note that while in this example the parameter is "jsonp" the server may implement it using some other name. Another common one is "callback", as in callback=processResult. Read the API documentation of the server you're connecting to.

Categories

Resources