Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

JSONP Callback function $http #1551

Closed
todiadiyatmo opened this issue Nov 10, 2012 · 37 comments
Closed

JSONP Callback function $http #1551

todiadiyatmo opened this issue Nov 10, 2012 · 37 comments

Comments

@todiadiyatmo
Copy link

Hi i'am quite new in angular.

I'am triying to use the $http module for xhr request.

However, the callback name must be "JSONP_CALLBACK" in which angular will turn the callback name to callback=angular.callbacks._1

There's some web web service which cannot accept "angular.callbacks._1 "callback name, for example

http://dev.markitondemand.com/Api/Lookup/jsonp?input=GM&callback=callback=angular.callbacks._1

i solve this with a messy hack found on stackoverflow

http://jsfiddle.net/pMGgR/

@raghur
Copy link

raghur commented Nov 28, 2012

me too - using the windows ACS service and it doesnt like the call back name

@pkozlowski-opensource
Copy link
Member

@raghur @todiadiyatmo do you guys know what upsets your JSONP endpoints with the callback names generated by AngularJS? Is it a dot? Or underscore? Or sth else altogether?

Getting rid of a dot might be problematic since callbacks would have to be registered in a global (window) scope....

@mawo87
Copy link

mawo87 commented Dec 10, 2012

I had the same problem with the TrustYou API. I suspect the dot being the issue ...
I also came across the hack on stackoverflow but I decided to use jQuery.getJSON in this particular case instead

@raghur
Copy link

raghur commented Dec 24, 2012

@pkozlowski-opensource - In the Chrome network console, if I click on the url to ACS, I get an ACS error page that tells me that the callback name is invalid.

@patrickkettner
Copy link

@haraldringvold I would sugest opening a new issue if you are having one, otherwise stackexchange would be the best place to ask a more general question like this.

@dancras
Copy link

dancras commented Mar 30, 2013

I'm having the same trouble with a third party API (all the dots being removed from the callback function name). Since my search brought me here I figure adding the following snippet here might be useful for others who find themselves in the same situation.

Add the following immediately before making a jsonp request.

var c = $window.angular.callbacks.counter.toString(36);

$window['angularcallbacks_' + c] = function (data) {
    $window.angular.callbacks['_' + c](data);
    delete $window['angularcallbacks_' + c];
};

The main problem is that this relies heavily on angular's current jsonp implementation and is likely to need maintenance in the future.

