tikalk/commandcar

SyntaxError: Unexpected token <

mihaiolteanu opened this issue · 5 comments

[Solution: Make sure your call returns a JSON response not an XML one (use format=json or something similar)]

I'm trying to create an API for last.fm, but I'm getting this error:

SyntaxError: Unexpected token <
    at Object.parse (native)
    at Request._callback (/usr/local/lib/node_modules/commandcar/main.js:346:21)
    at Request.self.callback (/usr/local/lib/node_modules/commandcar/node_modules/request/request.js:198:22)
    at Request.EventEmitter.emit (events.js:98:17)
    at Request.<anonymous> (/usr/local/lib/node_modules/commandcar/node_modules/request/request.js:1035:10)
    at Request.EventEmitter.emit (events.js:117:20)
    at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/commandcar/node_modules/request/request.js:962:12)
    at IncomingMessage.EventEmitter.emit (events.js:117:20)
    at _stream_readable.js:920:16
    at process._tickCallback (node.js:415:13)

when I call commandcar thus:
commandcar lastfm.artist_getSimilar --artist airbag -k myapikey
after a
sudo commandcar load --location ~/projects/commandcar/lastfm

The lastfm folder contains the api.json file:

{
    "protocol": "https",
    "hostname": "ws.audioscrobbler.com/2.0",
    "use_options": [
        {
            "short": "k",
            "long": "api_key",
            "def": "api_key",
            "desc": "api_key",
        }
    ]
}

and a commands folder inside it with the artist_getSimilar.json file:

{
    "path_template": "/?method=artist.getSimilar&artist={artist}&limit=5&api_key={api_key}",
    "ret": "name",
    "options": [
        {
            "short": "a",
            "long": "artist",
            "def": "artist name",
            "desc": "artist",
        },
        {
            "short": "k",
            "long": "api_key",
            "def": "apikey",
            "desc": "access token",
        }
    ]
}

The response I'm getting in the browser, with the following call
https://ws.audioscrobbler.com/2.0/?method=artist.getSimilar&artist=airbag&limit=5&api_key=myapikey
is something like this:

<?xml version="1.0" encoding="UTF-8" ?>
<lfm status="ok"><similarartists artist="Airbag"><artist><name>Nosound</name>
<mbid>797c5264-2edc-4718-b3fc-ee30b343a0fd</mbid>
<match>1</match>
<url>http://www.last.fm/music/Nosound</url>
<image size="small">http://img2-ak.lst.fm/i/u/34s/b7b889567c9245b292ed8fc034edf8ec.png</image>
<image size="medium">http://img2-ak.lst.fm/i/u/64s/b7b889567c9245b292ed8fc034edf8ec.png</image>
<image size="large">http://img2-ak.lst.fm/i/u/174s/b7b889567c9245b292ed8fc034edf8ec.png</image>
<image size="extralarge">http://img2-ak.lst.fm/i/u/300x300/b7b889567c9245b292ed8fc034edf8ec.png</image>
<image size="mega">http://img2-ak.lst.fm/i/u/b7b889567c9245b292ed8fc034edf8ec.png</image>
<image size="">http://img2-ak.lst.fm/i/u/arQ/b7b889567c9245b292ed8fc034edf8ec.png</image>
<streamable>0</streamable>
</artist>
<artist><name>RPWL</name>
<mbid>80301f91-cb5a-4f02-bd2a-ead999a7dc06</mbid>
<match>0.778902</match>
<url>http://www.last.fm/music/RPWL</url>
<image size="small">http://img2-ak.lst.fm/i/u/34s/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<image size="medium">http://img2-ak.lst.fm/i/u/64s/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<image size="large">http://img2-ak.lst.fm/i/u/174s/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<image size="extralarge">http://img2-ak.lst.fm/i/u/300x300/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<image size="mega">http://img2-ak.lst.fm/i/u/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<image size="">http://img2-ak.lst.fm/i/u/arQ/e3e2a5496af34b64bf3ad02d983986ea.png</image>
<streamable>0</streamable>
</artist>
...
</similarartists>
</lfm>

I believe the error occurs because your hostname contains a path section ("/2.0"). This should go on the path template instead. Can you try that out and see if it works?

Same error.

Oh, I see. I think it has to do with the fact you get xml as response, and I guess it tries to parse it as json. Can you ask the api for a json response instead using some parameter? usually that's the case. If not I'll have to add it to the list...

Oh, ok. I haven't thought about that. I've added format=json to the path_template. That seems to solve it.

But, and this might be another topic, is there a way to specify more precisely what is to be returned? I'm specifying name in ret but that gives me a response like undefined.
I can only give ret the outermost element, similarartists in this case, but I would expect something like similarartists/artist/name, where the json structure is:

{
    "similarartists": {
        "artist": [
            {
                "name": "Nosound",
                ......
            },
            {
                "name": "RPWL",
                ......
            }
        ]
       ....
    }
}

So that, in this case, commandcar would return Nosound, RPWL, ...

Good point. I need to rethink the "ret" issue.