I'm using several Angular JS $resource definitions all of which retrieve their base URL from a configuration service. For example:
$resource(config.baseURL() + '/api/v2/foo/:id', {id: '@id'})
$resource(config.baseURL() + '/api/v2/bar/:id', {id: '@id'})
The reason this is done is that the base URL can be changed via a query string parameter when the application is first loaded.
I figured out that (obviously in retrospect) the URL used by the $resource is initialized just once so it's possible to get a race condition where the URL for a particular $resource is initialized before the base URL query string parameter is dealt with. So I tried to change the $resource declaration to this:
$resource(':baseURL/api/v2/foo/:id', {baseURL: config.baseURL(), id: '@id'})
Unfortunately the base URL is getting escaped – the //
is converted to %2F%2F
– so the whole URL then doesn't work properly.
Is there any way to suppress the escaping for that parameter? (or maybe a better way to solve the problem in general)?
Another way you can tackle this is use a provider and config it in the config stage.
Here is an example of something similar I did a while back.
.provider('Environment', function () {
var environments = {
dev: {
root: 'http://localhost',
port: 3000,
api: '/api',
version: 'v1'
}
};
var selectedEnv = 'dev';
var self = this;
this.setEnvironments = function (envs) {
if (!Object.keys(envs).length)
throw new Error('At least one environment is required!');
environments = envs;
};
this.setActive = function (env) {
if (!environments[env])
throw new Error('No such environment present: ' + env);
selectedEnv = env;
return self.getActive();
};
this.getEnvironment = function (env) {
if (!env)
throw new Error('No such environment present: ' + env);
return environments[env];
};
this.getActive = function () {
if (!selectedEnv)
throw new Error('You must configure at least one environment');
return environments[selectedEnv];
};
this.getApiRoute = function () {
var active = self.getActive();
return active.root + (active.port ? ':' + active.port : '') +
active.api + (active.version ? '/' + active.version : '');
};
this.$get = [function () {
return self;
}];
})
Then in the config phase:
.config(function (EnvironmentProvider) {
EnvironmentProvider.setEnvironments({
dev: {
root: 'http://10.0.0.3',
api: '/api',
version: 'v1'
},
localonly: {
root: 'http://localhost',
api: '/api',
version: 'v1'
},
prod: {
root: 'https://myapp.mybackend.com',
api: '/api',
version: 'v1'
}
});
//Set prod as the active schema
EnvironmentProvider.setActive('prod');
});
Later in some controller/service/factory:
.factory('API',function($resource, Environment){
return {
User: $resource(Environment.getApiRoute() + '/users/:id', {id: '@_id'}),
OtherResource: $resource(Environment.getApiRoute() + '/otherresource/:id', {id: '@_id'})
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With