As a more permanent solution the framework could have a low level service purely for registering globals (heavily and uniquely prefixed so that multiple angular apps don't collide), which would also make cleaning up after an app much simpler.

@btford btford closed this as completed Aug 24, 2013
@btford
Copy link
Contributor

btford commented Aug 24, 2013

As part of our effort to clean out old issues, this issue is being automatically closed since it has been inactivite for over two months.

Please try the newest versions of Angular (1.0.8 and 1.2.0-rc.1), and if the issue persists, comment below so we can discuss it.

Thanks!

@wildavies
Copy link

I am getting the same issue on the CIneworld API, but I have used it without issue on other API's.
It definitely seems as though some web services can't accept a callback name in the format "angular.callbacks._1"

It happens whether I use $http.jsonp, $http.get or .get as part of a service with AngularJS 1.0.7 and also 1.0.8.

I can use jQuery instead or the alternative fix (http://stackoverflow.com/questions/13267285/angular-resource-with-jsonp-not-working), but it would be nice to use the full features of AngularJS.

@chrism2671
Copy link

I tested it with 1.0.8 & 1.2.0rc1 and have the same problem with both.

@rixrix
Copy link
Contributor

rixrix commented Sep 24, 2013

This isn't working for me.

version: 1.0.8
OS: Mountain Lion

I did a JSONP request on one of the file hosted at Github, like so

$http.json("https://raw.github.com/<username>/<reponame>/master/somedata.json?callback=JSON_CALLBACK")

ATM, the work-around mentioned by @williamtdavies worked for me

cheers

@petebacondarwin
Copy link
Contributor

Let's move this discussion to #3073

@TWiStErRob
Copy link

There's no point in merging this to #3073 because the problem caused by this bit:

'angular.callbacks.' + callbackId

which still exists in that pull request.
That is the dots will still be in callback=... and hence not all endpoints out there in the wild will work.
I'm using 1.2.4.

(I'd like to point out that I've watch/read a few tutorials and I was impressed with angular, until I wrote

$resource('http://...', { ..., callback: 'JSON_CALLBACK' }, ...);

as my 10th ever line of angular code, now I am really disappointed!)

@doneyourdamage
Copy link

This is also a problem for me.

"ReferenceError: JSONP_CALLBACK is not defined" on fully valid JSONP

@vincentbernat
Copy link

Hi!

I also have the problem. An API is ignoring the provided callback if it contains a dot. I have tried @dancras workaround but it doesn't work for me because I am doing parallel requests and the first few ones will use the same callbacks and the results will be mixed for the next ones.

@caitp
Copy link
Contributor

caitp commented Jul 11, 2014

Honestly, if an API can't deal with a dot or square brackets for the callback name, then that's really a bug to file on the API. You should typically only need to use JSONP in small demo applications, since larger scale apps should have the resources to set up CORS properly and avoid issues with XMLHttpRequest.

Strongly advise you bring this up with the web service you're having trouble with.

@vincentbernat
Copy link

Ultimately yes, but this thread seems to show that many API have those restrictions. I am dealing with a commercial API that I am unlikely to be able to change in a short timeframe. It supports CORS but it also requires basic authentication and they didn't configure the CORS part for that (they don't allow the Authorization header and they return a wildcard as allowed origin).

@caitp
Copy link
Contributor

caitp commented Jul 11, 2014

Polluting the global namespace is not really in the cards, so this is a problem for web services to deal with --- this is not an angular issue.

@blowsie
Copy link

blowsie commented Aug 18, 2014

While I can see @caitp's perspective:

--- this is not an angular issue.

Do you not think its a good approach to try cater for environments?

For example, what would jQuery be, if they just said "this is not a jquery issue" every time they ran into a browser issue?

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

It's not a browser issue either, it's literally "your web service needs to be a bit better and let you specify callbacks as properties of objects". Without this, all you can do is make it call global functions on window, and I don't think it's really in the cards for angular to support this

@TWiStErRob
Copy link

In an ideal world, that's true (also it's not "our" web service, it's third party), but there are more rigid platforms/services/companies/processes. There's no business value in making any HTTP endpoint modification to support calls from Angular, however if Angular's view is more flexible (i.e. you relax your statement and allow some exceptions when necessary) it'll be more widely used. I think there are more web services out there in the wild not supporting this than the number of seconds it may take to you fix (implement) this.

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

Don't think of it as "supporting angular", think of it as "supporting JSONP".

Now, arguably there is no point in supporting JSONP because it's really just a hack to avoid CORS issues, which are hopefully handled more gracefully on your web service and you should use them. But if you do want to support JSONP, then support it properly, javascript references are not always to objects in global.

@blowsie
Copy link

blowsie commented Aug 18, 2014

@dancras thanks for a solution however, angular uses the alphabet after 9 requests eg. angularcallbacks_a, which causes the solution to break

@TWiStErRob
Copy link

@caitp Hmm, I think I see something in this. When you say "your web service" you mean the backend for my Angular browser app. Now, what if I have a third party public API which I want to write a specific app upon and I don't want to create a backend just so I can wrap all the calls and have the endpoint in the same domain (note this means maintaining my own server, quota, availability, cache, auth, etc. when the public endpoint already does all that) , while I can just use JSONP. If I create my own server (with features listed above) just for mirroring an API and working around CORS I think that's the situation Hungarians refer to as "Shooting sparrows with a cannon". I know in the serious business world one must have a backend because usually they write their own stuff, but there are other uses of Angular, I think.

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

@blowsie what web service are you using which is doing this wrong? Is it your own web service or a third party one? If third party, file a bug, and if it's your own, fix your web service. It's really a server-side bug, not a client-side bug.

@blowsie
Copy link

blowsie commented Aug 18, 2014

@caitp in this case its redmine.
http://www.redmine.org/issues/13718#change-58154

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

well heres your problem: http://www.redmine.org/projects/redmine/repository/entry/trunk/lib/redmine/views/builders/json.rb#L30 --- looks like a pretty trivial patch to write, good first bug.

@dancras
Copy link

dancras commented Aug 18, 2014

@blowsie Yeah it's over a year old so I imagine a lot has changed since it was written.

Perhaps a suitable solution would be to have a configurable json callback strategy object on the $httpProvider, responsible for storing and retrieving json callbacks, with the current implementation as the default strategy. That way if people are stuck using closed source, slow moving APIs they have the means to solve this issue without the majority having to suffer from a crufty solution in angular itself.

It's been a while since I checked the code in this area so I couldn't say how feasible it is.

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

The solution is to stop treating it as an angular bug and get your web service developers to fix their jsonp support. Really. Angular's callback routine is perfectly valid, web services are doing the wrong thing when they get this wrong, and it's not very much effort to fix it. Step up to the plate and submit a patch if it's something you care about, you know?

@blowsie
Copy link

blowsie commented Aug 18, 2014

Thanks @caitp I see what your saying, unfortunately submitting a patch may be out of the question, as I don't know ruby.

@blowsie
Copy link

blowsie commented Aug 18, 2014

Ahh missed your previous comment, It appears to be some simple regex which I could submit a patch for, thanks.

@TWiStErRob
Copy link

@caitp I agree it's their fault, the funny thing is most of these endpoints treat this bug as a feature, as in they introduced it intentionally for some reason (security?) :)

@blowsie careful, Ruby may have a different flavor than you know (even different versions may differ).

@vincentbernat
Copy link

@caitp A third-party API provider could just say that their JSONP implementation works fine with jQuery and the bug should be on our side. This is an endless debate, there is no JSONP specification: they can just say that what is expected is a function name (aka an identifier name) where a dot is not valid.

The easiest moving part here is AngularJS.

@caitp
Copy link
Contributor

caitp commented Aug 18, 2014

No, the easiest thing is fixing this in your providers --- polluting the global namespace is not in the cards.

@katzlbt
Copy link

katzlbt commented Apr 23, 2015

The pyramid web framework disallows angular callbacks since newer versions.
https://pyramid.readthedocs.org/en/master/_modules/pyramid/renderers.html
JSONP_VALID_CALLBACK = re.compile(r"^[a-zA-Z_$][0-9a-zA-Z_$]+$")

@mnieper
Copy link

mnieper commented Aug 18, 2015

Loading the Google API Client Library for Javascript doesn't support callbacks that do not exist as a property on the window object either: https://developers.google.com/api-client-library/javascript/start/start-js.

The canonical solution seems to be to adding a property to the global object: https://github.com/GoogleCloudPlatform/appengine-endpoints-tictactoe-python/blob/master/static/js/render.js#L122

@codeofsumit
Copy link

works for $resource. Doesn't work for $http.

@buffcode
Copy link

Sorry but this is ***:

the easiest thing is fixing this in your providers

So the easiest thing is fixing a uncountable amount of webservices whose developers set too strict/dumb/... rules for callbacks instead of allowing to override the callback and offering a viable, cost-effective solution? There are a lot of services - even in real corporate situations - where "fixing the providers" is not an option (by costs, corporate politics or time / priority until this would be patched).

I understand the problem of polluting the global namespace, but in my opinion it is in the developer's hand to use a (probably inefficient) workaround if he needs to. There are also a lot of other ways to mis-use angular and write inefficient code. It is up to the developer to decide what and how to to use the possibilities.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests