api-keyexpress-gateway

Express-Gateway, serve same API path/route, but under different ServiceEndpoints


I have a server in Node.js + Express, that exposes some APIs both to public and admins. Actually I have 2 cloned instances running, one for Test, one for Production. They are twins, exposing same routes (/admin, /public), but are connected to two different DataBases, and are deployed on two different addresses.

I want to use Express-Gateway to provide APIs to 3d parties, so I'll give them firstly access to the Test Server. Once it's all done, I'll give them also the Production access.

To do this, my Idea is to create just 1 eg user, with multiple eg application. Each eg application will have eg credentials to access to Server or Production.

                                             http://server_test.com
            |-------------|                    |-------------|
            |   App Prod  |                    | Server Test |
    +----►  |    scopes:  |------+     +-----► |    /public  |
    |       | [api_prod]  |      |     |       |    /admin   |
    |       |-------------|      ▼     |       |-------------|
    |                       http://gateway.com
|------|                     |------------|         
| User |                     |   Express  |  
|------|                     |   Gateway  |    
    |       |-------------|  |------------|                     
    |       |   App Test  |      ▲     |    http://server_prod.com
    +----►  |    scopes:  |      |     |       |-------------|             
            | [api_test]  |------+     +-----► | Server Prod |     
            |-------------|                    |    /public  |                 
                                               |    /admin   |                   
                                               |-------------|

According to the credentials provided, the Gateway should redirect requests to server_test.com or server_prod.com. My idea was to use eg scopes to address requests to the right endpoint. So Server Test policy, will require the scope api_test, while Server Prod will require api_prod scope.

Anyway this solution doesn't work, because if the first match in apiEndpoints fails, it just results in "Not Found".

Example: I make a request to http://gateway.com/public using App Prod credentials, with api_prod scope. It should be passed to http://server_prod.com/public, but instead It matches first paths: '/*' of testEndpoint, and fails the scopes condition. So it just fails, while the correct apiEndpoint should be prodEndpoint.

How can I solve this problem?

This is my gateway.config.yml

apiEndpoints:
   testEndpoint
      host:*
      paths: '/*'            # <--- match this
      scopes: ["api_test"]   # <--- but fails this
   prodEndpoint
      host:*
      paths: '/*'
      scopes: ["api_prod"]   # <---- this is right
serviceEndpoints
    testService      
      url: "http://server_test.com"
    prodService      
      url: "http://server_prod.com"
policies
    - proxy
pipelines
    testEndpoint:              # Test
       apiEndpoints:
         - testEndpoint
       policies:
         - proxy
           - action
             serviceEndpoint: testService
    prodEndpoint:              # Prod
       apiEndpoints:
         - prodEndpoint
       policies:
         - proxy
           - action
             serviceEndpoint: prodService

Solution

  • I solved in this way: using -rewrite policy.

                                            http://server_test.com
    |-------------|                              |-------------|
    |   App Prod  | /prod/admin          /admin  | Server Test |
    |    scopes:  |-------------+     +--------► |    /public  |
    | [api_prod]  |             |     |          |    /admin   |
    |-------------|             ▼     |          |-------------|
                            http://gateway.com
                             |------------|         
                             |   Express  |  
                             |   Gateway  |    
    |-------------|          |------------|                     
    |   App Test  |             ▲     |        http://server_prod.com
    |    scopes:  |             |     |           |-------------|             
    | [api_test]  |-------------+     +---------► | Server Prod |     
    |-------------| /test/admin          /admin   |    /public  |                 
                                                  |    /admin   |                   
                                                  |-------------|
    
    

    This is my config file:

    apiEndpoints:
       testEndpoint
          host:*
          paths: '/test/*'        
          scopes: ["api_test"]   
       prodEndpoint
          host:*
          paths: '/prod/*'
          scopes: ["api_prod"]  
    serviceEndpoints
        testService      
          url: "http://server_test.com"
        prodService      
          url: "http://server_prod.com"
    policies
        - proxy
    pipelines
        testEndpoint:              # Test
           apiEndpoints:
             - testEndpoint
           policies:
             - rewrite:            # rewrite - delete '/test'
               -
                 condition:
                    name: regexpmatch
                    match: ^/test/?(.*)$
                 action:
                   rewrite: /$1   
             - proxy
               - action
                 serviceEndpoint: testService
        prodEndpoint:              # Prod
           apiEndpoints:
             - prodEndpoint
           policies:
             - rewrite:           # rewrite - delete '/prod'
               -
                 condition:
                    name: regexpmatch
                    match: ^/prod/?(.*)$
                 action:
                   rewrite: /$1  
             - proxy
               - action
                 serviceEndpoint: prodService