55

I am using JQuery ajax jsonp. I have got below JQuery Code:

 $.ajax({  
        type:"GET",        
        url: "Login.aspx",  // Send the login info to this page
        data: str, 
        dataType: "jsonp", 
        timeout: 200000,
        jsonp:"skywardDetails",
        success: function(result)
        { 
             // Show 'Submit' Button
            $('#loginButton').show();

            // Hide Gif Spinning Rotator
            $('#ajaxloading').hide();  
         } 

    });  

The above code is working fine, I just want to send the request as "POST" instead of "GET", Please suggest how can I achieve this.

Thanks

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Manoj Singh
  • 7,569
  • 34
  • 119
  • 198

6 Answers6

88

You can't POST using JSONP...it simply doesn't work that way, it creates a <script> element to fetch data...which has to be a GET request. There's not much you can do besides posting to your own domain as a proxy which posts to the other...but user's not going to be able to do this directly and see a response though.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • Can you please suggest, how can I restrict the encrypt passed URL, so that no one can see as it is POST. – Manoj Singh Dec 22 '10 at 10:34
  • 1
    @MKS - You can't really, not without proxying it through your own domain...GET requests are inherently "open", much more so than a POST – Nick Craver Dec 22 '10 at 10:36
  • Thanks @NICK, can you please suggest is it safe going with "GET" instead of "POST", what can be the drawbacks of using "GET"..please suggest – Manoj Singh Dec 22 '10 at 10:38
  • 1
    @T.J. - well, with SSL is can be drastically more secure though, if your payload is in the POST and not the URL, that was more what I was aiming at. – Nick Craver Dec 22 '10 at 10:40
  • @MKS - If you're doing something secure, use SSL to begin with. In absence of that, does the page need the data? a hacky-ish ` – Nick Craver Dec 22 '10 at 10:41
  • Thanks @Nick, can you please suggest any example where IFRAME is used for this! – Manoj Singh Dec 22 '10 at 10:43
  • @MKS - I'd ask a separate question on this...it's going to get really messy in comments, and I have to drive 100 miles to work very soon...some others can help out long after that. Look and see first if there's another question on this, cross-domain posting with an iframe for example. – Nick Craver Dec 22 '10 at 10:47
  • Thank you, I've been trying this impossibility for like 8 hours... That would explain all the whys of the can'ts. – Érik Desjardins Apr 03 '12 at 14:05
  • 4
    The notion that GET requests over SSL are less secure than POSTs when in transit is incorrect. URL info such as path, query string, etc are all encrypted as part of the HTTP request. Your query string cannot be "sniffed" at the packet level. There are other concerns, however, as outlined in the answer to [this SO question](http://stackoverflow.com/questions/323200/is-a-https-query-string-secure) – Sean Jan 10 '13 at 20:33
  • @NickCraver but dataType is the data type I expect to get, so I need the returned data wrapped in – hayley Jun 05 '22 at 18:17
41

Use json in dataType and send like this:

    $.ajax({
        url: "your url which return json",
        type: "POST",
        crossDomain: true,
        data: data,
        dataType: "json",
        success:function(result){
            alert(JSON.stringify(result));
        },
        error:function(xhr,status,error){
            alert(status);
        }
    });

and put this lines in your server side file:

if PHP:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Max-Age: 1000');

if java:

response.addHeader( "Access-Control-Allow-Origin", "*" ); 
response.addHeader( "Access-Control-Allow-Methods", "POST" ); 
response.addHeader( "Access-Control-Max-Age", "1000" );
Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
  • The other answer explains the reasoning behind this code: http://stackoverflow.com/a/4528304/102960 – igorsantos07 Nov 21 '13 at 21:25
  • 2
    Are there any potential security implications (e.g. CSRF) in allowing any 3rd-party site to initiate AJAX calls to your site's application, via these response header settings? – Jon Schneider Jan 02 '14 at 21:28
  • 1
    This did not work for me using Chrome v.36.0.1985.125. I received the error standard - no 'Access-Control-Allow-Origin' header even though I have this in PHP and can see it under the headers in the retrieved file in the network tab. The exact same request works when using 'GET'. I have tried a number of permutations, so I would be concerned if you want to use this answer that it may not work for all browsers. – Luke Aug 11 '14 at 03:21
  • 2
    Please note that part of the point of jsonp is to be able to have the browser send cookies along. The code as it is here will not accomplish that. For that you may have to turn on credentials as per this document: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Requests_with_credentials – ragamufin Oct 07 '14 at 07:26
  • what if we are using ASP.NET c#? Seriously I've been stuck at this step for ages I cant get past it and I am about to lose my mind! :) –  May 07 '15 at 08:48
7

Modern browsers allow cross-domain AJAX queries, it's called Cross-Origin Resource Sharing (see also this document for a shorter and more practical introduction), and recent versions of jQuery support it out of the box; you need a relatively recent browser version though (FF3.5+, IE8+, Safari 4+, Chrome4+; no Opera support AFAIK).

Tgr
  • 27,442
  • 12
  • 81
  • 118
  • 1
    And just to nitpick, JSONP is not AJAX. – Tgr Dec 24 '10 at 20:52
  • 5
    Actually I would nitpick a bit further and say JSONP is not XMLHttpRequest but it is AJAX. AJAX is ill defined anyway since it wouldn't strictly cover fetching JSON rather than XML or fetching synchronously. So given that AJAX is used more broadly than it's defined already plus the fact that JSONP is mostly used with asynchronous Javascript, I'm perfectly happy saying AJAX also covers JSNOP. – hippietrail Dec 22 '11 at 10:02
  • The important bit here seems to be to set an HTTP header of `Access-Control-Allow-Origin: *` or something similar. (You can declare individual allowed origins) – jocull May 21 '12 at 21:19
  • 1
    But you're still [conventionally] limited to only use GET, not POST, with JSONP requests, right? That is, I'm missing how this answer answers the OP's question. Just that, if you have to use POST (which probably is the "real" question here), you have options other than JSONP? – ruffin Nov 08 '13 at 15:19
  • If you, like me, got wondering how to implement this, look for the other answer in this same question: http://stackoverflow.com/a/17722058/102960 – igorsantos07 Nov 21 '13 at 21:25
0

If you just want to do a form POST to your own site using $.ajax() (for example, to emulate an AJAX experience), then you can use the jQuery Form Plugin. However, if you need to do a form POST to a different domain, or to your own domain but using a different protocol (a non-secure http: page posting to a secure https: page), then you'll come upon cross-domain scripting restrictions that you won't be able to resolve with jQuery alone (more info). In such cases, you'll need to bring out the big guns: YQL. Put plainly, YQL is a web scraping language with a SQL-like syntax that allows you to query the entire internet as one large table. As it stands now, in my humble opinion YQL is the only [easy] way to go if you want to do cross-domain form POSTing using client-side JavaScript.

More specifically, you'll need to use YQL's Open Data Table containing an Execute block to make this happen. For a good summary on how to do this, you can read the article "Scraping HTML documents that require POST data with YQL". Luckily for us, YQL guru Christian Heilmann has already created an Open Data Table that handles POST data. You can play around with Christian's "htmlpost" table on the YQL Console. Here's a breakdown of the YQL syntax:

  • select * - select all columns, similar to SQL, but in this case the columns are XML elements or JSON objects returned by the query. In the context of scraping web pages, these "columns" generally correspond to HTML elements, so if want to retrieve only the page title, then you would use select head.title.
  • from htmlpost - what table to query; in this case, use the "htmlpost" Open Data Table (you can use your own custom table if this one doesn't suit your needs).
  • url="..." - the form's action URI.
  • postdata="..." - the serialized form data.
  • xpath="..." - the XPath of the nodes you want to include in the response. This acts as the filtering mechanism, so if you want to include only <p> tags then you would use xpath="//p"; to include everything you would use xpath="//*".

Click 'Test' to execute the YQL query. Once you are happy with the results, be sure to (1) click 'JSON' to set the response format to JSON, and (2) uncheck "Diagnostics" to minimize the size of the JSON payload by removing extraneous diagnostics information. The most important bit is the URL at the bottom of the page -- this is the URL you would use in a $.ajax() statement.

Here, I'm going to show you the exact steps to do a cross-domain form POST via a YQL query using this sample form:

<form id="form-post" action="https://www.example.com/add/member" method="post">
  <input type="text" name="firstname">
  <input type="text" name="lastname">
  <button type="button" onclick="doSubmit()">Add Member</button>
</form>

Your JavaScript would look like this:

function doSubmit() {
  $.ajax({
    url: '//query.yahooapis.com/v1/public/yql?q=select%20*%20from%20htmlpost%20where%0Aurl%3D%22' +
         encodeURIComponent($('#form-post').attr('action')) + '%22%20%0Aand%20postdata%3D%22' +
         encodeURIComponent($('#form-post').serialize()) +
         '%22%20and%20xpath%3D%22%2F%2F*%22&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=',
    dataType: 'json', /* Optional - jQuery autodetects this by default */
    success: function(response) {
      console.log(response);
    }
  });
}

The url string is the query URL copied from the YQL Console, except with the form's encoded action URI and serialized input data dynamically inserted.

NOTE: Please be aware of security implications when passing sensitive information over the internet. Ensure the page you are submitting sensitive information from is secure (https:) and using TLS 1.x instead of SSL 3.0.

thdoan
  • 18,421
  • 1
  • 62
  • 57
-1

Here is the JSONP I wrote to share with everyone:

the page to send req
http://c64.tw/r20/eqDiv/fr64.html

please save the srec below to .html youself
c64.tw/r20/eqDiv/src/fr64.txt
the page to resp, please save the srec below to .jsp youself
c64.tw/r20/eqDiv/src/doFr64.txt

or embedded the code in your page:

function callbackForJsonp(resp) {

var elemDivResp = $("#idForDivResp");
elemDivResp.empty();

try {

    elemDivResp.html($("#idForF1").val() + " + " + $("#idForF2").val() + "<br/>");
    elemDivResp.append(" = " + resp.ans + "<br/>");
    elemDivResp.append(" = " + resp.ans2 + "<br/>");

} catch (e) {

    alert("callbackForJsonp=" + e);

}

}

$(document).ready(function() {

var testUrl = "http://c64.tw/r20/eqDiv/doFr64.jsp?callback=?";

$(document.body).prepend("post to " + testUrl + "<br/><br/>");

$("#idForBtnToGo").click(function() {

    $.ajax({

        url : testUrl,
        type : "POST",

        data : {
            f1 : $("#idForF1").val(),
            f2 : $("#idForF2").val(),
            op : "add"
        },

        dataType : "jsonp",
        crossDomain : true,
        //jsonpCallback : "callbackForJsonp",
        success : callbackForJsonp,

        //success : function(resp) {

        //console.log("Yes, you success");
        //callbackForJsonp(resp);

        //},

        error : function(XMLHttpRequest, status, err) {

            console.log(XMLHttpRequest.status + "\n" + err);
            //alert(XMLHttpRequest.status + "\n" + err);

        }

    });

});

});