gravitee-io / issues

Gravitee.io - API Platform - Issues
65 stars 26 forks source link

apim-portal-ui docker image ignores PORTAL_API_URL for links, pages and apis resource #5152

Closed dschulten closed 3 years ago

dschulten commented 3 years ago

Expected Behavior

When I define PORTAL_API_URL for the apim-portal-ui docker image, it should use that URL in the browser for all calls to the apim_management_api.

Current Behavior

If I redefine PORTAL_API_URL from localhost:8083 to a reverse proxy host name such as kmcapi-dev.example.net, the setting will affect the following resources:

http://kmcapi-dev.example.net/portal/environments/DEFAULT/theme http://kmcapi-dev.example.net/portal/environments/DEFAULT/configuration

But it does not affect subsequent API resources. The following requests are still being sent to localhost:8083, causing the portal ui to fail when delivered through the reverse proxy.

http://localhost:8083/portal/environments/DEFAULT/configuration/links http://localhost:8083/portal/environments/DEFAULT/pages?homepage=true http://localhost:8083/portal/environments/DEFAULT/apis?size=-1&filter=FEATURED

The screenshot below shows the portal running through a reverse proxy with a host name of kmcapi-dev.example.net.

grafik

The theme and configuration resources have been retrieved successfully. But the failure to retrieve /links caused the portal to show the message that the server is unavailable.

Also note that the docker-compose templating for config.json works just fine, as proven by the screenshot above.

Possible Solution

I have debugged and found that the incoming Configuration is always null when the ApiService ctor gets called:

export class ApiService {

    protected basePath = 'http://localhost:8083/portal/environments/DEFAULT';
    public defaultHeaders = new HttpHeaders();
    public configuration = new Configuration();
    public encoder: HttpParameterCodec;

    constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, // <--  url with localhost:8083
            @Optional() configuration: Configuration) {
        if (configuration) {                                    // <-- always null
            this.configuration = configuration;
        }
        if (typeof this.configuration.basePath !== 'string') {
            if (typeof basePath !== 'string') {
                basePath = this.basePath;
            }
            this.configuration.basePath = basePath;   //   <-- this seems to win
        }
        this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
    }

I think that explains the current behaviour. I was unable to find out why the config.json is not used for the Configuration passed into the ApiService ctor.

Steps to Reproduce (for bugs)

  1. Run gravitee with the docker-compose below
  2. Open localhost:8085
  3. Hit F12 and switch to network analysis
  4. Observe the requested URLs. You will see the reverse effect from the screenshot above: When running locally, the calls to /links etc on localhost:8083 will succeed, but /theme and /configuration fail because they have been successfully overridden to point to PORTAL_API_URL.
click to expand docker-compose.yml ``` version: '3.5' services: elasticsearch: container_name: gio_apim_elasticsearch environment: ES_JAVA_OPTS: -Xms512m -Xmx512m bootstrap.memory_lock: "true" discovery.type: single-node http.host: 0.0.0.0 transport.host: 0.0.0.0 xpack.monitoring.enabled: "false" xpack.security.enabled: "false" healthcheck: interval: 5m retries: 3 test: - CMD - /bin/sh - -c - nc -vz localhost 9200 timeout: 20s image: elasticsearch:7.7.0 ports: - published: 9200 target: 9200 ulimits: memlock: hard: -1 soft: -1 nofile: 65536 volumes: - data-elasticsearch:/usr/share/elasticsearch/data:rw gateway: container_name: gio_apim_gateway environment: gravitee_management_mongodb_uri: mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 gravitee_ratelimit_mongodb_uri: mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 gravitee_reporters_elasticsearch_endpoints_0: http://elasticsearch:9200 healthcheck: interval: 5m retries: 3 test: - CMD - /bin/sh - -c - nc -vz localhost 8082 timeout: 30s image: graviteeio/apim-gateway:3.6.0 ports: - published: 8082 target: 8082 restart: always volumes: - /etc/localtime:/etc/localtime:ro management_api: container_name: gio_apim_management_api environment: gravitee_analytics_elasticsearch_endpoints_0: http://elasticsearch:9200 gravitee_management_mongodb_uri: mongodb://mongodb:27017/gravitee?serverSelectionTimeoutMS=5000&connectTimeoutMS=5000&socketTimeoutMS=5000 hostname: management image: graviteeio/apim-management-api:3.6.0 ports: - published: 8083 target: 8083 restart: always volumes: - /etc/localtime:/etc/localtime:ro management_ui: container_name: gio_apim_management_ui depends_on: - management_api environment: MGMT_API_URL: https://kmcmanagement-dev.example.net/management/organizations/DEFAULT/environments/DEFAULT/ healthcheck: interval: 5m retries: 3 test: - CMD - /bin/sh - -c - nc -vz localhost 8080 timeout: 30s image: graviteeio/apim-management-ui:3.6.0 ports: - published: 8084 target: 8080 restart: always volumes: - /etc/localtime:/etc/localtime:ro mongodb: container_name: gio_apim_mongodb image: mongo:3.6 ports: - published: 27017 target: 27017 restart: always volumes: - data-mongo:/data/db:rw portal_ui: container_name: gio_apim_portal_ui depends_on: - management_api environment: PORTAL_API_URL: https://kmcapi-dev.example.net:443/portal/environments/DEFAULT healthcheck: interval: 5m retries: 3 test: - CMD - /bin/sh - -c - nc -vz localhost 8080 timeout: 30s image: graviteeio/apim-portal-ui:3.6.0 ports: - published: 8085 target: 8080 restart: always volumes: - /etc/localtime:/etc/localtime:ro volumes: data-elasticsearch: {} data-mongo: {} ```

Context

We want to use the portal ui to allow api subscribers to browse and subscribe apis.

Your Environment

dschulten commented 3 years ago

The root cause was a tricky misconfiguration in our reverse proxy in front of gravitee. The /configuration and /theme paths pointed to the Portal UI which served a generic HTML response page with a 200 OK. In that case configuration is null and the ApiService falls back to localhost:8083. Solution: we created a separate routing on the reverse proxy which points both /portal and /management to the management API and enter that URL in PORTAL_API_URL

aelamrani commented 3 years ago

Hi @dschulten

Thanks for sharing these details with the community.