mwaylabs / generator-m-ionic

Advanced workflows and setup for building rock-solid Ionic apps
MIT License
672 stars 134 forks source link

Multiple Proxies Support #414

Closed danielbrutti closed 8 years ago

danielbrutti commented 8 years ago

Hi,

I'm developing an app and found the need of have multiple proxy paths configured in the application. In my case I need 2 base urls /oauth and /api. And I can't just proxy to / since it will redirect to the web application running on tomcat.

I just did modifications on watching.js file in order to define multiple proxies if proxyConfig option is configured, which is a json file. With this modification you need to:

  1. Create a proxy.config.json file in root (or whatever you want) and define proxies there.
{
  "proxies": [
    {
      "proxyPath": "/oauth",
      "proxyMapTo": "http://127.0.0.1:8080/oauth"
    },
    {
      "proxyPath": "/api",
      "proxyMapTo": "http://127.0.0.1:8080/api"
    }
  ]
}
  1. Run gulp watch --no-open --proxyConfig=proxy.config.json

The console output will look like:

[proxy config] Proxy File Configuration: proxy.config.json
 ---------------------------------------
     Path: /oauth
   Map to: http://127.0.0.1:8080/oauth
 ---------------------------------------
 ---------------------------------------
     Path: /api
   Map to: http://127.0.0.1:8080/api
 ---------------------------------------

I can share the code if you think will be useful for other developers.

Best,

Daniel

gruppjo commented 8 years ago

@danielbrutti, that does look neat! Would very much like to see your implementation.

gruppjo commented 8 years ago

@danielbrutti! Still wouldn't mind implementing this if you show us your implementation here or submit a PR. Let me know what you think!

lsntomaszw commented 8 years ago

@gruppjo the easiest solution is to use http-proxy-middleware

  1. add configuration file for proxy settings; that will be list of pairs (soruce -> target)
file: /gulp/config/proxy.json

content:

[
  {
    "source": "/api",
    "target": "http://172.17.1.22:8080/space-link"
  },
  {
    "source": "/auth",
    "target": "http://172.17.1.22:8080/space-link"
  }
]

inside watching.js just add:

    if (options.useProxy) {
        var proxyMiddleware = require('http-proxy-middleware');
        var proxyConfig = require('./config/proxy.json');
        var proxy = [];

        for (var i = 0; i < proxyConfig.length; i += 1) {
            proxy.push(
                proxyMiddleware(proxyConfig[i].source, {
                    target      : proxyConfig[i].target,
                    changeOrigin: false
                }));
        }
        bsOptions.server.middleware = proxy;
    }

and then gulp watch --useProxy=true will give you:

[22:13:41] Starting 'watch'...
[HPM] Proxy created: /api  ->  http://172.17.1.22:8080/space-link
[HPM] Proxy created: /auth  ->  http://172.17.1.22:8080/space-link
...

Then, having this done - you may call any REST like:

$http.post(ApiEndpoint.url + '/auth', {
                    username: credentials.user_name,
                    password: credentials.user_password
                }

where ApiEndpoint.url should be empty for local development, and set fully (eg http://172.17.1.22:8080/space-link) for production app (as in production env, there is no CORS and no proxy transport)

gruppjo commented 8 years ago

@lsntomaszw That looks nice! I'll see if we can get it upstream soon

lsntomaszw commented 8 years ago

@gruppjo cool. I guess that the sam incjection of code shoud be made in cordova.js, cause when runing with livereload there is no proxy settings (currently) and first problem is CORS.

With the injected code you may use:

gulp --livereload "run ios" --env=dev --useProxy=true --force-build

and works like a charm

lsntomaszw commented 8 years ago

@gruppjo .. and what is more - ApiEndpoint.url should be replaced with Config.ENV.SERVER_URL

danielbrutti commented 8 years ago

Hi everyone.. want to apologize I couldn't work on this before.. were hard weeks on work. I share my code over here in case you still want to use it.. I have time to do a PR now in case you still want to use it.

JSON for proxies configuration (under root folder)

{
  "proxies": [
    {
      "proxyPath": "/oauth",
      "proxyMapTo": "http://192.168.0.10:8080/oauth"
    },
    {
      "proxyPath": "/api",
      "proxyMapTo": "http://192.168.0.10:8080/api"
    }
  ]
}

Modifications on gulp/watching.js

var fs = require('fs');
...

var bsInit = function (paths, openOverride) {
...
    if (options.proxyConfig) {
        console.log('[' + chalk.green('proxy config') + '] ' + chalk.bold('Proxy File Configuration: ' + options.proxyConfig));

        var data = fs.readFileSync('./' + options.proxyConfig, 'utf8');
        data = JSON.parse(data);

        var proxyArray = [];

        var url = require('url');
        var proxyMiddleware = require('proxy-middleware');

        for(var proxyDef of data.proxies) {  
          var proxyOptions = url.parse(proxyDef.proxyMapTo);
          proxyOptions.route = proxyDef.proxyPath;
          proxyArray.push(proxyMiddleware(proxyOptions));

          console.log(chalk.dim(' ---------------------------------------'));
          console.log('     Path: ' + chalk.green(proxyDef.proxyPath));
          console.log('   Map to: ' + chalk.green(proxyDef.proxyMapTo));
          console.log(chalk.dim(' ---------------------------------------'));
        }

        bsOptions.server.middleware = proxyArray;
    }
}
gruppjo commented 8 years ago

will be in the next release. Thanks for your input @danielbrutti, @lsntomaszw :)

siddharthshobhit commented 8 years ago

I'm adding up a simplest method for using multiple proxies. Need not to modify config.json / proxy.json or gulp/watching.js.

Just use app/main/constants/env-dev.json to define proxies i.e.

{ "API_ENDPOINT-1": "/proxy/icloud", "API_ENDPOINT-2": "/proxy/mcloud", "API_ENDPOINT-3": "/proxy/tcloud", "API_ENDPOINT-4": "/proxy/qcloud", }

if you are having multiple servers and you want to fix any of them for development mode, you can define your server type also i.e.

{ "API_ENDPOINT-1": "/proxy/icloud", "API_ENDPOINT-2": "/proxy/mcloud", "API_ENDPOINT-3": "/proxy/tcloud", "API_ENDPOINT-4": "/proxy/qcloud", "SERVER-TYPE":"dev" }

After this, define "icloud / mcloud / tcloud / qcloud" proxies in your apache server as generator-m-ionic uses apache server to serve

I'm using xampp for cross plat-form, which comes with apache. Set your proxies in apache in /opt/xampp/etc/extra/httpd-proxy.conf

Final step Use gulp defaults --set="watch --proxyPath=/proxy --proxyMapTo=http://localhost"
to set the defaults. Now, your default is localhost and local host is talking to your proxies. This method will serve your requirement.

gruppjo commented 8 years ago

Hi @siddharthshobhit, thanks for sharing your clever solution!

The current version of the generator (1.10) supports multiple proxies with a built-in feature. You can see how it works, here: https://github.com/mwaylabs/generator-m-ionic/blob/master/docs/guides/cors_proxy.md#built-in-multiple-proxies