7

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.

eeadev
  • 3,662
  • 8
  • 47
  • 100

2 Answers2

5

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.

Community
  • 1
  • 1
koox00
  • 2,691
  • 2
  • 15
  • 25
  • I dont understand, shall I use a workaround in order to make it work with Redmine API? If so, what happens when they fix it? – eeadev Dec 29 '15 at 11:01
  • 1
    according to the issue page on github angular team isn't oing to change this. It's up to the redmine team I guess. You can always set up CORS correctly and use json instead of jsonp – koox00 Dec 29 '15 at 11:05
  • 1
    I've updated my answer. added links to read more info about this. there is also an issue on redmine http://www.redmine.org/issues/13718#change-58154 – koox00 Dec 29 '15 at 11:20
  • how to setup CORS correctly with redmine and use json? – eeadev Dec 29 '15 at 11:33
  • maybe it's better to make a new question about that so we don't bloat this one and also get more help :) – koox00 Dec 29 '15 at 11:34
  • thank you for your time, but I cannot accept this answer, because it doesnt fix the jsonp issue, neither is very well explained because first it says that there is a problem in my code and then offer other solutions – eeadev Dec 29 '15 at 13:58
  • 2
    Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99209/discussion-between-koox00-and-eeadev). – koox00 Dec 29 '15 at 14:01
0

I see your console showing this:-

GET http://muser:mpasswd@myredmine/issues.json?callback=displayIssues

That's not technically a valid URL in HTTP. The username and password, shouldn't be in the GET call they should be in the header, according to.

https://en.wikipedia.org/wiki/Basic_access_authentication

A quick search on google found this https://docs.angularjs.org/api/ng/service/$http and angularjs basic authentication headers

I've not looked at redmine for years, and it might handle dodgy HTTP fine simply with the options earlier answers have specified, but if that doesn't work, check if the request is actually getting to Redmine properly

Community
  • 1
  • 1
sibaz
  • 1,242
  • 14
  • 26