question

GrahamAllwood-4295 avatar image
0 Votes"
GrahamAllwood-4295 asked MayankBargali-MSFT commented

Mapping Resources to Azure Functions

Hi,

What is the best way to achieve the following using APIM and a function app?:

I want the api to contain two resources:

GET /resource1
GET /resource2

The data is coming from a Azure Function app with two functions called GetResource1 and GetResource2

Do I import the API from the Azure Function, or an OpenAPI spec and do the mapping myself? How do I do this mapping?

Can I auto generate an OpenAPI spec in my Function App project somehow? Should I do it by hand?

Ultimately looking at doing this from an ARM template - but not got to that bit yet!!

Any help or links would be welcome.

Thanks

Graham

azure-functionsazure-api-management
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

MayankBargali-MSFT avatar image
0 Votes"
MayankBargali-MSFT answered MayankBargali-MSFT commented

Hi @GrahamAllwood-4295

You can Import an Azure Function App as an API in Azure API Management using azure portal. Everything will be taken for you when you are doing it from azure portal.

If you want to automate it using ARM template then you can refer to the below document:
https://docs.microsoft.com/en-us/azure/templates/microsoft.apimanagement/2019-01-01/service/backends?tabs=json
https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/template-functions-resource?tabs=json#return-value

For your reference, you can refer to the below ARM template

  {
             "type": "Microsoft.ApiManagement/service/apis",
             "apiVersion": "2020-06-01-preview",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "displayName": "{yourfunctionappname}",
                 "apiRevision": "1",
                 "description": "Import from \"{yourfunctionappname}\" Function App",
                 "subscriptionRequired": true,
                 "path": "{yourcutomAPIpath}",
                 "protocols": [
                     "https"
                 ],
                 "isCurrent": true
             }
         },
         {
             "type": "Microsoft.ApiManagement/service/backends",
             "apiVersion": "2020-06-01-preview",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "description": "{yourfunctionappname}",
                 "url": "https://{yourfunctionappname}.azurewebsites.net/api",
                 "protocol": "http",
                 "resourceId": "https://management.azure.com/subscriptions/{subscriptionID}/resourceGroups/{fiunctionappname}/providers/Microsoft.Web/sites/{yourfunctionappname}",
                 "credentials": {
                     "header": {
                         "x-functions-key": [
                             "{<!-- -->{<!-- -->{yourfunctionappname}-key}}"
                         ]
                     }
                 }
             }
         },
         {
             "type": "Microsoft.ApiManagement/service/namedValues",
             "apiVersion": "2020-06-01-preview",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}-key')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "displayName": "{yourfunctionappname}-key",
                 "tags": [
                     "key",
                     "function",
                     "auto"
                 ],
                 "secret": true
             }
         },
            
         {
             "type": "Microsoft.ApiManagement/service/properties",
             "apiVersion": "2019-01-01",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}-key')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "displayName": "{yourfunctionappname}-key",
                 "value": "{yourfunctionappkey}",
                 "tags": [
                     "key",
                     "function",
                     "auto"
                 ],
                 "secret": true
             }
         },
           
         {
             "type": "Microsoft.ApiManagement/service/apis/operations",
             "apiVersion": "2020-06-01-preview",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}/get-getresource1')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service/apis', parameters('service_teestcomsss_name'), '{yourfunctionappname}')]",
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "displayName": "GetResource1",
                 "method": "GET",
                 "urlTemplate": "/{yourcustomAPIOperationpath}",
                 "templateParameters": [],
                 "responses": []
             }
         },
         {
             "type": "Microsoft.ApiManagement/service/apis/operations",
             "apiVersion": "2020-06-01-preview",
             "name": "[concat(parameters('service_teestcomsss_name'), '/{yourfunctionappname}/get-getresource2')]",
             "dependsOn": [
                 "[resourceId('Microsoft.ApiManagement/service/apis', parameters('service_teestcomsss_name'), '{yourfunctionappname}')]",
                 "[resourceId('Microsoft.ApiManagement/service', parameters('service_teestcomsss_name'))]"
             ],
             "properties": {
                 "displayName": "GetResource2",
                 "method": "GET",
                 "urlTemplate": "/{yourcustomAPIOperationpath}",
                 "templateParameters": [],
                 "responses": []
             }
         }
 }
· 8
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for the reply.

However, the problem I have, after importing the function is that my resource (in the REST API) is named the same as the function. I want a different name for the resource to the name of my Azure function.

So, in my example, after importing the function, I get two API resources, called GetResource1 and GetResource2, but what I want is two API resources called Resource1 and Resource2, these map to the two Functions named above.

Hope this helps.

Thanks

Graham

0 Votes 0 ·

@GrahamAllwood-4295 If you want to change the front end URL of your operation then you need to update the "urlTemplate" value of your api operations. If you want to change the API Name then you need to update "path" parameter value.

I have updated the ARM template and you can find below property:
"path": "{yourcutomeAPIpath} -- Replace yourcutomeAPIpath to another name as per your need.
"urlTemplate": "/{yourcustomAPIOperationpath}", -- "urlTemplate": "/Resource1" or urlTemplate": "/Resource2"

If you want to update it from portal then refer to the below screenshot

To Update API URL :
79530-image.png


Yo Update API URL:

79596-image.png

79613-image.png


0 Votes 0 ·
image.png (41.4 KiB)
image.png (28.4 KiB)
image.png (30.7 KiB)

If you want to use OpenAPI for your function you can try to leverage this: https://github.com/Azure/azure-functions-openapi-extension

0 Votes 0 ·

Thanks for the update @MayankBargali-MSFT .

Whenever I change the FrontEnd settings for the API to change the GET URL (as you show above), I then get a 404 when querying the API in Postman.

Using AppInsights, it appears the the API gateway is getting the request, it then tried to send it off to the functions backend, but the URL it uses to reach the Azure function seems to be following the new Resource name (Resource1 in our case). It is this stage that then returns the 404 back to the gateway.

I have Subscriptions turned off in API Manager so that I can call anonymously.

Are you able to call your newly named API and it reach the function?

Thanks

Graham

0 Votes 0 ·
Show more comments