Cross Domain AJAX in IE9 not working in CQ5 - javascript

I need to send a cross domain request using jQuery AJAX. But it is not working in IE9.
The strange thing is, it works fine when I try it in a standalone HTML file. But breaks when done in a CQ page.
The js code is below:
$.support.cors = true;
$.ajax({
cache: false,
url: "https://www.some.external.web.service",
dataType: "json",
contentType: "application/json; charset=utf-8",
type: "POST",
crossDomain: true,
data: "{"key":"value"}",
processData: false,
success: function (response) { alert("success"); },
error: function (xhr, status, error) { alert("AJAX Error:status: "+ status+ "\nerror: " + error + "\nxhr.status: " + xhr.status + "\nResponseText: \n" + xhr.responseText); }
});
I have tried using datatype as 'jsonp' but still no avail. In IE9, it never returns the 'Success' handler and always goes to the 'error' handler.
The error shown is 'Transport Error'.
The webservice is in https and my page can be either http(author) or http(publish)
I already have the $.support.cors = true; set before the ajax. What am I missing ?

I couldn't use JSONP or XDR because of the GET and text content respectively.
For this, I added an iframe in my page whose HTML resides in the client's server. So we post our data to the iframe and the iframe then posts it to the webservice. Hence the cross-domain referencing is eliminated.
We've added a 2-way origin check to confirm only authorized page posts data to and from the iframe.
<iframe style="display:none;" id='receiver' name="receiver" src="https://iframe-address-at-client-server">
</iframe>
//send data to iframe
var hiddenFrame = document.getElementById('receiver').contentWindow;
hiddenFrame.postMessage(JSON.stringify(message), 'https://client-server-url');
//The iframe receives the data using the code:
window.onload = function () {
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
eventer(messageEvent, function (e) {
var origin = e.origin;
//if origin not in pre-defined list, break and return
var messageFromParent = JSON.parse(e.data);
var json = messageFromParent.data;
//send json to web service using AJAX- same origin now
//return the response back to source
e.source.postMessage(JSON.stringify(aJAXResponse), e.origin);
}, false);
}

Related

Postman: Send XML as body using application/x-www-form-urlencoded as content type

