简体   繁体   中英

How dynamically change API endpoint on Angularjs services based on the domain or host application

I have MVC web application that use Angularjs and a Web API, both application are published in different domains. Everytime thet I commit code changes TFS publish both the MVC app and the Web API and using web.config transformation it change the web config connection and app keys to point to developer, production or testing.

Now that I am using angular I have a service that point to the API endpoint to do something for instance the login.

...

function loginService($http, $q) {

        var baseUri = "http://localhost/"

        var service = {
            login: login,
           ...
        };

        return service;


        function login(user, password) {
            var deferred = $q.defer();
            $http({ method: 'POST', url: baseUri + '/api/tokens',
...

As you can see the baseUri is set to localhost but I would like it have for the production environment something like var baseUri = "http://production/" and for testing baseUri = "http://testing/" . SO the baseUri changes depend of what is being publish by TFS.

Remember the the domain where the MVC application is hosted is different of the WebAPI so I cannot check the domain of the angular scope and build the base URI.

Thank you

Can you do a switch on the domain of the MVC app and based on whichever it is build the URI for the API?

So something like:

switch (MVCdomain) {
    case "http://production/": baseUri = "http://APIproduction/"; break;
    case "http://testing/": baseUri = "http://APItesting/"; break;
}

Could probably encapsulate that in its own endpointService that you can inject into your loginService or any other service that needs it, something like this:

(function () {
    angular.module('app').factory('endpointService', function ($location) {
        return {
            getAPIEndpoint: function () {
                var endpoint = '';
                switch ($location.host()) {
                    // test if MVC app is in prod/test/local and determine what API endpoint should be called
                    case 'ProdDomainP.com': endpoint = 'ProdDomainAPIP.com'; break;
                    case 'TestDomainP.com': endpoint = 'TestDomainAPIP.com'; break;
                }
                return endpoint;
            }
        }
    });
})();

This would be a service you inject into other services to determine what API endpoint you call, like so:

function loginService($http, $q, endpointService) {

    var baseUri = endpointService.getAPIEndoint();

    var service = {
        login: login,
       ...
    };

    return service;


    function login(user, password) {
        var deferred = $q.defer();
        $http({ method: 'POST', url: baseUri + '/api/tokens',
    ...

I am trying to do this as well. So I don't have to hard code api endpoints in my angular app, before I bootstrap angular, I make a service call in JavaScript to get endpoints. On the server side (web api) the controller reads from the web.config to get the end points that the angular app will use and returns them as JSON. Then , still before I bootstrap angular and after the endpoints are returned to JavaScript (via a native js promise or angular promise) , I set a global object var that holds all end points. In angular there is an endpoint service that exposes this global end points object. Finally when that endpoint object is set, I bootstrap angular app. This ensures the endpoints are set before angular runs and tries tobuse the endpoints.

It sucks there needs to be this global endpoint object that exists outside of angular but it's the only way I can think of allows usage of web.config for transforms and not have to hardcode URL endpoint in js

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM