Azure API Management - Can I define a custom response status code? - azure-api-management

When setting up the all the possible response codes and their descriptions for an endpoint in API Management Service, I can only choose an existing status code from a dropdown list, but it doesn't allow me to add a custom status code, such as 499. I use the 499 status code in my API for a specific type of error relevant to my applicatoin. Is there any way to add this to the list of responses?

You could dynamic mocking using APIM with an APIM policy called return-response.
<return-response>
<set-status code="200" reason="OK" />
<set-header name="content-type" exists-action="override">
<value>"application/json"</value>
</set-header>
<set-body>{
"id": "cat12345",
"name": "Garfield",
"tag": "Sleepy Cat"
}</set-body>
</return-response>
For more details, you could refer to this tutorial.

Not with forms UI. But if you select an API, there'll be a pencil in Frontend block on Design tab. It allows you to edit your API specification in OpenAPI 2/3 spec. Using that it should be possible to add a custom response statuses code.

Related

Azure API Management - Authentication using HTTP query parameters

I want to expose an API that uses HTTP query parameters for authentication. Something like this:
{root-backendURL}/resource?login=loginName&password=loginPassword
I am using Azure API Management. I've created a new API which points to the backend service, and I've created a new operation called "Resource". For that operation I've added two Query parameters that are required.
Now I want to expose and make use of the APIM Gateway URL that should look something like this:
{root-GatewayURL}/apiName/resource
Adding those two required query parameters will make the URL look like this:
{root-GatewayURL}/apiName/resource?login=loginName&password=loginPassword
When I test the Gateway URL using Postman, I get a 401 response.
{
"code": 401,
"errors": [
{
"message": "Authentication failed."
}
]
}
I've tried to use a Send-Request policy and add from there the query parameters. This way it works.
<rewrite-uri template="/" />
<set-variable name="login" value="loginName" />
<set-variable name="password" value="loginPassword" />
<send-request mode="new" response-variable-name="resource" ignore-error="false">
<set-url>#($"{root-BackendURL}/resource?login={(string)context.Variables["login"]}&password={(string)context.Variables["password"]}")</set-url>
<set-method>GET</set-method>
</send-request>
<return-response>
<set-body>#(new JObject(new JProperty("resource",((IResponse)context.Variables["resource"]).Body.As<JObject>())).ToString())</set-body>
</return-response>
I've double checked the URLs and they are identical. Why do I get different results?
I do not want to use the policy, I want to make it work using the query parameters, because I need to use also an ID for the resource and also other query parameters, for example:
{root}/resource/{id}?limit=25&offset=50&loginName&password=loginPassword

How to perform a 302 Redirect with a forwarding URL

We are using Xamarin and UITest in order to create UI tests for our application.
We are using Azure API management for integration, and am trying to mock our Authentication process.
We are using Xamarin Essentials WebAuthenticator, which opens an external browser in order to do the two step OAuth and load a login page.
Since UITest cannot control anything outside of the app itself, we need to have API management respond by giving a 302 redirect back to the controlling app, with our test authentication tokens that are mocked.
I've tried creating a mock response that returns a 302, with a Location header with the value of our return url for the app. However whenever I test this in the APIM test page, it simply just returns a 200 OK.
Is it possible to make a GET request to APIM, which performs a 302 redirect to a specified uri, with a body of mocked test data?
You may try with a return-response policy.
Something similar to this example:
<when condition="#(context.Request.OriginalUrl.Scheme == Uri.UriSchemeHttp)">
<return-response>
<set-status code="302" reason="Temporary Redirect" />
<set-header name="Location" exists-action="override">
<value>#{
var uri = context.Request.OriginalUrl;
return Uri.UriSchemeHttps + "://" + uri.Host + uri.Path + uri.QueryString;
}</value>
</set-header>
</return-response>
</when>
For your reference: https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#ReturnResponse

How can I throw exceptions in set-body in Azure API Management?

