We are using Azure API Management in a project, and we want APIM to be our shield against invalid requests. Since we've already specified what a valid request looks like in our OpenAPI specification and uploaded that to APIM, it seems like a reasonable assumption.
I have specified a component in our OpenAPI (version 3.0.1) specification like this:
TemperatureRange:
description: Defines a desired temperature range
required:
- min
- max
properties:
min:
type: number
max:
type: number
When uploaded to APIM the schema looks fine:
{
"required": [
"min",
"max"
],
"properties": {
"min": {
"type": "number"
},
"max": {
"type": "number"
}
},
"description": "Defines a desired temperature range"
}
However, when I call an API that uses this definition, I can leave out properties even though they are marked as required.
The payload I sent looks like this, leaving out the required max property:
[{
"someProperty": "someValue",
"temperatureRange": {
"min": -18,
}
}]
I can't find any documentation on this and it isn't mentioned in any restrictions. What is the intended behavior?
Looks like this is functionality that has been requested but has not been implemented: https://feedback.azure.com/forums/248703-api-management/suggestions/17369008-schema-validation-in-apim
Related
Has anyone here used the PUT /MoveEntry call successfully before? I can make the call to create the record, but I was expecting the API to populate the lot number and it is not. It does by UI, but not by API. Is there a trick that I'm missing?
Update 1:
PUT /MoveEntry
{
"Hold": {
"value": true
},
"Details": [
{
"OrderType": {
"value": "RO"
},
"ProductionNbr": {
"value": "RO0000001"
},
"Quantity": {
"value": 1
},
"Location": {
"value": "PRODRECPT"
},
"Warehouse": {
"value": "ABBOTSFORD"
}
}
]
}
It always records the document successfully, but never has the lot number.
Could it be a lot class configuration issue?
Update 2:
Acu support agrees this looks like a defect and has passed the case on to Acu development.
I would take a look at the Numbering Sequence called AMBatch as that is the one that seems to be used by default for me on the Move Entry screen.
After working with Acu Support, it came back the API requires the "OperationNbr" field to be populated with the Bill of Materials operation number. Then the lot number is generated as expected.
I am trying to use the AWS boto3 Python sdk to work with the Access Analyzer api. Specifically the list_findings action. The relevant api documentation is here
https://docs.aws.amazon.com/access-analyzer/latest/APIReference/API_ListFindings.html
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/accessanalyzer.html#AccessAnalyzer.Client.list_findings
According to the documentation the input parameters to this action includes
"sort": {
"attributeName": "string",
"orderBy": "string"
}
The documentation, as far as I can tell, doesn't place any restrictions on what the attributeName can be and therefore it seems that any valid field on the returned findings should be valid input. The structure of the returned findings is described as
{
"findings": [
{
"action": [ "string" ],
"analyzedAt": number,
"condition": {
"string" : "string"
},
"createdAt": number,
"error": "string",
"id": "string",
"isPublic": boolean,
"principal": {
"string" : "string"
},
"resource": "string",
"resourceOwnerAccount": "string",
"resourceType": "string",
"sources": [
{
"detail": {
"accessPointArn": "string"
},
"type": "string"
}
],
"status": "string",
"updatedAt": number
}
],
"nextToken": "string"
}
I would like to sort by the createdAt attribute on the returned findings. For all the fields I have tried they always return the same error
Error has occured in AWS Access Analyzer Integration: An error occurred (ValidationException) when calling the ListFindings operation: Invalid sort.attributeName
An example piece of code I am trying is as follows
client = aws_session(
region='region',
roleArn='roleArn',
roleSessionName='roleSessionName',
roleSessionDuration='roleSessionDuration',
)
kwargs = {
'analyzerArn': 'some_ARN_here'
}
kwargs['sort'] = {
'attributeName': 'createdAt',
'orderBy': 'ASC'
}
response = client.list_findings(**kwargs)
Without the sort arguement the code behaves as expected and returns results. No matter what attribute I use in the sort field it always returns the same error.
How do I know what the valid attributeName's are? What is the correct format for passing parameters in this case? I have not been able to find any other examples online using this particular portion of the boto3 sdk. Any insight would be appreciated.
I am looking to sort the findings in order to retrieve only the most recent. By default the oldest is returned first when specifying maxResults as an arguement.
The answer, and hopefully this saves someone a months time, is that this is not documented correctly anywhere. I had to use my browsers inspector to see the params passed in the request when performing some actions in the AWS UI for Access Analyzer and noticed they were passing UpdatedAt in the attributeName for the sort field.
This subtle distinction was breaking the API call as the U needs to be capitalized in updatedAt when being passed as a parameter. Where is this is documented? Seems nowhere. Not all the fields on findings worked as a sort attribute, such as createdAt. So in order to use the sort field you need to format as such on list_findings
kwargs['sort'] = {
'attributeName': 'UpdatedAt',
'orderBy': 'ASC'
}
This is not representative of how the fields are returned from the API and is not intuitive. The way the parameters are passed to the API are not in the same format as they are received.
I need to be able to retrieve the linked work item of any given specific commit. I'm currently using the following api call
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/commits/{commitId}?api-version=5.0
with the following response
{
"parents": [],
"treeId": "7fa1a3523ffef51c525ea476bffff7d648b8cb3d",
"push": {
"pushedBy": {
"id": "8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d",
"displayName": "Chuck Reinhart",
"uniqueName": "fabrikamfiber3#hotmail.com",
"url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d",
"imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=8c8c7d32-6b1b-47f4-b2e9-30b477b5ab3d"
},
"pushId": 1,
"date": "2014-01-29T23:33:15.2434002Z"
},
"commitId": "be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4",
"author": {
"name": "Chuck Reinhart",
"email": "fabrikamfiber3#hotmail.com",
"date": "2014-01-29T23:32:09Z"
},
"committer": {
"name": "Chuck Reinhart",
"email": "fabrikamfiber3#hotmail.com",
"date": "2014-01-29T23:32:09Z"
},
"comment": "First cut\n",
"url": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/commits/be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4",
"remoteUrl": "https://dev.azure.com/fabrikam/_git/Fabrikam-Fiber-Git/commit/be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4",
"_links": {
"self": {
"href": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/commits/be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4"
},
"repository": {
"href": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249"
},
"changes": {
"href": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/commits/be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4/changes"
},
"web": {
"href": "https://dev.azure.com/fabrikam/_git/Fabrikam-Fiber-Git/commit/be67f8871a4d2c75f13a51c1d3c30ac0d74d4ef4"
},
"tree": {
"href": "https://dev.azure.com/fabrikam/_apis/git/repositories/278d5cd2-584d-4b63-824a-2ba458937249/trees/7fa1a3523ffef51c525ea476bffff7d648b8cb3d"
}
}
}
from https://learn.microsoft.com/en-us/rest/api/azure/devops/git/commits/get?view=azure-devops-rest-5.0 and am missing a way to see what work item its linked to or if it is linked at all. Does anyone know of a way to get this information? Thanks
You could use the Get Commits API, docs here. The base request looks like:
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/commits?api-version=5.0
You could then add the following parameters:
fromCommitId - string - If provided, a lower bound for filtering commits alphabetically
toCommitId - string - If provided, an upper bound for filtering commits alphabetically
includeWorkItems - boolean - Whether to include linked work items
So that your final query would look something like, with your toCommitId and fromCommitId parameters being your commit id that you are after (the documentation doesn't specificy whether these are inclusive or exclusive so your might have to tweak this slightly):
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/commits?includeWorkItems=true&.toCommitId={searchCriteria.toCommitId}&fromCommitId={searchCriteria.fromCommitId}&api-version=5.0
The result should contain a workItems property inside each commit object of the response as per this documentation.
Note:
Parameters that use the searchCriteria prefix in their name can be specified without it as query parameters, e.g. searchCriteria.$top -> $top
There is also:
ids - array - If provided, specifies the exact commit ids of the commits to fetch. May not be combined with other parameters.
Which could allow you to forgo passing in the to and from commit ids but the docs state that it May not be combined with other parameters - even though the example request does combine it with other parameters. I haven't tried this myself so please do comment when you find out whether you go with from-to id or just ids.
OPs action
The OP ended up using the following request as they didn't mind all commits being returned:
GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/commits?includeWorkItems=true&api-version=5.0
I have a backend API (that implements ApiController) which I'd like to put behind an APIM API. ApiController allows us to discriminate between two different GET operations based on the query parameters that are passed in. When I attempt to define these endpoints in APIM, I get the following error:
The message suggests an endpoint is defined solely by the path and operation. But that seems to contradict documentation I found here which suggests there's a way to differentiate between operations based on query parameters:
Required parameters across both path and query must have unique names.
(In OpenAPI a parameter name only needs to be unique within a
location, for example path, query, header. However, in API Management
we allow operations to be discriminated by both path and query
parameters (which OpenAPI doesn't support). That's why we require
parameter names to be unique within the entire URL template.)
I have an ApiController that defines two different Get operations, differing only by the query parameters. How do I represent that in my APIM API?
The problem comes from multiple operation objects with the same OperationId. This is invalid swagger. In the Swagger file did not match the name of the selected API, so change the title attribute of the doc tag to match the destination API it worked..
Here is a similar SO thread you could refer to.
I got my answer from Azure support, sharing the info here:
APIM endpoints are defined by the path, method, and the name you assign to the operation. To differentiate between two GET endpoints to the same controller, differing only by query parameters, you need to hardcode required query parameters into the path. See the following two images:
In the latter image, the hardcoded query parameter is classified by the UI as a template parameter, but it still behaves like a regular query parameter. Query arguments defined in this way:
Are required
Can appear in anywhere in a request's list of query arguments
Are not case-sensitive
Are listed as a "Request Parameter" along side all other path parameters and query arguments in the Development Portal
Edit:
There's a typo in the screenshots. The URLs are case sensitive, and the casing of "blah" were different in each case. Here's what the the Open API Specification looks like when the casing is consistent. The overloaded path (with the query parameter hardcoded into the path template) appears in a section called x-ms-paths:
{
"swagger": "2.0",
"info": {
"title": "Echo API",
"version": "1.0"
},
"host": "<hostUrl>",
"basePath": "/echo",
"schemes": ["https"],
"securityDefinitions": {
"apiKeyHeader": {
"type": "apiKey",
"name": "Ocp-Apim-Subscription-Key",
"in": "header"
},
"apiKeyQuery": {
"type": "apiKey",
"name": "subscription-key",
"in": "query"
}
},
"security": [{
"apiKeyHeader": []
}, {
"apiKeyQuery": []
}],
"paths": {
"/Blah": {
"get": {
"operationId": "blah",
"summary": "Blah",
"responses": {}
}
}
},
"tags": [],
"x-ms-paths": {
"/Blah?alpha={alpha}": {
"get": {
"operationId": "blah2",
"summary": "Blah2",
"parameters": [{
"name": "alpha",
"in": "query",
"required": true,
"type": "string"
}],
"responses": {}
}
}
}
}
I'm trying out Azure's API App service, and I have a valid Swagger schema exposed for the service to consume, following the documentation here. I can retrieve the Swagger schema at its endpoint both on my local server and once the API App is deployed, and I've updated my web.config file to include the application/json MIME type. My apiapp.json file is as follows:
{
"$schema": "http://json-schema.org/schema#",
"id": "apiapp.dlxdev",
"namespace": "microsoft.com",
"gateway": "/* gateway, copied from Azure portal */",
"version": "1.0.0",
"title": "DLX API App (Dev)",
"summary": "The developer version of the DLX API App.",
"author": "Daniel W. Hieber",
"endpoints": {
"apiDefinition": "/api.json",
"status": null
}
}
Even though my endpoint is defined as /api.json, when I go to the API Definition blade in the Azure Portal, it says Failed to get metadata for 'apiApp.dlxDev' from endpoint '/swagger/docs/v1': Failed status code: 'NotFound'. Response Body: 'Not Found'.. It seems as though Azure is still looking for my Swagger file at the default /swagger/docs/v1 endpoint rather than the /api.json endpoint I specified.
I've also tried creating a metadata folder and placing my Swagger schema there (renaming it to apiDefinition.swagger.json, following the documentation), and didn't have any luck with that either.
Any ideas where I'm going wrong? Why isn't Azure detecting the endpoint for my Swagger schema?
UPDATE 1
Now I receive the following error in the API Definition blade: #/definitions/: Cannot determine schema of data definition named ''. This doesn't appear to be a problem with the Swagger schema itself, since all of my schema references are formatted correctly, and the schema itself is valid.
UPDATE 2
One thing that I needed to do was restart the gateway under which my API app was being hosted. Restarting the gateway is what caused the error message to change. So I think the app is recognizing my Swagger schema now. But I'm still not sure why I'm getting the 'Cannot determine schema' error, since my schema is formatted correctly.
Now I receive the following error in the API Definition blade: >#/definitions/: Cannot determine schema of data definition named ''. This >doesn't appear to be a problem with the Swagger schema itself, since all of my >schema references are formatted correctly, and the schema itself is valid.
I believe Azure requires a default response defined in swagger for every operation. Perhaps double check that every operation has a default response and every response has a schema property which resolves to a valid schema in the definitions section.
Like:
"paths": {
"/Categories": {
"get": {
"tags": [
"Categories"
],
...
],
...
"responses": {
"200": {
"description": "EntitySet Categories",
"schema": {
"$ref": "#/definitions/NorthwindAPI.Models.Category"
}
},
"default": {
"description": "Unexpected error",
"schema": {
"$ref": "#/definitions/_Error"
}
}
},
...
"definitions": {
"NorthwindAPI.Models.Category": {
"properties": {
"CategoryID": {
"format": "int32",
"description": "CategoryID",
"type": "integer"
},
"CategoryName": {
"description": "CategoryName",
"type": "string"
},
"Description": {
"description": "Description",
"type": "string"
},
"Picture": {
"description": "Picture",
"type": "string"
}
}
},
"_Error": {
"properties": {
"error": {
"$ref": "#/definitions/_InError"
}
}
},
HTH,
Josh