Manage versioned API in Azure API Manager

时光毁灭记忆、已成空白 提交于 2019-12-22 12:18:13

问题


I´m looking into host our web API in Azure using an API app. I am using the Azure API Manager in front of the API App to expose the developer portal to some of our consumers. The web API is built in .NET core and it has version support using the URL (https://example.com/api/v2/controller...). I have given it swagger support and one swagger.json is created for each version. These swagger files I use in my ARM templates to set up API Manager and expose this versioned API. When adding a version to API Manager I have to give a path which must be unique for the API Im adding. So for version v1 I give "api/v1" and for v2 I give "api/v2". So far so good. The problem is when trying to call the API using API Manager the URL ends up to be: https://foo-api-manager-dev.azure-api.net/api/v2/api/v2/tests So the "api/v2"-part i duplicated. I guess it has something to do with how API Manager works and how my versioning is set up in my web API. When calling the controllers directly to the API App then the URL is correct.

I have searched around a lot and tried different approaches to this but could really need some input here. All suggestions are appreciated!

My routing is managed in a base controller and looks like this

[Produces("application/json")]
[Route("api/v{version:apiVersion}/[controller]")]
public abstract class VersionBaseController : ApiController
{
    protected VersionBaseController()
       : base()
    {
    }
}

Controllers like this:

[ApiVersion("2.0")]
public class TestsController : VersionBaseController
{
    [HttpGet]
    public string Get()
    {
        return "Get works V2";
    }

The entire template to create the api manager:

//Create API Manager
{
  "apiVersion": "2018-06-01-preview",
  "name": "[parameters('apim_name')]",
  "location": "[parameters('location')]",
  "type": "Microsoft.ApiManagement/service",
  "sku": {
    "name": "[parameters('apim_tier')]",
    "capacity": 1
  },
  "properties": {
    "publisherEmail": "[parameters('apim_adminEmail')]",
    "publisherName": "[parameters('apim_orgName')]"
  },
  "resources": [
    //Create version set
    {
      "apiVersion": "2017-03-01",
      "type": "Microsoft.ApiManagement/service/api-version-sets",
      "name": "[concat(parameters('apim_name'), '/', parameters('VersionSetName'))]",
      "dependsOn": [
        "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'))]"
      ],
      "properties": {
        "description": "Version configuration",
        "displayName": "Api set 1",
        "versioningScheme": "Segment"
      }
    },
    //Link version 1
    {
      "apiVersion": "2017-03-01",
      "type": "apis",
      "name": "AvidaAPIV1",
      "dependsOn": [
        "[resourceId('Microsoft.ApiManagement/service/api-version-sets', parameters('apim_name'), parameters('VersionSetName'))]",
        "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'))]"
      ],
      "properties": {
        "contentFormat": "swagger-link-json",
        "contentValue": "[concat(parameters('ExternalApiBaseUrl'),'/swagger/v1/swagger.json')]",
        "path": "/api/v1",
        "isCurrent": true,
        "apiVersion": "v1",
        "apiVersionName": "v1",
        "apiVersionDescription": "string",
        "apiVersionSetId": "[concat('Microsoft.ApiManagement/service/api-version-sets', parameters('VersionSetName'))]"
      }
    },
    //Link version 2
    {
      "apiVersion": "2017-03-01",
      "type": "apis",
      "name": "AvidaAPIV2",
      "dependsOn": [
        "[resourceId('Microsoft.ApiManagement/service/api-version-sets', parameters('apim_name'), parameters('VersionSetName'))]",
        "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'))]"
      ],
      "properties": {
        "contentFormat": "swagger-link-json",
        "contentValue": "[concat(parameters('ExternalApiBaseUrl'),'/swagger/v2/swagger.json')]",
        "path": "/api/v2",
        "isCurrent": false,
        "apiVersion": "v2",
        "apiVersionName": "v2",
        "apiVersionDescription": "string",
        "apiVersionSetId": "[concat('Microsoft.ApiManagement/service/api-version-sets', parameters('VersionSetName'))]"
      }
    },
    //Create unlimited product
    {
      "apiVersion": "2017-03-01",
      "type": "products",
      "name": "[concat('UnlimitedProduct', parameters('ProductNameSuffix'))]",
      "dependsOn": [
        "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'))]"
      ],
      "properties": {
        "displayName": "[concat('UnlimitedProduct', parameters('ProductNameSuffix'))]",
        "description": "Unlimited external access",
        "terms": "",
        "subscriptionRequired": false,
        "state": "published"
      },
      "resources": [
        {
          "apiVersion": "2017-03-01",
          "type": "apis",
          "name": "AvidaAPIV1",
          "dependsOn": [
            "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'))]",
            "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'), '/apis/AvidaAPIV1')]",
            //"[concat('Microsoft.ApiManagement/service/', parameters('apim_name'), '/apis/AvidaAPIV2')]",
            "[concat('Microsoft.ApiManagement/service/', parameters('apim_name'), '/products/UnlimitedProduct', parameters('ProductNameSuffix'))]"
          ]
        }
      ]
    }

回答1:


It depends on how you configure your version set. Initially each API in Azure APIM has only URI suffix - i.e. part of the path coming right after host to identify API called. When you add API to a version set and set this version set's scheme to "path" you additionally specify version string for each API. look into your API's settings, there should be a field called "Version identified". This identifier is appended to API URL suffix automatically.

So imagine you have an API with suffix of "httpbin" and you add it to a version set and set it's version identified to "v0" that means that this API will be reachable by calling https://xxx.xxx/httpbin/v0/...

Looking at your configuration. I have a feeling that you've put "api/v1" as both API suffix and version identifier. Try splitting it into "api" as API suffix, and "v1" as version identifier.




回答2:


To be able to identify the issue, it would be helpful to have the api-part of the automation script. In that way we can see what APIM actually uses as ARM template regarding the linked version 1 and 2 of the APIs.




回答3:


So I realized in APIM there is no version set created at all: The resulting APIs from my above template scripts

I then created version set manually and linked to my 2 swaggers in the Azure portal and then it looks correct: Manually created in portal

But even when creating the version manually I have the same problem with the URL. I need to duplicate "api/v2/api/v2/[controller]"

The settings for version2 now looks like this which seems correct to me: enter image description here



来源:https://stackoverflow.com/questions/51244756/manage-versioned-api-in-azure-api-manager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!