Duplicated path names

Hi team,

It looks like I can create multiple APIs under the same account with the same path name. Is this intentional? If so, why? which api will get hit if I try to access the duplicated path?

Thanks

Could you share the API definition of the duplicates for review? Also, when you say the same account, do you mean the same org_id or something else?

You can specify the same listen path name for two different APIs, however, there would be an internal change to make sure that the listen path is unique. The way this is done is by appending the api_id of the API definition to the listen path. You would then make a request to that unique listen path to distinguish between the 2. FYI, the append only occurs on the duplicate and not the original listen path.

I encourage you to use query the Gateway APIs to confirm this behavior if you are using the Open Source Gateway / Community Edition.

@Olu
Here is what I have:



API definitions:

{
  "created_at": "2022-04-07T12:15:13Z",
  "api_model": {},
  "api_definition": {
    "api_id": "7d92ff7dae834dc676032d6fdfa5e122",
    "jwt_issued_at_validation_skew": 0,
    "upstream_certificates": {},
    "use_keyless": false,
    "enable_coprocess_auth": false,
    "base_identity_provided_by": "",
    "custom_middleware": {
      "pre": [],
      "post": [],
      "post_key_auth": [],
      "auth_check": {
        "name": "",
        "path": "",
        "require_session": false,
        "raw_body_only": false
      },
      "response": [],
      "driver": "",
      "id_extractor": {
        "extract_from": "",
        "extract_with": "",
        "extractor_config": {}
      }
    },
    "disable_quota": false,
    "custom_middleware_bundle": "",
    "cache_options": {
      "cache_timeout": 60,
      "enable_cache": true,
      "cache_all_safe_requests": false,
      "cache_response_codes": [],
      "enable_upstream_cache_control": false,
      "cache_control_ttl_header": "",
      "cache_by_headers": []
    },
    "enable_ip_blacklisting": false,
    "tag_headers": [],
    "jwt_scope_to_policy_mapping": {},
    "pinned_public_keys": {},
    "expire_analytics_after": 0,
    "domain": "",
    "openid_options": {
      "providers": [],
      "segregate_by_client": false
    },
    "jwt_policy_field_name": "",
    "enable_proxy_protocol": false,
    "jwt_default_policies": [],
    "active": true,
    "jwt_expires_at_validation_skew": 0,
    "config_data": {},
    "notifications": {
      "shared_secret": "",
      "oauth_on_keychange_url": ""
    },
    "jwt_client_base_field": "",
    "auth": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "check_host_against_uptime_tests": false,
    "auth_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "blacklisted_ips": [],
    "graphql": {
      "schema": "",
      "enabled": false,
      "engine": {
        "field_configs": [],
        "data_sources": []
      },
      "type_field_configurations": [],
      "execution_mode": "proxyOnly",
      "proxy": {
        "auth_headers": {}
      },
      "subgraph": {
        "sdl": ""
      },
      "supergraph": {
        "subgraphs": [],
        "merged_sdl": "",
        "global_headers": {}
      },
      "version": "2",
      "playground": {
        "enabled": false,
        "path": ""
      }
    },
    "hmac_allowed_clock_skew": -1,
    "dont_set_quota_on_create": false,
    "uptime_tests": {
      "check_list": [],
      "config": {
        "expire_utime_after": 0,
        "service_discovery": {
          "use_discovery_service": false,
          "query_endpoint": "",
          "use_nested_query": false,
          "parent_data_path": "",
          "data_path": "",
          "cache_timeout": 60
        },
        "recheck_wait": 0
      }
    },
    "enable_jwt": false,
    "do_not_track": false,
    "name": "testDuplicate",
    "slug": "testduplicate",
    "oauth_meta": {
      "allowed_access_types": [],
      "allowed_authorize_types": [],
      "auth_login_redirect": ""
    },
    "CORS": {
      "enable": false,
      "max_age": 24,
      "allow_credentials": false,
      "exposed_headers": [],
      "allowed_headers": [
        "Origin",
        "Accept",
        "Content-Type",
        "X-Requested-With",
        "Authorization"
      ],
      "options_passthrough": false,
      "debug": false,
      "allowed_origins": [
        "*"
      ],
      "allowed_methods": [
        "GET",
        "POST",
        "HEAD"
      ]
    },
    "event_handlers": {
      "events": {}
    },
    "proxy": {
      "target_url": "http://httpbin.org/",
      "service_discovery": {
        "endpoint_returns_list": false,
        "cache_timeout": 0,
        "parent_data_path": "",
        "query_endpoint": "",
        "use_discovery_service": false,
        "_sd_show_port_path": false,
        "target_path": "",
        "use_target_list": false,
        "use_nested_query": false,
        "data_path": "",
        "port_data_path": ""
      },
      "check_host_against_uptime_tests": false,
      "transport": {
        "ssl_insecure_skip_verify": false,
        "ssl_min_version": 0,
        "proxy_url": "",
        "ssl_ciphers": []
      },
      "target_list": [],
      "preserve_host_header": false,
      "strip_listen_path": true,
      "enable_load_balancing": false,
      "listen_path": "/testduplicate/",
      "disable_strip_slash": true
    },
    "client_certificates": [],
    "use_basic_auth": false,
    "version_data": {
      "not_versioned": true,
      "default_version": "",
      "versions": {
        "Default": {
          "name": "Default",
          "expires": "",
          "paths": {
            "ignored": [],
            "white_list": [],
            "black_list": []
          },
          "use_extended_paths": true,
          "extended_paths": {
            "ignored": [],
            "white_list": [],
            "black_list": [],
            "transform": [],
            "transform_response": [],
            "transform_jq": [],
            "transform_jq_response": [],
            "transform_headers": [],
            "transform_response_headers": [],
            "hard_timeouts": [],
            "circuit_breakers": [],
            "url_rewrites": [],
            "virtual": [],
            "size_limits": [],
            "method_transforms": [],
            "track_endpoints": [],
            "do_not_track_endpoints": [],
            "validate_json": [],
            "internal": []
          },
          "global_headers": {},
          "global_headers_remove": [],
          "global_response_headers": {},
          "global_response_headers_remove": [],
          "ignore_endpoint_case": false,
          "global_size_limit": 0,
          "override_target": ""
        }
      }
    },
    "jwt_scope_claim_name": "",
    "use_standard_auth": true,
    "session_lifetime": 0,
    "hmac_allowed_algorithms": [],
    "disable_rate_limit": false,
    "definition": {
      "location": "header",
      "key": "x-api-version",
      "strip_path": false
    },
    "use_oauth2": false,
    "jwt_source": "",
    "jwt_signing_method": "",
    "jwt_not_before_validation_skew": 0,
    "use_go_plugin_auth": false,
    "jwt_identity_base_field": "",
    "allowed_ips": [],
    "request_signing": {
      "is_enabled": false,
      "secret": "",
      "key_id": "",
      "algorithm": "",
      "header_list": [],
      "certificate_id": "",
      "signature_header": ""
    },
    "org_id": "6238e0730544b90001387454",
    "enable_ip_whitelisting": false,
    "global_rate_limit": {
      "rate": 0,
      "per": 0
    },
    "protocol": "",
    "enable_context_vars": false,
    "tags": [],
    "basic_auth": {
      "disable_caching": false,
      "cache_ttl": 0,
      "extract_from_body": false,
      "body_user_regexp": "",
      "body_password_regexp": ""
    },
    "listen_port": 0,
    "session_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "auth_configs": {
      "authToken": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "basic": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "coprocess": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "hmac": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "jwt": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oauth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oidc": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      }
    },
    "strip_auth_data": false,
    "id": "624ed5d17baa83000112e5dc",
    "certificates": [],
    "enable_signature_checking": false,
    "use_openid": false,
    "internal": false,
    "jwt_skip_kid": false,
    "enable_batch_request_support": false,
    "enable_detailed_recording": false,
    "response_processors": [
      {
        "name": "response_body_transform",
        "options": {}
      }
    ],
    "use_mutual_tls_auth": false
  },
  "hook_references": [],
  "is_site": false,
  "sort_by": 0,
  "user_group_owners": [],
  "user_owners": []
}
{
  "created_at": "2022-04-07T12:15:03Z",
  "api_model": {},
  "api_definition": {
    "api_id": "07f0ec1c911e401e6cb76ddace04c0e0",
    "jwt_issued_at_validation_skew": 0,
    "upstream_certificates": {},
    "use_keyless": false,
    "enable_coprocess_auth": false,
    "base_identity_provided_by": "",
    "custom_middleware": {
      "pre": [],
      "post": [],
      "post_key_auth": [],
      "auth_check": {
        "name": "",
        "path": "",
        "require_session": false,
        "raw_body_only": false
      },
      "response": [],
      "driver": "",
      "id_extractor": {
        "extract_from": "",
        "extract_with": "",
        "extractor_config": {}
      }
    },
    "disable_quota": false,
    "custom_middleware_bundle": "",
    "cache_options": {
      "cache_timeout": 60,
      "enable_cache": true,
      "cache_all_safe_requests": false,
      "cache_response_codes": [],
      "enable_upstream_cache_control": false,
      "cache_control_ttl_header": "",
      "cache_by_headers": []
    },
    "enable_ip_blacklisting": false,
    "tag_headers": [],
    "jwt_scope_to_policy_mapping": {},
    "pinned_public_keys": {},
    "expire_analytics_after": 0,
    "domain": "",
    "openid_options": {
      "providers": [],
      "segregate_by_client": false
    },
    "jwt_policy_field_name": "",
    "enable_proxy_protocol": false,
    "jwt_default_policies": [],
    "active": true,
    "jwt_expires_at_validation_skew": 0,
    "config_data": {},
    "notifications": {
      "shared_secret": "",
      "oauth_on_keychange_url": ""
    },
    "jwt_client_base_field": "",
    "auth": {
      "use_param": false,
      "param_name": "",
      "use_cookie": false,
      "cookie_name": "",
      "auth_header_name": "Authorization",
      "use_certificate": false,
      "validate_signature": false,
      "signature": {
        "algorithm": "",
        "header": "",
        "secret": "",
        "allowed_clock_skew": 0,
        "error_code": 0,
        "error_message": ""
      }
    },
    "check_host_against_uptime_tests": false,
    "auth_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "blacklisted_ips": [],
    "graphql": {
      "schema": "",
      "enabled": false,
      "engine": {
        "field_configs": [],
        "data_sources": []
      },
      "type_field_configurations": [],
      "execution_mode": "proxyOnly",
      "proxy": {
        "auth_headers": {}
      },
      "subgraph": {
        "sdl": ""
      },
      "supergraph": {
        "subgraphs": [],
        "merged_sdl": "",
        "global_headers": {}
      },
      "version": "2",
      "playground": {
        "enabled": false,
        "path": ""
      }
    },
    "hmac_allowed_clock_skew": -1,
    "dont_set_quota_on_create": false,
    "uptime_tests": {
      "check_list": [],
      "config": {
        "expire_utime_after": 0,
        "service_discovery": {
          "use_discovery_service": false,
          "query_endpoint": "",
          "use_nested_query": false,
          "parent_data_path": "",
          "data_path": "",
          "cache_timeout": 60
        },
        "recheck_wait": 0
      }
    },
    "enable_jwt": false,
    "do_not_track": false,
    "name": "testDuplicate",
    "slug": "testduplicate",
    "oauth_meta": {
      "allowed_access_types": [],
      "allowed_authorize_types": [],
      "auth_login_redirect": ""
    },
    "CORS": {
      "enable": false,
      "max_age": 24,
      "allow_credentials": false,
      "exposed_headers": [],
      "allowed_headers": [
        "Origin",
        "Accept",
        "Content-Type",
        "X-Requested-With",
        "Authorization"
      ],
      "options_passthrough": false,
      "debug": false,
      "allowed_origins": [
        "*"
      ],
      "allowed_methods": [
        "GET",
        "POST",
        "HEAD"
      ]
    },
    "event_handlers": {
      "events": {}
    },
    "proxy": {
      "target_url": "http://httpbin.org/",
      "service_discovery": {
        "endpoint_returns_list": false,
        "cache_timeout": 0,
        "parent_data_path": "",
        "query_endpoint": "",
        "use_discovery_service": false,
        "_sd_show_port_path": false,
        "target_path": "",
        "use_target_list": false,
        "use_nested_query": false,
        "data_path": "",
        "port_data_path": ""
      },
      "check_host_against_uptime_tests": false,
      "transport": {
        "ssl_insecure_skip_verify": false,
        "ssl_min_version": 0,
        "proxy_url": "",
        "ssl_ciphers": []
      },
      "target_list": [],
      "preserve_host_header": false,
      "strip_listen_path": true,
      "enable_load_balancing": false,
      "listen_path": "/testduplicate/",
      "disable_strip_slash": true
    },
    "client_certificates": [],
    "use_basic_auth": false,
    "version_data": {
      "not_versioned": true,
      "default_version": "",
      "versions": {
        "Default": {
          "name": "Default",
          "expires": "",
          "paths": {
            "ignored": [],
            "white_list": [],
            "black_list": []
          },
          "use_extended_paths": true,
          "extended_paths": {
            "ignored": [],
            "white_list": [],
            "black_list": [],
            "transform": [],
            "transform_response": [],
            "transform_jq": [],
            "transform_jq_response": [],
            "transform_headers": [],
            "transform_response_headers": [],
            "hard_timeouts": [],
            "circuit_breakers": [],
            "url_rewrites": [],
            "virtual": [],
            "size_limits": [],
            "method_transforms": [],
            "track_endpoints": [],
            "do_not_track_endpoints": [],
            "validate_json": [],
            "internal": []
          },
          "global_headers": {},
          "global_headers_remove": [],
          "global_response_headers": {},
          "global_response_headers_remove": [],
          "ignore_endpoint_case": false,
          "global_size_limit": 0,
          "override_target": ""
        }
      }
    },
    "jwt_scope_claim_name": "",
    "use_standard_auth": true,
    "session_lifetime": 0,
    "hmac_allowed_algorithms": [],
    "disable_rate_limit": false,
    "definition": {
      "location": "header",
      "key": "x-api-version",
      "strip_path": false
    },
    "use_oauth2": false,
    "jwt_source": "",
    "jwt_signing_method": "",
    "jwt_not_before_validation_skew": 0,
    "use_go_plugin_auth": false,
    "jwt_identity_base_field": "",
    "allowed_ips": [],
    "request_signing": {
      "is_enabled": false,
      "secret": "",
      "key_id": "",
      "algorithm": "",
      "header_list": [],
      "certificate_id": "",
      "signature_header": ""
    },
    "org_id": "6238e0730544b90001387454",
    "enable_ip_whitelisting": false,
    "global_rate_limit": {
      "rate": 0,
      "per": 0
    },
    "protocol": "",
    "enable_context_vars": false,
    "tags": [],
    "basic_auth": {
      "disable_caching": false,
      "cache_ttl": 0,
      "extract_from_body": false,
      "body_user_regexp": "",
      "body_password_regexp": ""
    },
    "listen_port": 0,
    "session_provider": {
      "name": "",
      "storage_engine": "",
      "meta": {}
    },
    "auth_configs": {
      "authToken": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "basic": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "coprocess": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "hmac": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "jwt": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oauth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      },
      "oidc": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
          "algorithm": "",
          "header": "",
          "secret": "",
          "allowed_clock_skew": 0,
          "error_code": 0,
          "error_message": ""
        }
      }
    },
    "strip_auth_data": false,
    "id": "624ed5c77baa83000112e5db",
    "certificates": [],
    "enable_signature_checking": false,
    "use_openid": false,
    "internal": false,
    "jwt_skip_kid": false,
    "enable_batch_request_support": false,
    "enable_detailed_recording": false,
    "response_processors": [
      {
        "name": "response_body_transform",
        "options": {}
      }
    ],
    "use_mutual_tls_auth": false
  },
  "hook_references": [],
  "is_site": false,
  "sort_by": 0,
  "user_group_owners": [],
  "user_owners": []
}