Ok, first thing: I am not responsible for this code.
I am dealing with a router. This router has a web interface, and the code I'm about to show is in the router's web interface.
My job is to build an app to configure this router.
And I need my app to perform the login operation in the router.
The thing is: the developers that created the web interface for this router, made the router accept a post request in which the body of the request is xml, and the content type is application/x-www-form-urlencoded !!!! (whaaaaaat???)
The source code that generates this request is in the page:
function PostXML_log(pUrl, value) {
$.ajax({
type: "POST",
dataType: 'xml',
url: pUrl,
processData: false,
data: value,
async: true,
beforeSend: function () { show_message("wait"); },
success: function (data) {
var code = $(data).find('CODE').text();
if (code == "0" || code == "-1") {
$.cookie.json = false;
$.cookie("stork", $(data).find('MESSAGE').text(), { expires: 1 });
if (code == "-1")
window.location = "mac_err.html";
else
location.href = "../main_status.html";
}
else show_message("error", err_message)
},
error: function () { show_message("error", 'loading Error...'); },
timeout: 20000
});
}
function loginIn() {
var username = 'admin';//$('#username').val();
var password = ASCII2HEX($('#login_pwd').val());
var xml = '<?xml version="1.0" encoding="utf-8"?><LOGIN><USER_NAME>' + username + '</USER_NAME><PASSWD>' + password + '</PASSWD></LOGIN>';
PostXML_log("/cgi-bin/cgi.cgi?/app/route/login", xml);
};
The problem is that I can't find a way to replicate this behavior using Postman. I couldn't find a way to send a body and use application/x-www-form-urlencoded as content type at the same time.
I tried 4 different strategies with no success:
1 - Send as body, using content type application/xml, results in no response being received (send as pure text or text/xml results the same):
2 - Send xml as form key, results in error
3 - Send xml as form value, results in error
4 - send xml as both key and value, error: (i tried putting the xml's <xml> tag as key and the <login> tag as value, as well as putting the whole xml as key and value, no luck)

Cross-Domain Ajax POST request with php proxy

First of all, I have already read this answer, which is to do the Cross-Domain Ajax GET request with php proxy. But what I need is a Ajax POST request.
So in my project, long time ago. Someone wrote this php file and together the ajax call in JavaScript, those are mean to solve the cross origin problem and which works really good! So I never think about to understand this, because I basiclly just need to change the url in the JavaScript and don't need to understand how this Ajax call works together with php.
PHP:
<?php
$nix="";
$type=$_GET['requrl'];
if ($_GET['requrl'] != $nix) {
$file = file_get_contents($_GET['requrl']);
}
elseif ($_POST['requrl'] != $nix) {
$file = file_get_contents($_POST['requrl'], false, $_POST['data']);
}
else {
$file = "false type";
}
echo $file;
?>
JavaScript:
var url = "https://XXXXXXXXXXXXXX";
url = encodeURI(url);
var useProxyPhp = true;
var data = (useProxyPhp) ? {requrl: url} : "";
var ajaxUrl = (useProxyPhp) ? "proxy.php" : url;
var ajaxProperties = {
type: 'GET',
data: data,
url: ajaxUrl,
cache: false
};
res = jQuery.ajax(ajaxProperties).done(function(res) {
// do something with the result here
})
So what I need to do is just take the same ajax GET request (copy and paste in JS) and just replace the url every time ==> job done!
Now, the first time I need to do a ajax POST request to send a xml file to the server, the server will do some calculate on it and give me a response.
I tested first with the POSTMAN and everything works fine, but when I switch to my real project. I become the Cross origin problem. So I think If I could do something to the already existing php and js, so I can solve the cross origin problem.
I tried this in my JavaScript but I got only the "false type" as antwort
function sendWPSRequest(xml) {
var url = "https://XXX.XXX.XXX.XXX:XXXX/wps";
useProxyPhp = true;
var data = (useProxyPhp) ? {requrl: url, data: xml} : "";
var ajaxUrl = (useProxyPhp) ? "proxy.php" : url;
$.ajax({
type: "POST",
url: ajaxUrl,
dataType: "text",
contentType: "application/xml",
data: data,
success:function (response) {
console.log('POST success: ', response);
},
error: function (jqXHR, textStatus, errorThrown) {
alert("POST", textStatus, errorThrown);
}
});
}
Can someone help me a little bit to understand what the php is doing here and what should I do to modify the php and JS.

No 'Access-Control-Allow-Origin' header is present on the requested resource when i am using a public URL

I want to call sample service using Ajax. Below is the code i am using.
<script type="text/javascript">
var date1;
var time1;
var time2;
var date2
function CallService() {
date1 = new Date();
time1 = date1.getMilliseconds();
$.ajax({
url: "https://www.google.co.in",
type: "GET",
crossDomain: true,
contentType: "text/xml; charset=\"utf-8\"",
success: OnSuccess,
error: OnError
});
return false;
}
function OnSuccess(data, status) {
alert('success');
}
function OnError(request, status, error) {
alert('error');
}
$(document).ready(function () {
jQuery.support.cors = true;
});
</script>
I know that if we add header('Access-Control-Allow-Origin: *'); in server will remove the issue.
But i don't have access to the server side code so please can some one tell me how can i enable cross domain access in javascript.
Thanks in Advance.
You can use JSONP which stands for “JSON with Padding” and it is a workaround for loading data from different domains. It loads the script into the head of the DOM and thus you can access the information as if it were loaded on your own domain, thus by-passing the cross domain issue
Basic Example : http://jsfiddle.net/yvzSL/714/
Please refer "http://www.sitepoint.com/jsonp-examples/" for more examples

Calling PHP webservice method from Javascript/jQuery

I've have created a PHP web service method
public function import_external_xml($importXml)
I want to allow a client to upload xml via my web service method. My web service is not on the same domain as the client. The client has a webpage with a button where he want to write some javascript/jQuery to upload the xml via my web service method.
How can he do this?
Web service method in server.php:
public function import_external_xml($importXml)
{
echo 'import_external_xml';
exit;
}
I did the same thing using Ruby on Rails. But was sending data that was not in xml format.
One important thing as you said that your webservice is not on the same domain, you will have to deal with CORS. You can get idea about CORS here https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
You can refer this Post JQuery JSON Calls To PHP WebService Always Runs "Error" Callback
function callPhpAPI(){
var dataa = {"your_data":youdata};
$.ajax({
url : yourwebserviceurl,
type: 'POST',
data : JSON.stringify(dataa),
contentType : "application/json",
success:function(data)
{
if(data){
alert(data);
//console.log("Data from Server"+JSON.stringify(data));
}
else{
console.log("Data is empty");
}
},
error: function(xhr) {
alert('Error! Status = ' + xhr.status + " Message = " + xhr.statusText);
//console.log('Error! Status = ' + xhr.status + " Message = " + xhr.statusText);
}
});
});
You can call your php function like this using ajax
xmlDocument = $("<wrap/>").append(xmlDocument).html();
xmlDocument = encodeURIComponent(xmlDocument);
then ajax
jQuery.ajax({
type: "POST",
url: 'your_functions_address.php',
processData : false,
contentType : 'text/xml',
data : xmlDocument,
success: function (obj, textstatus) {
if( !('error' in obj) ) {
yourVariable = obj.result;
}
else {
console.log(obj.error);
}
}
});
i think you want pass xml via this ajax post , then you can refer this discussion
post xml
also check this

