Return HTTP 405 When HTTP Method Not Match in Azure API Management

In Azure API Management, when the HTTP method of a request doesn’t match the one defined in the corresponding operation, APIM returns status code HTTP 400 Resource Not Found to the client. For example, the OOTB Echo API defined the Retrieve resource (cached) operation with HTTP GET. If you call it with HTTP POST, you’ll get HTTP 404 Resource Not Found in the response.

The HTTP 404 returned by APIM in this scenario doesn’t really follow the definition of HTTP status code strictly. According to the definition, HTTP 405 Method Not Allowed is designated for this situation. There was a feedback for this issue to APIM team and it would be addressed in the future according to the response. But before that, we have to use some workaround to bypass this issue. Here is how you can do it with policies in APIM.

Handle the error

When APIM failed to identify an API or operation, it will raise a configuration error which will returns HTTP 404. What we need to do is to handle this error and change the status code to HTTP 405. In this way, you avoid the overhead of creating operations for each of the HTTP methods to handle the situation. The next question is on which scope the error should be handled. Depending on the configurations of your APIM, I think you can handle the error on either all operations or all APIs.

The policy code

The following policy code is a sample for Echo API all operations.

<on-error>
    <base />
    <choose>
        <when condition="@(context.LastError.Source == "configuration" && context.Request.Url.Path == "/echo/resource-cached")">
            <return-response>
                <set-status code="405" reason="Method not allowed" />
                <set-body>@{
                    return new JObject(
                        new JProperty("status", "HTTP 405"),
                        new JProperty("message", "Method not allowed")
                    ).ToString();
                }</set-body>
            </return-response>
        </when>
        <otherwise />
    </choose>
</on-error>

The tricky part is in the <when> condition. The first part of the condition is to check if this is a configuration error. If it is, the second part will test if the request is to Retrieve resource (cached) operation. The second test is to avoid the situation where a real HTTP 404 happens.

You may wonder why I used context.Request rather than context.Operation to test which operation it is. The reason is APIM sets context.Operation to null in this case because it cannot identify which operation it is (and that is why the configuration error happens).

You can use this walkaround to return HTTP 405 until APIM fixes its behavior.

Creating API Management instances in Parallel with Automation Runbook

Provisioning an Azure API Management (APIM) service instance is a bit time-consuming task. It usually takes 20 to 30 minutes to get an instance created. In most of cases, it is fine because you usually don’t have the needs to create many APIM instances. For most customers, 2 or 3 instances are enough for their solutions. And provisioning APIM instances doesn’t seem to be a day to day work.

But recently I am preparing a lab environment for an APIM related lab session that I am going to deliver in an event. Given that provisioning an APIM instance would take 20 to 30 minutes, it is impracticable to let attendees create the instances during the lab session. I have to provision an APIM instance for each attendee before the lab session. As there could be more than 40 attendees, I have to do it with a script rather than manually clicking around in Azure portal.

APIM supports creating instances with PowerShell. It doesn’t support Azure CLI at the moment. The Cmdlet for instance creation is New-AzureRmApiManagement, and as mentioned in the document, this is a long running operation which could take up to 15 minutes. If I simply create a PowerShell script to run this operation sequentially, it would take tens of hours to get all APIM instances created. It is not acceptable. I have to run the operations in parallel.

I ended up creating a PowerShell Workflow runbook in Azure Automation to do the task. PowerShell Workflow has several ways to support parallel processing, and Azure Automation provides the enough computing resource to run all operations in parallel.

The following code snippet shows the key part of the workflow.

The code is quite straight forward. I need to include the Azure authorization code for each of the parallel operation because when operations are running in parallel, each operation runs in its own process. So each of them need to be authorized before they can access the Azure resource.

For the completed code, you can get it from here. To run this workflow runbook in Azure Automation, the AzureRM.ApiManagement module needs to be imported into Azure Automation. That’s all.