Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jsonp getting 404 when calling Redmine API

I am trying to consume Redmine API from an angularjs project.

I ended up using jsonp in order to solve CORS problem.

I receive 404 when calling this:

var url = 'http://muser:mpasswd@myredmine/issues.json?callback=displayIssues';
 $http({
                method: 'JSONP',
                url: url
            }).
            success(function (data, status) {
                console.log("success");
                console.log(data);
            }).
            error(function (data, status) {
                console.log("Error: " + status);
            });
...
    function displayIssues(issues) {
                console.log('displayIssues');
                ...
            }

But when I call the same url with Postman, it works.

Why do I receive this 404?

here is my console:

GET http://muser:mpasswd@myredmine/issues.json?callback=displayIssues jsonpReq @ angular.js:8576(anonymous function) @ angular.js:8420sendReq @ angular.js:8291serverRequest @ angular.js:8025wrappedCallback @ angular.js:11498wrappedCallback @ angular.js:11498(anonymous function) @ angular.js:11584Scope.$eval @ angular.js:12608Scope.$digest @ angular.js:12420Scope.$apply @ angular.js:12712(anonymous function) @ angular.js:18980x.event.dispatch @ jquery-2.0.3.min.js:5y.handle @ jquery-2.0.3.min.js:5
authentication.service.js:100 Error: 404

Rest API and jsonp are both enabled in the admin->setting->auth

I also tried:

        var url = 'http://muser:mpasswd@myredmine/redmine/issues.json&callback=JSON_CALLBACK';
        $http.jsonp(url, {
            params: {
                callback: 'JSON_CALLBACK',
                format: 'json'
            }
        }).success(function (data) {
            console.log('ok');
        }).error(function (data) {
            console.log('error: ' + JSON.stringify(data));
        });

getting this:

GET http://muser:mpasswd@myredmine/issues.json&callback=angular.callbacks._0?callback=JSON_CALLBACK&format=json jsonpReq @ angular.js:8576(anonymous function) @ angular.js:8420sendReq @ angular.js:8291serverRequest @ angular.js:8025wrappedCallback @ angular.js:11498wrappedCallback @ angular.js:11498(anonymous function) @ angular.js:11584Scope.$eval @ angular.js:12608Scope.$digest @ angular.js:12420Scope.$apply @ angular.js:12712(anonymous function) @ angular.js:18980x.event.dispatch @ jquery-2.0.3.min.js:5y.handle @ jquery-2.0.3.min.js:5
services.js:35 error: undefined

Also, when calling this:

var url = 'http://muser:mpasswd@myredmine/redmine/issues.json&callback=JSON_CALLBACK';
            $http.jsonp(url).success(function (data) {
                console.log('success');
            }).error(function (error) {
                console.log('error:: ' + error);
            });

I get the same error

Please consider that muser, mpasswd and myredmine are just examples.

like image 290
eeadev Avatar asked Dec 16 '15 16:12

eeadev


1 Answers

From the ngDocs:

The name of the callback should be the string JSON_CALLBACK

Angular will replace that string internally with an angular.callbacks_{0-9a-z}

So first change your code to this:

var url = 'http://muser:mpasswd@myredmine/redmine/issues.json?callback=JSON_CALLBACK';
$http.jsonp(url).succe...

Playing with this fiddle it seems that Redmine strips the dot . from urls thus making angular.callbacks_0 to angularcallback_0 which is undefined.
You can read more on github, there is an issue about this.

POSSIBLE SOLUTIONS

1) There is a hack posted by another user on SO here to change the name of the callback to a custom one.

Working fiddle according to @Todi-Adiatmo's hack.

2) Another solution according to @dancras found on the issue posted on github is to define the undefined angularcallbacks_{..} with the call to angular.callbacks_{..} and then delete the global angularcallbacks_.
You have to use this immediately before the jsonp call:

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

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

Working fiddle according to @danca's solution.

like image 173
koox00 Avatar answered Sep 28 '22 10:09

koox00