I want to send a post request from inside an iframe in laravel. I have the script file (from which I'm sending the request) in a folder in public (public/scripts/subscript/main.js). And my example request looks like this in the main.js file:
$.post("./server/update-data", { id: 1 }, function(data){
console.log(data);
}).fail(function() {
alert("ERROR");
});
//route
Route::post('/server/update-data', 'PageController#goToServer');
The specific issue is that the request is going through the parent route then to the route given, e.g
(localhost:8000/parent/server/update-data)
but should look like this
(localhost:8000/server/update-data)
which should not be. How do I skip the parent route?
Please note that this same code works for requests that are not from inside the iFrame.
Related
i have a problem with res.render() in expressjs
i use ajax to request on this route:
route.get('/about',authentication,(req,res)=>{
res.render('about');
});
I did some search and found out that res.render does not work with ajax calls
so how can I change and render page without res.render().
If I remove the res.render and console.log it it will work actually any code work but not res.render (by clicking a link I send a token in header with ajax request then in my route I have an authentication middleware that get the token then redirects the user to about.ejs page)
I just want to change the page. Any idea will help guys.
thx
here is the front-end request:
$(document).ready(function(){
$('#about').click(function(){
// window.location.href='/about';
$.ajax({
method:'get',
url:'http://localhost:5000/about',
headers:{"authtoken":localStorage.getItem('authToken')}
}).done(()=>{
// window.location.href='/about';
}).catch(e=>console.log('header.ejs error'));
});
});
res.render composes a html page using templates and sends the final composed result from the server to the client. It does not issue a rendering of the page in the client window.
If the request is issued by entering the URL in the addressbar of the browser, then the browser will do the request and render the result the server sends.
If you do an ajax request you will receive that response, but you are responsible to do something with it in the .done callback. The browser does not magically know what has to be done with the data if you do an ajax request. And because you do not have anything in your .done callback nothing will happen.
So you have to do something like that:
.done(response => {
var bodyContent = response.match(/<body>(.*)<\/body>/)[1]
$('body').html(bodyContent);
})
Usually ajax is used to update a portion of page using some resposne from server without refreshing page. If you want to navigate to another route instead of ajax use form submits or href. If you stick to ajax then return a JSON from the server and do the alteration using javascript
requestHandler=(req,res)=>{
res.json({data:{}})
}
Step-1: Make a public URL, say http://your-web-site.com/redirect_destination.html
Step-2: On making ajax request from front-end, redirect user to that page using .redirect() method on response
EDIT:
The point is, I don't think it's possible to render page by making an ajax request. You can prepare a URL which renders your desired page and redirect user to that URL using .redirect() method.
Your router will not render page ,it will send only response and I didnt get just for page rendering, why you are calling ajax request on click event.If dont mind you can write logic on click and change window.location with your router. It will render particular page, for that your router should be something like this:
// about page route (http://localhost:8080/about)
router.get('/about',isAuthenticated, function(req, res) {
res.sendFile(path.join(__dirname+'/public/about.html'));
});
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
And change your url on click to http://localhost:8080/about
I'm using ASP.NET WebForms and one of the asp pages serves a pdf file through its Page_Load event. Locally I can access it through a URL like:
http://localhost:2091/Pages/Search/ViewPdf.aspx?id=1
And it works perfectly. The problem is when I try to access it using Ajax. When I run the $.get() method of jQuery:
$.get({
url: "http://localhost:2091/Pages/Search/ViewPdf.aspx?id=1",
success: function(data) {
...
}
});
I get the 404 Not Found error and in the console, the $.get() method is trying to access this URL:
http://localhost:2091/Paginas/Search/[object%20Object]
If try to access the URL directly on the browser or by using cURL everything works fine, but through the $.get() calling it doesn't. Why? What can I do?
Separate the URL parameters. Also ensure that you're sending using the same domain to avoid making a cross origin request.
$.get( "http://localhost:2091/Pages/Search/ViewPdf.aspx", { id: 1 } )
.done(function( data ) {
alert( "Data Loaded...do stuff here" );
});
In addition, it looks like the server received the original request and subsequently redirected to http://localhost:2091/Paginas/Search/[object%20Object] so take a look at your server-side logic to see why it's redirecting to an invalid URL
How to be confirmed whether a backbonejs .save() is sending PUT request ?? I checked my server side, which is working good, there is no problem in server side. But my .save() is not working.
Here is my model of backbone
define(['underscore','backbone'],function(_,Backbone)
{
var my_model = Backbone.Model.extend(
{
urlRoot: "http://localhost/back/server_file.php/number"
});
return my_model;
});
Here is how I am using .save()
var my_data = {
id: data.id,
code: data.code
};
var My_model = new my_model();
My_model.save(my_data,
{
success: function(response)
{
alert('Yes');
},
error: function(response)
{
alert('No');
}
});
I think my .save() is sending POST request to server.
UPDATE
I think I could find out my problem. I am describing that here.
What I would like to do
I would like to send 2 parameters from backbonejs model to server side script (I am using PHP SLIM Framework). Based on those 2 parameters server side script update a record's(2 field of this record match with those 2 parameters ) another field with a static parameter at database.
What backbonejs provide (As I think )
Backbonejs has a model with id as JSON format. Backbonejs sends PUT request to server side script. Server side script just dump (update) the data(which was as JSON format,like a bundle) to the database with matching id. Serer side script would not like to look inside the data.
I am getting (from network tab of firebug) my PUT request URL is like http://localhost/back/server_file.php/number/1 (This is the id) . On the other hand I would like to get URL is like http://localhost/back/server_file.php/number/1 (id the first parameter)/456 (Second parameter).
If I am right, anyone could say how can I implement my plan??
This should work,
My_model.set(my_data);
My_model.save(null, {
wait : true,
url : "http://localhost/back/server_file.php/number/1/456",
success : function(response){
},
error : function(e){
}
});
You can debug the request being sent in network tab of Chrome Developer Tools or you can use a network tool like Fiddler to see all requests.
Refer the attached on where to see the request method being used.
I am using jQuery.post() to send data to the server, when the server sends data back to the client, the post() callback is invoked. I know that the server might response with the redirect header field ("Location").
currently, the redirect does not occur. what can be the reason?
is there any possibility to run a script before the redirect occur?
UPDATE:
enclosed a snipped code. i know that the POST method is accepted by the server, and that the server responds to the POST. somehow, always the error() is being invoked (it seems like it happends even before the response is accepted by the client\browswer).
what is wrong?
$(document).ready(function() {
$("#loginForm").submit(function() {
$.ajax({
type : "POST",
data : $("#loginForm :input").not("#loginBtn").serialize(),
url : "http://localhost/auth",
success : function(data, textStatus, jqXHR) {
alert("success");
alert(jqXHR.getResponseHeader("Location"));
},
error : function(jqXHR, textStatus, errorThrown) {
alert("error");
}
});
});
});
jquery.post() works by issuing an Ajax request. In an Ajax call, the PHP script works asynchronously (think of it as a background thread). Thus, the PHP script cannot redirect the client's browser. The way to go would be to have the PHP script responsd with the URL to redirect to, and redirect using javascript.
In your POST callback:
function(data){ //data will be the URL to redirect to, sent back by the PHP script
window.location = data;
}
EDIT
From Jquery documentation on jquery.ajax()
statusCode(added 1.5)Map
Default: {}
A map of numeric HTTP codes and functions to be called when the response has the corresponding code. For example, the following will alert when the response status is a 404:
$.ajax({
statusCode: {
404: function() {
alert('page not found');
}
}
});
If the request is successful, the status code functions take the same parameters as the success callback; if it results in an error, they take the same parameters as the error callback.
Please in redirect case get simple response without redirecting print any flag like "redirect" and and write client side redirect using
if(responce == 'redirect')
window.location = "Your url"
Do not redirect on server.
It will work.
If you perform an operation that results in a redirect, JQuery does not detect it. The browser handles it automatically behind the scenes, to create a seamless experience.
I have a web site that is trying to call an MVC controller action on another web site. These sites are both setup as relying party trusts in AD FS 2.0. Everything authenticates and works fine when opening pages in the browser window between the two sites. However, when trying to call a controller action from JavaScript using the jQuery AJAX method it always fails. Here is a code snippet of what I'm trying to do...
$.ajax({
url: "relyingPartySite/Controller/Action",
data: { foobar },
dataType: "json",
type: "POST",
async: false,
cache: false,
success: function (data) {
// do something here
},
error: function (data, status) {
alert(status);
}
});
The issue is that AD FS uses JavaScript to post a hidden html form to the relying party.
When tracing with Fiddler I can see it get to the AD FS site and return this html form which should post and redirect to the controller action authenticated. The problem is this form is coming back as the result of the ajax request and obviously going to fail with a parser error since the ajax request expects json from the controller action. It seems like this would be a common scenario, so what is the proper way to communicate with AD FS from AJAX and handle this redirection?
You have two options.
More info here.
The first is to share a session cookie between an entry application (one that is HTML based) and your API solutions. You configure both applications to use the same WIF cookie. This only works if both applications are on the same root domain.
See the above post or this stackoverflow question.
The other option is to disable the passiveRedirect for AJAX requests (as Gutek's answer). This will return a http status code of 401 which you can handle in Javascript.
When you detect the 401, you load a dummy page (or a "Authenticating" dialog which could double as a login dialog if credentials need to be given again) in an iFrame. When the iFrame has completed you then attempt the call again. This time the session cookie will be present on the call and it should succeed.
//Requires Jquery 1.9+
var webAPIHtmlPage = "http://webapi.somedomain/preauth.html"
function authenticate() {
return $.Deferred(function (d) {
//Potentially could make this into a little popup layer
//that shows we are authenticating, and allows for re-authentication if needed
var iFrame = $("<iframe></iframe>");
iFrame.hide();
iFrame.appendTo("body");
iFrame.attr('src', webAPIHtmlPage);
iFrame.load(function () {
iFrame.remove();
d.resolve();
});
});
};
function makeCall() {
return $.getJSON(uri)
.then(function(data) {
return $.Deferred(function(d) { d.resolve(data); });
},
function(error) {
if (error.status == 401) {
//Authenticating,
//TODO:should add a check to prevnet infinite loop
return authenticate().then(function() {
//Making the call again
return makeCall();
});
} else {
return $.Deferred(function(d) {
d.reject(error);
});
}
});
}
If you do not want to receive HTML with the link you can handle AuthorizationFailed on WSFederationAuthenticationModule and set RedirectToIdentityProvider to false on Ajax calls only.
for example:
FederatedAuthentication.WSFederationAuthenticationModule.AuthorizationFailed += (sender, e) =>
{
if (Context.Request.RequestContext.HttpContext.Request.IsAjaxRequest())
{
e.RedirectToIdentityProvider = false;
}
};
This with Authorize attribute will return you status code 401 and if you want to have something different, then you can implement own Authorize attribute and write special code on Ajax Request.
In the project which I currently work with, we had the same issue with SAML token expiration on the clientside and causing issues with ajax calls. In our particular case we needed all requests to be enqueud after the first 401 is encountered and after successful authentication all of them could be resent. The authentication uses the iframe solution suggested by Adam Mills, but also goes a little further in case user credentials need to be entered, which is done by displaying a dialog informing the user to login on an external view (since ADFS does not allow displaying login page in an iframe atleast not default configuration) during which waiting request are waiting to be finished but the user needs to login on from an external page. The waiting requests can also be rejected if user chooses to Cancel and in those cases jquery error will be called for each request.
Here's a link to a gist with the example code:
https://gist.github.com/kavhad/bb0d8e4a446496a6c05a
Note my code is based on usage of jquery for handling all ajax request. If your ajax request are being handled by vanilla javascript, other libraries or frameworks then you can perhaps find some inspiration in this example. The usage of jquery ui is only because of the dialog and stands for a small portion of the code which could easly be swapped out.
Update
Sorry I changed my github account name and that's why link did not work. It should work now.
First of all you say you are trying to make an ajax call to another website, does your call conforms to same origin policy of web browsers? If it does then you are expecting html as a response from your server, changedatatype of the ajax call to dataType: "html", then insert the form into your DOM.
Perhaps the 2 first posts of this serie will help you. They consider ADFS and AJAX requests
What I think I would try to do is to see why the authentication cookies are not transmitted through ajax, and find a mean to send them with my request. Or wrap the ajax call in a function that pre authenticate by retrieving the html form, appending it hidden to the DOM, submitting it (it will hopefully set the good cookies) then send the appropriate request you wanted to send originally
You can do only this type of datatype
"xml": Treat the response as an XML document that can be processed via jQuery.
"html": Treat the response as HTML (plain text); included script tags are evaluated.
"script": Evaluates the response as JavaScript and evaluates it.
"json": Evaluates the response as JSON and sends a JavaScript Object to the success callback.
If you can see in your fiddler that is returning only html then change your data type to html or if that only a script code then you can use script.
You should create a file anyname like json.php and then put the connection to the relayparty website this should works
$.ajax({
url: "json.php",
data: { foobar },
dataType: "json",
type: "POST",
async: false,
cache: false,
success: function (data) {
// do something here
},
error: function (data, status) {
alert(status);
}
});