I'm trying to use jQuery to POST a form to chargify. My "Net" tab shows a 302 redirect (in red indicating an error), but jQuery is throwing a 404 error. Is it possible to preform a x-domain, post, redirect request from the browser or will I need to use proxy?
$(function() {
var endpoint = "https://api.chargify.com/api/v2/signups"
$('#new_sub_form').on('submit', function(e){
e.preventDefault()
var jqxhr = $.ajax({
type: "POST",
url: endpoint,
crossDomain:true,
data: $('#new_sub_form').serialize(),
success: function(data, textStatus, request){
console.log(request.getResponseHeader('Location'));
},
error: function (request, textStatus, errorThrown) {
console.log(request.getResponseHeader('Location')); // Returns null
}
})
})//on('submit')
})//ready()
UPDATE (more info):
So I realized the 302 was redirecting me to a page that didn't exist on my server. Unfortunately once i fixed this, I still have an issue. From what I can tell, i POST to chargify, they then send a 302 back to the browser with the URI I specified. This URI is located on my server (localhost for now). Once the user is redirected my server parses the response and returns JSON. I tested the Response Header location via copy and paste into another tab and works fine.
Chargify is only offering https, while my localhost is http. Would this cause the error?!
HTTP Response
Ran into to a very similar problem the other day. However im using ASP.NET MVC4.
Its not enough if you use crossDomain:true u also need to add,
dataType: 'json or html depending on the return value',
xhrFields: {
withCredentials: true
},
You will also need to add these headers "Access-Control-Allow-Origin:"http://yourdomain.net" ,
Access-Control-Allow-Credentials:true" and maybe "Access-Control-Allow-Methods:GET,POST" in your case aswell to your RESPONSE.
Chargify Direct does not support ajax/CORS.
You should use a "transarent redirect", as they describe, which is basically a standard form post redirecting the user to Chargify, and they will redirect the user back again to the URL you specify in the payload. This means the user will briefly leave your site and return back to it.
<form method="post" action="https://api.chargify.com/api/v2/signups">
</form>
Docs: https://docs.chargify.com/chargify-direct-introduction
Related
I am trying to post data to a from AJAX to a Google form, but even though it reports success with a statusCode of 0, the data never appears in the form:
var dat={ "entry.529474552" :"data1", "entry.1066559787": "name1"};
postToGoogle("1FAIpQLSf4w1OQGsIncaiqXlmfAl4jYSt-e4Zx3xVJa7Weob4LnQbRZQ",dat);
function postToGoogle(id, dat) {
$.ajax({
beforeSend: function (xhr) {
xhr.setRequestHeader('Access-Control-Allow-Origin', 'chrome-extension://EXTENSION_ID');
xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST, PUT');
},
url: "https://docs.google.com/forms/d/e/"+id+"/formResponse",
data: dat,
type: "POST",
dataType: "xml",
xhrFields: { withCredentials: true },
statusCode: {
0: function() { console.log("OK") },
200: function() { console.log("error") },
}
});
}
It generates a CORS error, but supposedly, the POST should go through anyway.
For those looking to do this as of April 2019
I was working on this today. The current answer is as follows:
Each field in the Google Form has a unique ID. In order to retrieve it, get a pre-filled link by filling out all relevant form fields you wish to programatically submit
Note: In order to ensure the URL is accessible without restriction, you'll also want to disable restriction to your domain only (for GSuite paying users)
Then, copy the link and paste in your browser. The URL has a base format as follows:
https://docs.google.com/forms/d/e/[FORMID]/formResponse
Each param is a key/value pair of type: entry.XXXXXX=value
The prefilled link will give you the value of XXXXX for each relevant field
Request must be made with following headers:
Method: GET
Content-Type: application/x-www-form-urlencoded
The final request looks like this
https://docs.google.com/forms/d/e/123332233bsj333/formResponse?entry.123456=value1&entry.2333442=value2&submit=Submit
Don't forget to append submit=Submit at the end of your request!
It generates a CORS error, but supposedly, the POST should go through anyway.
While it is possible to make a successful POST request, get a CORS error, and be unable to read the response, this is only true for Simple Requests.
Because your request has:
Custom headers (Access-Control-Allow-Origin and Access-Control-Allow-Methods, which are response headers and have no business being on a request in the first place)
Credentials (i.e. you have set withCredentials: true)
… it is a Preflighted Request.
Before the browser will make the POST request, it will make an OPTIONS request to ask permission.
Since it doesn't get permission, the request fails.
Note that even if you did turn it into a simple request and make the POST successfully, you would still get a status of 0. You can't read the status when there is a CORS error.
I've got a few similar POST request on a website. In one case, the request is working (data is stored on the server), but then, there's an unexpected redirect. I send/receive data using jQuery. On the backend, I use the PHP framework Laravel.
Let's say I'm on myapp.dev/clients/123. Then I click the store-data-button and data is sent to/received from the server (Let's assume $('#resubmission_note').val() === 'abc'):
// AJAX request
$('#store-data-button').on('click', function() {
let ajaxRequest = $.ajax({
url: '/resubmissions',
type: 'POST',
data: {
// An integer, some text, and a date
'client_id': $('#id').html(),
'resubmission_note': $('#resubmission_note').val(),
'resubmission_due_date': $('#resubmission_due_date').val()
}
});
ajaxRequest.done(function(returned_id) {
// Removed all code here for testing. Browser still redirecting.
});
});
But then the browser is redirected to myapp.dev/clients/123?resubmission_note=abc.
The network tab in Chrome devtools says
Name:123?resubmission_note=abc
Status: 200
Type: document
initiator: Other
There's data appended in the URL, that should only be the case with GET request, AFAIK. I checked whether some other JavaScript code might interfere, but couldn't find store-data-button or resubmission_note in any unexpected files.
Any advice on how to fix the problem or how to debug it?
So I've got this jQuery AJAX call, and the response comes from the server in the form of a 302 redirect. I'd like to take this redirect and load it in an iframe, but when I try to view the header info with a javascript alert, it comes up null, even though firebug sees it correctly.
Here's the code, if it'll help:
$j.ajax({
type: 'POST',
url:'url.do',
data: formData,
complete: function(resp){
alert(resp.getAllResponseHeaders());
}
});
I don't really have access to the server-side stuff in order to move the URL to the response body, which I know would be the easiest solution, so any help with the parsing of the header would be fantastic.
cballou's solution will work if you are using an old version of jquery. In newer versions you can also try:
$.ajax({
type: 'POST',
url:'url.do',
data: formData,
success: function(data, textStatus, request){
alert(request.getResponseHeader('some_header'));
},
error: function (request, textStatus, errorThrown) {
alert(request.getResponseHeader('some_header'));
}
});
According to docs the XMLHttpRequest object is available as of jQuery 1.4.
If this is a CORS request, you may see all headers in debug tools (such as Chrome->Inspect Element->Network), but the xHR object will only retrieve the header (via xhr.getResponseHeader('Header')) if such a header is a simple response header:
Content-Type
Last-modified
Content-Language
Cache-Control
Expires
Pragma
If it is not in this set, it must be present in the Access-Control-Expose-Headers header returned by the server.
About the case in question, if it is a CORS request, one will only be able to retrieve the Location header through the XMLHttpRequest object if, and only if, the header below is also present:
Access-Control-Expose-Headers: Location
If its not a CORS request, XMLHttpRequest will have no problem retrieving it.
var geturl;
geturl = $.ajax({
type: "GET",
url: 'http://....',
success: function () {
alert("done!"+ geturl.getAllResponseHeaders());
}
});
The unfortunate truth about AJAX and the 302 redirect is that you can't get the headers from the return because the browser never gives them to the XHR. When a browser sees a 302 it automatically applies the redirect. In this case, you would see the header in firebug because the browser got it, but you would not see it in ajax, because the browser did not pass it. This is why the success and the error handlers never get called. Only the complete handler is called.
http://www.checkupdown.com/status/E302.html
The 302 response from the Web server should always include an alternative URL to which redirection should occur. If it does, a Web browser will immediately retry the alternative URL. So you never actually see a 302 error in a Web browser
Here are some stackoverflow posts on the subject. Some of the posts describe hacks to get around this issue.
How to manage a redirect request after a jQuery Ajax call
Catching 302 FOUND in JavaScript
HTTP redirect: 301 (permanent) vs. 302 (temporary)
The underlying XMLHttpRequest object used by jQuery will always silently follow redirects rather than return a 302 status code. Therefore, you can't use jQuery's AJAX request functionality to get the returned URL. Instead, you need to put all the data into a form and submit the form with the target attribute set to the value of the name attribute of the iframe:
$('#myIframe').attr('name', 'myIframe');
var form = $('<form method="POST" action="url.do"></form>').attr('target', 'myIframe');
$('<input type="hidden" />').attr({name: 'search', value: 'test'}).appendTo(form);
form.appendTo(document.body);
form.submit();
The server's url.do page will be loaded in the iframe, but when its 302 status arrives, the iframe will be redirected to the final destination.
UPDATE 2018 FOR JQUERY 3 AND LATER
I know this is an old question but none of the above solutions worked for me. Here is the solution that worked:
//I only created this function as I am making many ajax calls with different urls and appending the result to different divs
function makeAjaxCall(requestType, urlTo, resultAreaId){
var jqxhr = $.ajax({
type: requestType,
url: urlTo
});
//this section is executed when the server responds with no error
jqxhr.done(function(){
});
//this section is executed when the server responds with error
jqxhr.fail(function(){
})
//this section is always executed
jqxhr.always(function(){
console.log("getting header " + jqxhr.getResponseHeader('testHeader'));
});
}
try this:
type: "GET",
async: false,
complete: function (XMLHttpRequest, textStatus) {
var headers = XMLHttpRequest.getAllResponseHeaders();
}
+1 to PleaseStand
and here is my other hack:
after searching and found that the "cross ajax request" could not get response headers from XHR object, I gave up. and use iframe instead.
1. <iframe style="display:none"></iframe>
2. $("iframe").attr("src", "http://the_url_you_want_to_access")
//this is my aim!!!
3. $("iframe").contents().find('#someID').html()
So I've got this jQuery AJAX call, and the response comes from the server in the form of a 302 redirect. I'd like to take this redirect and load it in an iframe, but when I try to view the header info with a javascript alert, it comes up null, even though firebug sees it correctly.
Here's the code, if it'll help:
$j.ajax({
type: 'POST',
url:'url.do',
data: formData,
complete: function(resp){
alert(resp.getAllResponseHeaders());
}
});
I don't really have access to the server-side stuff in order to move the URL to the response body, which I know would be the easiest solution, so any help with the parsing of the header would be fantastic.
cballou's solution will work if you are using an old version of jquery. In newer versions you can also try:
$.ajax({
type: 'POST',
url:'url.do',
data: formData,
success: function(data, textStatus, request){
alert(request.getResponseHeader('some_header'));
},
error: function (request, textStatus, errorThrown) {
alert(request.getResponseHeader('some_header'));
}
});
According to docs the XMLHttpRequest object is available as of jQuery 1.4.
If this is a CORS request, you may see all headers in debug tools (such as Chrome->Inspect Element->Network), but the xHR object will only retrieve the header (via xhr.getResponseHeader('Header')) if such a header is a simple response header:
Content-Type
Last-modified
Content-Language
Cache-Control
Expires
Pragma
If it is not in this set, it must be present in the Access-Control-Expose-Headers header returned by the server.
About the case in question, if it is a CORS request, one will only be able to retrieve the Location header through the XMLHttpRequest object if, and only if, the header below is also present:
Access-Control-Expose-Headers: Location
If its not a CORS request, XMLHttpRequest will have no problem retrieving it.
var geturl;
geturl = $.ajax({
type: "GET",
url: 'http://....',
success: function () {
alert("done!"+ geturl.getAllResponseHeaders());
}
});
The unfortunate truth about AJAX and the 302 redirect is that you can't get the headers from the return because the browser never gives them to the XHR. When a browser sees a 302 it automatically applies the redirect. In this case, you would see the header in firebug because the browser got it, but you would not see it in ajax, because the browser did not pass it. This is why the success and the error handlers never get called. Only the complete handler is called.
http://www.checkupdown.com/status/E302.html
The 302 response from the Web server should always include an alternative URL to which redirection should occur. If it does, a Web browser will immediately retry the alternative URL. So you never actually see a 302 error in a Web browser
Here are some stackoverflow posts on the subject. Some of the posts describe hacks to get around this issue.
How to manage a redirect request after a jQuery Ajax call
Catching 302 FOUND in JavaScript
HTTP redirect: 301 (permanent) vs. 302 (temporary)
The underlying XMLHttpRequest object used by jQuery will always silently follow redirects rather than return a 302 status code. Therefore, you can't use jQuery's AJAX request functionality to get the returned URL. Instead, you need to put all the data into a form and submit the form with the target attribute set to the value of the name attribute of the iframe:
$('#myIframe').attr('name', 'myIframe');
var form = $('<form method="POST" action="url.do"></form>').attr('target', 'myIframe');
$('<input type="hidden" />').attr({name: 'search', value: 'test'}).appendTo(form);
form.appendTo(document.body);
form.submit();
The server's url.do page will be loaded in the iframe, but when its 302 status arrives, the iframe will be redirected to the final destination.
UPDATE 2018 FOR JQUERY 3 AND LATER
I know this is an old question but none of the above solutions worked for me. Here is the solution that worked:
//I only created this function as I am making many ajax calls with different urls and appending the result to different divs
function makeAjaxCall(requestType, urlTo, resultAreaId){
var jqxhr = $.ajax({
type: requestType,
url: urlTo
});
//this section is executed when the server responds with no error
jqxhr.done(function(){
});
//this section is executed when the server responds with error
jqxhr.fail(function(){
})
//this section is always executed
jqxhr.always(function(){
console.log("getting header " + jqxhr.getResponseHeader('testHeader'));
});
}
try this:
type: "GET",
async: false,
complete: function (XMLHttpRequest, textStatus) {
var headers = XMLHttpRequest.getAllResponseHeaders();
}
+1 to PleaseStand
and here is my other hack:
after searching and found that the "cross ajax request" could not get response headers from XHR object, I gave up. and use iframe instead.
1. <iframe style="display:none"></iframe>
2. $("iframe").attr("src", "http://the_url_you_want_to_access")
//this is my aim!!!
3. $("iframe").contents().find('#someID').html()
I'm starting to get stumped on this. I'm developing a C#.NET Web API service and frontend application to use it. I've been having a lot of difficulty using a token to authenticate my requests and jQuery seems to be having trouble. I can get a token just fine, but jQuery won't add it to an Authorization header in further requests.
My setup is an index.html page with several jQuery Mobile pages inside it. It starts on a '#login' page, which sends a request to my /Token URI with a username, password, and grant type. This is successful and the return is the token. The page changes to '#home' and a test ajax call is sent to /api/values to grab value. The problem is that instead of adding a header called 'Authorization', jQuery adds an 'Access-Control-Request-Headers' with the value 'accept, authorization' instead. At first I thought it was a CORS issue, but the request works fine when I use Advanced Rest Client in Chrome to send the request.
AJAX Call from '#Home'
$.ajax({
url: 'http://slalomtest2.azurewebsites.net/api/values/',
type: 'GET',
async: true,
dataType:"json",
beforeSend: function(request){
request.withCredentials = true;
request.setRequestHeader("Authorization", "Basic " + Token);
},
success: function(result){
console.log(result);
},
error: function(request, error){
$.mobile.changePage("#login");
}
});
The bad request the AJAX sends
This is what it looks like from Advanced Rest Client in the same browser
Thanks in advance for the help, I've been banging my head against the wall all day.