How to set custom http headers when changing iframe src?

Is there a way to add a custom http header into the request done by an <iframe> when changing the source (src) using javascript?
You can have the results of an ajax request that has custom headers be set as the content of an iframe like so:
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('src',"data:text/html;charset=utf-8," + escape(data))
}
});
This is assuming the iframe is pointing at a cross domain src. It is simpler if everything is on the same domain.
Edit: Maybe try this variation.
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('src',"/")
$("#output_iframe_id").contents().find('html').html(data);
}
});
Rather than using a data URI, or setting the contents to a string, you can use URL.createObjectURL(), and set it as the src of the iframe.
var xhr = new XMLHttpRequest();
xhr.open('GET', 'some.pdf');
xhr.onreadystatechange = handler;
xhr.responseType = 'blob';
xhr.setRequestHeader('Authorization', 'Bearer ' + token);
xhr.send();
function handler() {
if (this.readyState === this.DONE) {
if (this.status === 200) {
// this.response is a Blob, because we set responseType above
var data_url = URL.createObjectURL(this.response);
document.querySelector('#output-frame-id').src = data_url;
} else {
console.error('no pdf :(');
}
}
}
The object URLs are pretty interesting. They're of the form blob:https://your.domain/1e8def13-3817-4eab-ad8a-160923995170. You can actually open them in a new tab and see the response, and they're discarded when the context that created them is closed.
Here's a full example: https://github.com/courajs/pdf-poc
I ended up going with the approach proposed by the other answers here, that use ajax to get the html string and then directly set the contents of the iFrame.
However, I used the approach posted in this answer to actually set the contents of the iFrame, as I found it worked well cross platform with almost all devices I could dig up.
Tested - successful:
Chrome 54 (desktop) ^
Firefox 49 (desktop) ^
IE 11 (desktop) ^
IE 10 (desktop) in emulation mode ^
Safari/Chrome on iOS 8 (ipad)
Chrome on Android 6 (nexus phone)
Edge on Lumia 950 (Win 10 Phone)
^ confirmed that linked css and js in the content run correctly (others not tested)
Tested - unsuccessful:
IE 9 (desktop) in emulation mode
Safari/Chrome on iOS 7 (iPhone)
So putting them together gives something like this (Note: I havn't actually run this exact code):
$.ajax({
type: "GET",
url: "https://yourdomain.com/gethtml",
beforeSend: function(xhr) {
xhr.setRequestHeader("yourheader", "value");
},
success: function(data) {
var iframeDoc = document.querySelector('#myiframe').contentWindow.document;
iframeDoc.open('text/html', 'replace');
iframeDoc.write(data);
iframeDoc.close();
}
});
Here's an example of setting the iFrame contents in this JS Bin
Edit: Here's the html part
<iframe id="myiframe" src="about:blank"></iframe>
Edit 2:
The solution above appears to no longer be working in Firefox (50.1.0) for some unknown reason. Using the solution in this answer I've now changed to code to the example below, which also seems to be more robust:
$.ajax({
type: "GET",
url: "https://yourdomain.com/gethtml",
beforeSend: function(xhr) {
xhr.setRequestHeader("yourheader", "value");
},
success: function(data) {
var iframe = document.getElementById('myiframe');
iframe.contentWindow.contents = data;
iframe.src = 'javascript:window["contents"]';
}
});
The following code works. It is a modification of the code provided by Matthew Graves, modified to use the srcdoc attribute to solve the problem of CSS and JavaScript references not been ran. Unfortunately, it is only working in Chrome.
$.ajax({
type: "GET",
url: "https://app.icontact.com/icp/a/",
contentType: "application/json",
beforeSend: function(xhr, settings){
xhr.setRequestHeader("some_custom_header", "foo");},
success: function(data){
$("#output_iframe_id").attr('srcdoc',data)
}
});
Edit: Finally, I have resolved the issue of the scripts blocks cross-browser, by reassigning them to the iframe on document.ready function:
$(document).ready(function () {
var doc = $(document);
if (frames.length > 0) {
doc = frames[0].document;
$(doc).find('script').each(function () {
var script = document.createElement("script");
if ($(this).attr("type") != null) script.type = $(this).attr("type");
if ($(this).attr("src") != null) script.src = $(this).attr("src");
script.text = $(this).html();
$(doc).find('head')[0].appendChild(script);
$(this).remove();
});
}
});

Categories