1

My Angular 1.5.8 web application is at http://www.example.com/foo/ and my RESTful list of bars is at http://www.example.com/foo/api/bars. When ui-router goes to the list of bars in Angular, my browser is at http://www.example.com/foo/#/bars. I simply want to connect to a RESTful resource to connect to http://www.example.com/foo/api/bars using HTTP GET.

So I try the most obvious thing:

$resource("api/bars/")

In my mind that should resolve api/bars/ to the current path http://www.example.com/foo/#/bars to give me http://www.example.com/foo/api/bar, right? But it doesn't work (even though I could swear it worked with $http). Instead it gives me a $resource:badcfg error.

Angular lets me do the following, but this doesn't produce the correct path, instead giving me http://www.example.com/api/bars:

$resource("/api/bars/")

So I try $browser.baseHref(), but that seems to be set to the empty string (why?), producing http://www.example.com/api/bars again.

$resource($browser.baseHref() + "/api/bars/")

I tried to use $location.path(), but Angular thinks I want the path after the hash sign, so that doesn't work, giving me http://www.example.com/bars/api/bars. Doh!

$resource($location.path() + "/api/bars/")

How can I simply resolve api/bars/ to the base path of the current URL http://www.example.com/foo/#/bars, producing http://www.example.com/foo/api/bars (or even just the path)?

Note that it is not acceptable for me to hard code an absolute path, or to change my HTML code. Why should I? Besides, this application will be mounted at two places on the same server (hey, it's easy with Java, Tomcat, and JAX-RS), at http://www.example.com/foo/ and http://www.example.com/foo-demo/. The application should run unmodified under each location, accessing the RESTful API list of bars at http://www.example.com/foo/api/bars and http://www.example.com/foo-demo/api/bars, respectively.

This is not complicated; this is simple "URI syntax 101" which has been outlined in RFCs for over two decades. I simply want to resolve api/bars/ to the base path of the current URL http://www.example.com/foo/#/bars. How do I do that in Angular 1.5?

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272

2 Answers2

1

OK, there's two ways to do this. If you absolutely want an absolute path, you can use this:

$resource(location.origin + location.pathname + "api/bars/")

Note the use of the location object location.origin to establish the protocol, domain, and port; and location.pathname to establish the base path. (Once again Microsoft will throw a wrench into the works: location.origin doesn't work on IE11 on some versions of Windows 10.)

But the better approach is simply to use:

$resource("api/bars")

"Wait, I thought you said that this will give you an error!" you might exclaim. Well it turns out I was wrong about that. I was indeed getting an error, but it was because I hadn't set the Accept header to ask for JSON, and the plain/text response I was getting (that's the default on my RESTful resource) was confusing $resource. It turns out that a relative URI will work after all.

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
  • That's fine and it also has a valuable information that not only the array vs. object problem can be a reason for the error you received. – Andreas Jägle Dec 09 '16 at 22:14
1

It is possible to use relative-path syntax for $resource as you can use it with $http which is used by $resource. This can be done by omitting the leading slash (as you suggested) or by prefixing the resource with ./.

Your badcfg error seems more likely to be the case because your request works out correctly but the server response does not match the expectations. So probably you are returning a single object instead of an array. Please use the dev tools to debug what is really returned from the server.

See the docs on $resource for details.

Andreas Jägle
  • 11,632
  • 3
  • 31
  • 31
  • You were right on all counts… but you seem to have been typing your answer just as I was typing mine, so you didn't see my post. Two minutes earlier and you would have beat me to it. ;) I would still mark yours as the correct answer because you went to all that work, but my answer does note a solution for creating an absolute, resolved path. Thanks for putting thought into your correct and competent response. – Garret Wilson Dec 09 '16 at 22:03