I'm defining a inbound policy and trying to construct a URL from 2 components. I know how to get these values 1 but 1 but when I have to combine them into one cant figure out the syntax.
First I call a api and save the response
<send-request mode="copy" response-variable-name="createdUser" timeout="20" ignore-error="false">
<set-url>{{Systems.One.Endpoint}}/services/rest</set-url>
</send-request>
I can trace my response is ok like this
<trace source="Contact Id">#(((IResponse)context.Variables["createdUser"]).Body.As<JObject>()["contactId"])</trace>
But I dont know how to create a url from the {{System.One.Endpoint}} and the #(((IResponse)context.Variables["createdUser"]).Body.As()["contactId"])
This here does not work
<send-request mode="copy" response-variable-name="createPeriod" timeout="seconds" ignore-error="true">
<set-url>
{{System.Two.Endpoint}}/api/#(((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"])/createperiod/{{DefaultPeriodlength}}
</set-url>
Everything after the # is just being set as string and not loaded from the actual value form the variable
How can I combine these two values?
Policy expressions can only be used to produce whole value for element/attribute. Named values in contract can be used to represent any part of any attribute/element value, and are inserted into policy prior to it being analyzed/executed.So something like this:
<set-url>#("{{System.Two.Endpoint}}/api/" + ((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"].ToString() + "/createperiod/{{DefaultPeriodlength}}")</set-url>
or if you prefer string interpolation:
<set-url>#($"{{System.Two.Endpoint}}/api/{((IResponse)context.Variables["createPeriod"]).Body.As<JObject>()["contactId"]}/createperiod/{{DefaultPeriodlength}}")</set-url>
Related
I want to set a hardcoded default value for my #RequestParam variable for sometime.
Eg: UI sends--> url.com/v1/apiName?fruits=apple,mango
we want --> url.com/v1/apiName?fruits=apple,mango,banana
Reason for this: UI calls this API they send 2 default values(unfortunately hardcoded) we introduced 1 new value. Their deployment will take time, so for time being, we want to override their inputs.
New to APIM, so need some help.
Thanks in advance.
Have you tried the "set-query-parameter"-policy?
<set-query-parameter name="fruits" exists-action="override">
<value>apple,mango,banana</value>
</set-query-parameter>
If you want to rewrite the value, first you need to get the value and then add your part.
You could use "set-query-parameter" snippet method to do this.
<set-query-parameter name="fruits" exists-action="override">
<value>#{
string fruits = context.Request.OriginalUrl.Querys["fruits"]; // apple mango
return $"{fruits},banana"; // concatenation
}</value>
</set-query-parameter>
This way you'll get the original value from the request and add yours to it.
2 urls you'll need working with api management + some small knowledge in C# (Google it's enough for that)
https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions
https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies
I dont know what i am doing wrong but expression inside to fetch value form variable is not working in set-body policy inside send-request policy. Same thing works in return response.
Scenario is I have to make 2 call where i will be passing data form first call as input to 2nd call.
E.G
<set-body template="liquid">
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/">
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
</soap:Header>
<soap:Body>
<tem:GetSomething>
<tem:contactId>
#{ context.Variables.GetValueOrDefault<string>("ContactId").ToString(); }
</tem:contactId>
</tem:GetSomething>
</soap:Body>
</soap:Envelope>
</set-body>
Here In ContactId is the variable I have created which contains value from the first call output.
I am getting below error for above snippet line
**'There was an error deserializing the object of type System.Guid. The value '
#{ context.Variables.GetValueOrDefault<string>("ContactId").ToString(); }
' cannot be parsed as the type 'Guid'.'. Please see InnerException for more details.**
Can anybody tell what is missing
from Codit Blog
Accessing the context variable
The context variable is also accessible from within Liquid templates. There’s a similar object model, compared to C# expressions, however the syntax is different. As an example, reading a query string parameter in C# works like this: #(context.Request.Url.Query.GetValueOrDefault(“orderId”, “”)). Inside the Liquid template, you need to apply the following notation: {{context.Request.Url.Query[“orderId”]}}.
Hi Guys I am building a Client which Interact with Azure Storage Rest API.
I was going through documentation https://learn.microsoft.com/ru-ru/rest/api/storageservices/fileservices/list-containers2:
And didn't understood the use of parameter prefix and marker which can be send along with Azure request.
It says:
prefix
Optional. Filters the results to return only containers whose name
begins with the specified prefix.
marker
Optional. A string value that identifies the portion of the list of
containers to be returned with the next listing operation. The
operation returns the NextMarker value within the response body if the
listing operation did not return all containers remaining to be listed
with the current page. The NextMarker value can be used as the value
for the marker parameter in a subsequent call to request the next page
of list items.
The marker value is opaque to the client.
With Prefix, I think:
If i have dir structure:
file01.txt
images/image01.jpg
images/folder/image001.jpg
fightVideo/subFolder/current/video001.mpg
fightVideo/subFolder/current/video002.mpg
If I give prefix container name as "fight". It should return
fightVideo.
But I am not sure.
And for Marker I don't understand whats its use?
Please can someone explain the use of Prefix and Marker with examples?
In context of listing containers, if you specify prefix parameter it will list the containers names of which start with that prefix value. It has nothing to do with listing blobs.
List blobs operation also supports this prefix parameter and when you specify this parameter, it will list the blobs names of which start with that prefix value.
So the example you have given is for listing blobs and when you specify flight as prefix there, you will get back fightVideo/subFolder/current/video001.mpg and fightVideo/subFolder/current/video002.mpg in response but not when you call list containers with this prefix.
Regarding marker, Kalyan's explanation is correct but let me add a little bit more to that.
Essentially Azure Storage Service is a shared service and you simply can't ask it to return all the results in one go (if we were to take an analogy from SQL world, you simply can't do SELECT * FROM TABLE kind of thing). Each request to the service is assigned a predefined timeout and the response would include the items fetched in that time + optionally a token if the service thinks that there's more data available. This token is called continuation token. In order to get the next set of items, you would need to pass this continuation token in the marker parameter in your next request.
Each call to storage service will try to return a predefined maximum number of items. For listing blob containers/blobs, this limit is 5000 items. For listing tables/entities, this limit is 1000 items. If there are more items in your account, then apart from this data storage service returns you a continuation token which tells you that there's more data available.
Please note that even though the limit is there but you can't always assume that you will get these number of records. Based on a number of conditions, it is quite possible that you don't get back any data but still receive a continuation token. So your code need to handle this condition as well.
If there are too many blobs to be listed, then the response contains the NextMarker element.
<?xml version="1.0" encoding="utf-8"?>
<EnumerationResults ServiceEndpoint="https://myaccount.blob.core.windows.net">
<Prefix>string-value</Prefix>
<Marker>string-value</Marker>
<MaxResults>int-value</MaxResults>
<Containers>
<Container>
<Name>container-name</Name>
<Properties>
<Last-Modified>date/time-value</Last-Modified>
<Etag>etag</Etag>
<LeaseStatus>locked | unlocked</LeaseStatus>
<LeaseState>available | leased | expired | breaking | broken</LeaseState>
<LeaseDuration>infinite | fixed</LeaseDuration>
<PublicAccess>container | blob</PublicAccess>
</Properties>
<Metadata>
<metadata-name>value</metadata-name>
</Metadata>
</Container>
</Containers>
<NextMarker>marker-value</NextMarker>
</EnumerationResults>
The REST API documentation mentions that the marker value can be used in a subsequent call to request the next set of list items.
You can imagine marker as a paginatator index.
I am having some problems with iterating over a list collection in Mule, using the for-each scope. The iteration works fine, goes over every line, but I can't figure out how to extract the data I need. The revelant code part is below, 'Address' is a list, and I need to get each String from the list, which would be added to the 'finalString' variable, with some extra information.
<foreach collection="#[payload['Address']]" doc:name="For Each" counterVariableName="i" rootMessageVariableName="Original">
<set-variable variableName="finalString" value="#[flowVars['finalString']]" doc:name="Variable"/>
</foreach>
Within the foreach scope, each line will be represented by payload.
So you could use something like:
<foreach collection="#[payload['Address']]" doc:name="For Each" counterVariableName="i" rootMessageVariableName="Original">
<set-variable variableName="finalString" value="#[flowVars['finalString'] + payload]" doc:name="Variable"/>
</foreach>
But that will look like "nulladdress1address2" but you can change this to check for null or concat differently.
Query string parameter
I have seen plenty of examples of reading query string parameters.
For example take the following URI:
/api/Profile?id={accountId}
The accountId can be read in the policy xml using the following syntax:
context.Request.Url.Query["accountId"]
Route parameter
But what if my URI is structured as:
/api/profiles/{accountId}
How do I read accountId in the policy xml when the parameter is not in the query string?
Using the example above I can read the accountId by the following syntax:
context.Request.MatchedParameters["accountId"]
For example I could assign it to a variable for usage elsewhere in the APIM policy file:
<set-variable name="account-id" value="#(context.Request.MatchedParameters["accountId"])" />
There isn't a massive amount of documentation about it, but thankfully there is at least some mention of the Context variable on learn.microsoft.com.
There is a GitHub repository with quite some snippets including your use case: https://github.com/Azure/api-management-policy-snippets/blob/master/policy-expressions/README.md
For your concrete example, you can use this:
context.Request.MatchedParameters.GetValueOrDefault("accountId", "optional-default-value")
The benefit compared to the other solution is that the policy evaluation does not fail if the URI parameter does not exist. It will use the default value as a fallback instead. Otherwise a 500 Internal Server Error would be returned.