which api will get hit if I send request to “https://polite-employ-mgw.aws-usw2.cloud-ara.tyk.io/testduplicate/

which api will get hit if I send request to “https://polite-employ-mgw.aws-usw2.cloud-ara.tyk.io/testduplicate/”

This I don’t know and cannot answer why at this time. What I know and can assume is correct is the use of the ingress / gateway / proxy endpoint to make calls. If you use the dashboard endpoint, then analytics won’t be tracked.

Regarding your initial questions

It looks like I can create multiple APIs under the same account with the same path name. Is this intentional?

Yes, it is intentional and only available via the dashboard. It can be disabled via the dashboard config file. For Tyk Cloud, you would need to open a support ticket.

If so, why?

This is needed because it is possible to have one dashboard keeping track of the same API with the same listen path in different environments (multi-cloud) or regions (multi-region). For example, there could be two gateways deployed in two different regions (one in EU and one in US). Both can have the same APIs listen on the same path and be segmented with [gateway shading] or (Gateway Sharding). Having a central layer or place to manage APIs across regions/environments would be extremely helpful.

which api will get hit if I try to access the duplicated path?

For the open source gateway I am sure the api_id is appended to listen_path with a hyphen - as the separator. However, with the dashboard, I will have to ask internally and would get back to you.

For the dashboard, the decision is made based on the first one that is loaded. The order of the load could be random because of unordered JSON loads. A load or refresh happens when an API is created or updated.

It’s not best practice to have duplicate listen_paths on a single node, so it’s best to avoid the scenario unless the use case is needed. Hopes this clears this up.

I see, thanks…in this case, how would below work? I believe different paths will share the same endpoint if they use the same dashboard

This is needed because it is possible to have one dashboard keeping track of the same API with the same listen path in different environments (multi-cloud) or regions (multi-region).

You would need to either implement Hybrid Gateways or setup a MDCB environment

I see, thanks! Feel free to close this ticket