The API that I'm working on now throwing 500 Internal Server Error when the request body do not have certain property inside. I want to eliminate that and instead, it returns another status code such as 400 Bad Request. I get that the error is return from APIM from Azure, how can I throw the error inside the set-body policy since I deserialize the request body in here?
I've read many posts and documents but no luck on succeeding that. Here's my code right now:
<inbound>
<send-request mode="new" response-variable-name="" timeout="60 sec">
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>#{
var request = context.Request.Body.As<JObject>(preserveContent: true);
if(String.IsNullOrEmpty((string)request["id"])){
WHAT SHOULD I PUT HERE?
}
return request.ToString();
}</set-body>
</send-request>
</inbound>
Thanks and appreciate if anyone could help.
You can use the return response policy in Azure API Management
https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies#ReturnResponse

Why does Set-Body policy not recognize my POST body?

I'm trying to connect an API endpoint in Azure (api management) to a backend service. However, the set-body policy isn't recognizing my JSON body and thus isn't transforming it for the backend call.
I've tried all iterations i can think of for the "Liquid" and "None" templates. The microsoft documentation is useless as even the "liquid" template is capitalized in the doc while it NEEDS to be lowercase. Even the Deep Dive article that everyone points to is misleading and/or out of date.
i was once able to get the {{context.Request.OriginalUrl}} reference to work using liquid template, but i can't seem to get the {{body.json}} reference to work
Here's the policy i have in the section (purely to test - this has no use for what i'm doing):
<set-body template="liquid">
Calling User Agent: {{context.Request.OriginalUrl}}
</set-body>
And here's an example of what i have to try to read the json body (passing through via POST):
<set-body template="liquid">{{body}}</set-body>
I've tried several iterations and inputs like below:
<set-body template="liquid">{{body.json}}</set-body>
while passing through a body like this:
{"json":"this is an example body"}
No matter what I do, this is what I see in the trace after testing the call:
set-body (0.069 ms)
{
"input": null,
"output": ""
}
i'm obviously open to using the "none" template, but i run into the same problems. The documentation is wrong - if i copy/paste the example:
<set-body>#(context.Body.As<String>())</set-body>
I get errors like:
One or more fields contain incorrect values:
Error in element 'set-body' on line 32, column 10: 'IProxyRequestContext' does not contain a definition for 'Body' and no extension method 'Body' accepting a first argument of type 'IProxyRequestContext' could be found (are you missing a using directive or an assembly reference?)
and when i do get it to not error, it returns the same "output":"" output.
For being able to access the body as an object in the liquid template, you will have to set the Content-Type header to application/json as mentioned in the docs.
If your requests are already sending this header, then it should work without setting it too.
A policy like this in the inbound section will guarantee it works as expected
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body template="liquid">{{body.json}}"}</set-body>
As for accessing it via the context variable, you have to access it as context.Request.Body.As<string>() as mentioned in the docs, so something like this
<set-body>#(context.Request.Body.As<string>())</set-body>
The official reference for set-body doesn't seem to have the problems you've mentioned.
Was there any other doc you are referring to? If its on learn.microsoft.com, you could open an issue at the end of each doc.

How can I create API with my custom code in Azure?

Can I create an API that has the definition of the sum of two numbers and returns me the output. I want to write all the logic in Azure Web API Management itself. Is there any provision, or do I need to create it in my machine and import it to Azure Web API Management?
Is it possible to create it in Web API in Azure itself, rather than importing it?
There are two ways to go about this. APIM does support policy expressions: https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions This allows you to plug in arbitrary code into request processing pipeline. You can check policy samples here: https://learn.microsoft.com/en-us/azure/api-management/policy-samples to see this in action. When combined with other policies it does allow you to a lot of things. If we assume that you "addition" operation has URI template of /add?a={a}&b={b} then you can sum up and return result with one simple policy:
<return-response>
<set-status code="200" reason="OK" />
<set-body>#{
var a = int.Parse(context.Request.Url.Query.GetValueOrDefault("a", "0"));
var b = int.Parse(context.Request.Url.Query.GetValueOrDefault("b", "0"));
return (a + b).ToString();
}</set-body>
</return-response>
As you can see this is a pretty much regular C# code, but it's limited in what you can do and what types you can use (see first link). If you can't make it work within these limitations your best bet is to move custom logic outside of APIM, into Azure Functions, for example.