-1

I'm making an ajax call to a another page on my own domain. On this page however, I make an API call to Etsy's API. I get the JSON back, format it into XML, then echo $xml to return the data to the original ajax call. However, ajax.responseXML is always null! ajax.responseText does contain all the info I need though.

If instead of returning the XML-formatted JSON, I just return some XML without that data, (say... echo "<orders></orders>") then it works. And responseXML is not null.

So I'm thinking that even though my ajax call is calling another page on my domain, because that page is making an cross-domain call (Etsy API), it is violating the single origin policy and that is why responseXML is null?

Here's the call:

var ajax = new XMLHttpRequest();
     ajax.open("GET", "OrderFetcher.php?function=sort");
     ajax.onreadystatechange = function () {
     if (ajax.readyState === 4) {

     if (ajax.responseXML === null) {
          console.log("ajax.responseXML is null.");
     }

     ordersToSort = convertXmlToArray(ajax.responseXML);

};
ajax.send();

OrderFetcher.php contains the API call.

EDIT

Here's the php code ajax calls:

if (array_key_exists("function", $_GET)) {
if ($_GET["function"] === "sort") {

    header('Content-Type: text/xml');

    $fetchUrl = "https://openapi.etsy.com/v2/shops/__SELF__/receipts/open?limit=150&includes=Transactions,Listings";
    $orders = fetch(); // fetch() makes the API call via an Oauth object and oauth->fetch(...etc...etc...)

    $xml = "<orders>";

    foreach ($orders as $order) {
        $xml .= "<order>";
        $xml .= "<title>$order[title]</title>";
        $xml .= "<order_date>$order[order_date]</order_date>";
        $xml .= "<hidden_order_date>$order[hidden_order_date]</hidden_order_date>";
        $xml .= "<ship_date>$order[ship_date]</ship_date>";
        $xml .= "<addr_name>$order[addr_name]</addr_name>";
        $xml .= "<addr_line_1>$order[addr_line_1]</addr_line_1>";
        $xml .= "<addr_line_2>$order[addr_line_2]</addr_line_2>";
        $xml .= "<addr_city>$order[addr_city]</addr_city>";
        $xml .= "<addr_state>$order[addr_state]</addr_state>";
        $xml .= "<addr_zip>$order[addr_zip]</addr_zip>";
        $xml .= "<addr_country>$order[addr_country]</addr_country>";
        $xml .= "<price>$order[price]</price>";
        $xml .= "<quantity>$order[quantity]</quantity>";
        $xml .= "<message>$order[message]</message>";
        $xml .= "</order>";
    }

    $xml .= "</orders>";

    echo $xml;
}

I believe I've narrowed it down to something with the API call or ajax timing out. In the code above, if I comment out the API call and xml data and instead just do the below, it "returns" fine and ajax.responseXML is not null.

if (array_key_exists("function", $_GET)) {
    if ($_GET["function"] === "sort") {

        header('Content-Type: text/xml');

        //$fetchUrl = "https://openapi.etsy.com/v2/shops/__SELF__/receipts/open?limit=150&includes=Transactions,Listings";
        //$orders = fetch();
        // Remove xml string building code.

        echo "<xmltag>Test</xmltag>";
     }
}

EDIT 2

When I open "OrderFetcher.php?function=sort" (the ajax call) in my browser it runs for a few seconds (making API call) then gives me this:


This page contains the following errors:

error on line 1 at column 1: Document is empty Below is a rendering of the page up to the first error.


However, I'm not convinced something that Etsy is returning is causing invalid XML, because of these two points I mentioned above:

  1. If I ignore the API data (but still make the API call) and return a simple XML string (echo "<tag></tag>"), then responseXML will still be null, even though I'm not "echo-ing" any of the data from the API call.

This doesn't work (ajax.responseXML is null):

$orders = fetch();  
echo "<xmltag>Test</xmltag>";
  1. If I return the simple XML string (echo "<tag></tag>") but also remove the API call altogether, suddenly responseXML is valid and not null!

This does work (ajax.responseXML is not null):

//$orders = fetch();  
echo "<xmltag>Test</xmltag>";
Nick H
  • 217
  • 4
  • 19
  • This is happening in a browser? What is the console telling you? The ajax call is not cross domain because you're calling a script on the same site.. The PHP may do a call to a remote endpoint but that has nothing to do with your JS – Dale Jun 15 '17 at 17:24
  • responseXML is only filled if the data being returned can be parsed as XML/HTML. Might need to tell the XHR to expect xml or make sure your server script is outputing the correct content-type header – Patrick Evans Jun 15 '17 at 17:28
  • You might need to show your php code. it looks like you are constructing the XML in your php file. So show how you are returning the response from the php file – karthick Jun 15 '17 at 17:43
  • Ok I've narrowed it down to the API call - I think because it's taking too long. It takes about 5-7 seconds, before that ajax tries to use responsXML and that's why it's empty. There is a way to set a timeout for an ajax call correct? – Nick H Jun 15 '17 at 17:49
  • @Dale the console is showing an error and stopping execution when it tries to call a 'getElementsByTagName' on ajax.responseXML, it says it's null. – Nick H Jun 15 '17 at 21:56
  • the request taking too long shouldn't be causing this problem. The request failing or timing out, however, very well could. – Kevin B Jun 15 '17 at 21:57
  • @KevinB the API call does return successfully, ajax.responseText contains all the data I need (except with my added XML tags) and I've tested the API call when isolated. Perhaps ajax tries to access responseXML before the API call has finished? – Nick H Jun 15 '17 at 21:58
  • or, perhaps the xml isn't xml? opening the endpoint (your server) directly in the browser would tell you if it was invalid and why. Given your code, i could think of quite a few values that etsy could return that would result in your endpoint generating invalid xml. – Kevin B Jun 15 '17 at 21:59
  • @KevinB I though that too, but I don't think this is the case based on my second edit (see above). Even if I ignore the data returned from the API call, and echo a simple XML string, ajax.responseXML is still null. – Nick H Jun 15 '17 at 23:04

1 Answers1

0

Wow this was just a noob mistake. In my fetch() function (that makes the API call) I had an echo "something" in there. Therefore that was getting executed before echo $xml causing the errors I was experiencing.

Nick H
  • 217
  • 4
  • 19