Api Management sets forward-request for a one way request - azure

I want to log to log the request and the response so I place a one-way-request in the inbound and the outbound section:
<policies>
<inbound>
<send-one-way-request mode="new">
<set-url>#("example.com")</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>#(context.Request.Body.As<string>(preserveContent: true))</set-body>
</send-one-way-request>
</inbound>
<backend>
<base />
</backend>
<outbound>
<send-one-way-request mode="new">
<set-url>#("example.com")</set-url>
<set-method>POST</set-method>
<set-header name="Content-Type" exists-action="override">
<value>application/json</value>
</set-header>
<set-body>#(context.Response.Body.As<string>(preserveContent: true))</set-body>
</send-one-way-request>
</outbound>
</policies>
identical call, except the body.
When I check the trace I see this in the inbound section:
send-one-way-request (0 ms)
"One way request was successfully send to https://...."
forward-request (9690 ms)
{
"response": {
"status": {
"code": 200,
"reason": "OK"
},
"headers": [
{
"name": "Pragma",
"value": "no-cache"
},
{
"name": "Content-Length",
"value": "2"
},
{
"name": "Cache-Control",
"value": "no-cache"
},
{
"name": "Content-Type",
"value": "application/json; charset=utf-8"
},
{
"name": "Date",
"value": "Wed, 05 Jul 2017 07:56:14 GMT"
},
{
"name": "Expires",
"value": "-1"
},
{
"name": "Server",
"value": "Microsoft-IIS/8.0"
},
{
"name": "X-AspNet-Version",
"value": "4.0.30319"
},
{
"name": "X-Powered-By",
"value": "ASP.NET"
}
]
}
}
but in the outbound I only get:
send-one-way-request (0 ms)
"One way request was successfully send to https://...."
and no forward request. Because I use a one way request I don't expect a response from the calls and I can't remember to have the forward-request in the inbound part (didn't found them in a saved traced call with a one way request in the inbound).
Is there maybe a configuration anything else that triggers a forward-request?
Edit:
I use the azure function to handle this. When I make a typo in the subdomain the forward-request disappears, but when I make a typo in the function name it is still there... Both requests are directed to the same azure function.
Edit2:
This is getting more confuse: when I send the default body from the swagger file the request-forward is not there. If I repeat the request or if i modify the default body it appears...

Since send-one-way request policy is completely asynchronous in regards to request processing itself, there is no guarantee that reply from such request will be logged, because by the time it is received the request itself may be long processed, response returned to client along with tracing information. So it works as a best effort, if by the time when response to send-one-way-request is received the main request is still being processed response will be logged, otherwise not.
In the first example reply to one-way request in inbound is logged because there is still a lot processing to be done on the main request - send request to backend, process outbound section. But when one-way request is placed as the last statement in outbound, right before response to the client is sent - response to one-way request will come too late to be placed into trace.
Typo in subdomain may trigger longer connection time, if such domain not actively refuses connections, thus will stall response, thus it will disappear from trace.
It's all a question of timing. If you want to make sure that main request processing is stalled until you get response from these side requests use send-request policy instead.

Related

Why does clangd respond with "method not found" when using textDocument/didOpen?

I try to communicate with clangd. The first initialization is fine, but when trying to open a document with "textDocument/didOpen" i get the response "method not found". I cannot find any other method in the specification for opening documents. Is it the wrong method, or am I doing something else wrong?
My request
Content-Length: 1771
{
"id": 2,
"jsonrpc": "2.0",
"method": "textDocument/didOpen",
"params": {
"textDocument": {
"languageId": "cpp",
"text": "file content...",
"uri": "file://src/main.cpp",
"version": 1
}
}
}
The response I get:
Content-Length: 77
{
"error": {
"code": -32601,
"message": "method not found"
},
"id": 2,
"jsonrpc": "2.0"
}
The language server protocol distinguishes between request messages which are client --> server messages to which the server will respond, and notification messages which are client --> server messages which are meant to notify the server about something and do not require a response.
The id field is only expected for request messages (it's used to associate the response with the request). However, textDocument/didOpen is a notification message. Removing the id field should fix the error.
Further reading:
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#requestMessage
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#notificationMessage

APIM - validate-content on consumption tier

I recently changed our APIM instance from the developer tier, to the consumption tier, and am seeing some weird behavior in the validate-content policy. On the developer tier, this policy would work as expected and return a 400 error with the appropriate error message.
Below is the policy:
<validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="prevent">
<content type="application/json" validate-as="json" action="prevent" />
</validate-content>
Below is an example from the trace and the response from developer tier (expected behavior):
//Trace
validate-content (0.100 ms)
{
"name": "application/json",
"type": "RequestBody",
"validationRule": "IncorrectMessage",
"details": "Body of the request does not conform to the definition skills-POST-request, which is associated with the content type application/json. Property 'nam' has not been defined and the schema does not allow additional properties. Line: 1, Position: 7",
"action": "Prevented"
}
//Response
HTTP/1.1 400 Bad Request
vary: Origin
{
"statusCode": 400,
"message": "Body of the request does not conform to the definition skills-POST-request, which is associated with the content type application/json. Property 'nam' has not been defined and the schema does not allow additional properties. Line: 1, Position: 7"
}
However, now the same policy on the consumption tier returns the following trace and response (incorrect behavior):
//Trace
validate-content (4.736 ms)
{
"name": "application/json",
"type": "RequestBody",
"validationRule": "IncorrectMessage",
"details": "Body of the request does not conform to the definition skills-POST-request, which is associated with the content type application/json. Property 'nam' has not been defined and the schema does not allow additional properties. Line: 1, Position: 7",
"action": "Prevented"
}
validate-content (0.714 ms)
{
"name": null,
"type": "RequestBody",
"validationRule": "ValidationException",
"details": "Body of the request cannot be validated for the content type application/json. Value cannot be null.\r\nParameter name: key",
"action": "Prevented"
}
validate-content (2.679 ms)
{
"messages": [
"Value cannot be null.\r\nParameter name: key"
]
}
//response
HTTP/1.1 500 Internal Server Error
vary: Origin
{
"statusCode": 500,
"message": "Internal server error",
"activityId": "b3d76aed-fdf0-4240-a5c1-db49fed82105"
}
This looks to be some sort of bug perhaps in the content validation policy for the consumption tier?
I entered a support request with Microsoft and they determined this was a bug in API management. The workaround was to add the following to policy:
errors-variable-name="requestBodyValidation"
So the final policy now looks like:
<validate-content unspecified-content-type-action="prevent" max-size="102400" size-exceeded-action="prevent" errors-variable-name="requestBodyValidation">
<content type="application/json" validate-as="json" action="prevent" />
</validate-content>
As per the Azure documentation,Consumption tier in APIM supports TLS Settings,External Cache,Client Certificate authentication & Graph QL API's only. Therefore validate-content APIM policy doesn’t work for APIM Services running on consumption SKU.

Client Certificate is not being passed on by Azure Application Gateway

I've picked up something that someone else has set up.
We have an API Management instance, siting behind an Application Gateway, which has a policy on an API:
<inbound>
<choose>
<when condition="#(context.Request.Certificate == null)">
<return-response>
<set-status code="403" reason="Client certificate required..d1PD" />
</return-response>
</when>
</choose>
<choose>
<when condition="#(!context.Request.Certificate.Verify())">
<return-response>
<set-status code="403" reason="Client certificate cannot be verified..d2PD " />
</return-response>
</when>
</choose>
<choose>
<when condition="#(!context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint))">
<return-response>
<set-status code="403" reason="Client certificate is untrusted or invalid..d3PD" />
</return-response>
</when>
</choose>
<base />
</inbound>
In Postman I am passing a cert and key. The Postman Console shows
Client Certificate:
keyPath:"C:\selfsigned\internalscm.X.com.key"
pemPath:"C:\selfsigned\internalscm.X.com.crt"
pfxPath:""
I'm passing Ocp-Apim-Trace in the header of the request so am getting a trace back which contains:
traceEntries {2}
inbound [10]
..
6 {4}
source : authentication-certificate
timestamp : 2019-08-06T08:55:31.3435485Z
elapsed : 00:00:00.0006857
data {2}
message : Certificate was attached to request per configuration.
certificate {...}
7 {4}
source : choose
timestamp : 2019-08-06T08:55:31.3435485Z
elapsed : 00:00:00.0007011
data {3}
message : Expression was successfully evaluated.
expression : context.Request.Certificate == null
value : true
UPDATE:
The authentication-certificate assessment is of the backend's certificate and is nothing to do with the client certificate (.key and .crt) that Postman claims to be including in the request (the same result is returned if I pass a pfx and password instead of .key and .crt).
When I hit the API that the Gateway is protecting, I can see in the trace that it is processing the client certificate (and returning a 200):
{
"source": "client-certificate-handler",
"timestamp": "2019-08-09T15:47:46.3825928Z",
"elapsed": "00:00:00.0005974",
"data": "Requesting client certificate because next handler requires access to it."
},
{
"source": "client-certificate-handler",
"timestamp": "2019-08-09T15:47:46.6950495Z",
"elapsed": "00:00:00.3225172",
"data": "Client certificate thumbprint '6C03F4E7999999999999999999999999' received."
},
{
"source": "choose",
"timestamp": "2019-08-09T15:47:46.6950495Z",
"elapsed": "00:00:00.3225288",
"data": {
"message": "Expression was successfully evaluated.",
"expression": "context.Request.Certificate == null",
"value": false
}
},
{
"source": "choose",
"timestamp": "2019-08-09T15:47:46.9606395Z",
"elapsed": "00:00:00.5849700",
"data": {
"message": "Expression was successfully evaluated.",
"expression": "!context.Request.Certificate.Verify()",
"value": false
}
},
{
"source": "choose",
"timestamp": "2019-08-09T15:47:46.9606395Z",
"elapsed": "00:00:00.5850060",
"data": {
"message": "Expression was successfully evaluated.",
"expression": "!context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint)",
"value": false
}
}
So it looks like AppGateway is dropping the client certificate.
The trace doesn't give me enough to start deducing why the client certificate (assuming that Postman is transmitting it to the Gateway as it does the API) is being dropped. Where should I start?
For ref, when I remove the policy the request is processed as expected.
I'm not sure if you can make AppGateway pass the certificate - you need to check their docs. The reason I'm skeptical is bacuse the whole idea of AppGateway is to look into traffic and provide protection by doing that. And the only way to d othat is to terminate SSL connection at AppGateway level. See here for more information: https://learn.microsoft.com/en-us/azure/application-gateway/ssl-overview there are two modes for AppGateway: SSL temination when AppGateway makes HTTP (not HTTPS) calls to backend, and SSL end-to-end when AppGateway uses own SSL certificate to connect to backend.
Some client certificate information can be passed to backend via server variables: https://learn.microsoft.com/en-us/azure/application-gateway/rewrite-http-headers-url#mutual-authentication-server-variables

HTTP request / Service bus - application/x-www-form-urlencoded not supported error

I've got a really simple Logic app:
HTTP request (works as end-point web hook for Slack)
Send request from Slack (URI) to Service Bus queue
I haven't made any changes in Logic App but Send message action suddenly started reporting this error:
Decoding as string is not supported for content envelope of type
'application/x-www-form-urlencoded'.
Send message is defined like that:
"Send_message": {
"inputs": {
"body": {
"Label": "#{triggerBody()}"
},
...
I see only difference in request outputs:
BEFORE
Headers
{
"Accept": "*/*",
"User-Agent": "Slackbot,1.0,(+https://api.slack.com/robots)",
"Content-Type": "application/x-www-form-urlencoded"
...
}
Body
{
"$content-type": "application/x-www-form-urlencoded",
"$content": "dG9r..."
}
NOW
Headers
{
"Accept": "*/*",
"User-Agent": "Slackbot,1.0,(+https://api.slack.com/robots)",
"Content-Type": "application/x-www-form-urlencoded"
...
}
Body
{
"$content-type": "application/x-www-form-urlencoded",
"$content": "dG9r...",
"$formdata": [
{
"key": "token",
"value": "..."
},
{
"key": "team_id",
"value": "..."
},
{
"key": "trigger_word",
"value": "!"
},
...
]
}
$formdata is now a part of the output of Request as JSON array consisting of all query parameters.
Does anyone have any ideas? I would greatly appreciate any help to make it work again.
Edit: West Europe fixed and working
Yes, in the effort to have native support for x-www-form-urlencoded data in the runtime there was a bug that was recently released. We are rolling back and patching now. Can you send me an email so we can target your region for a fix, and share a workaround? Apologies in advance - as a general rule we never want to ship anything that will break existing logic apps. In this case adding some new metadata around form-data no longer allowed people to stringify x-www-form-urlencoded data (which is what you are doing here).

Azure Logic Apps Cannot send HTTP request for wns/raw notification

I have a small logic app which is meant to fetch data from somewhere and store it on blob. I then would like to send the URL to all devices via push notification. I wish to send the URL as a raw notification, so on the app/background task, i can do some processiong.
The problem is when i use logic app to create a http POST request to send a notification, i get a 400 error. The same header with authentication and etc, with the payload and URL works fine on a POSTMAN or REST API CLIENT. THe following are the inputs and outputs. Please help. Brain dead already.
This is the input.
{
"uri": "https://xxoppoc.servicebus.windows.net/xxopPOC/messages/?api-version=2015-01",
"method": "POST",
"headers": {
"Authorization": "SharedAccessSignature sr=sb%3a%2f%2fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxt%2f&sig=qEnxxxxxxxxxxxx&skn=DefaultFullSharedAccessSignature",
"Content-Type": "application/octet-stream",
"ServiceBusNotification-Format": "windows",
"ServiceBusNotification-Tags": "MyTag",
"X-WNS-Type": "wns/raw"
},
"body": "Some Raw Information. Hello World"
}
This is the output:
{
"statusCode": 400,
"headers": {
"transfer-Encoding": "chunked",
"date": "Wed, 30 Mar 2016 14:10:41 GMT",
"server": "Microsoft-HTTPAPI/2.0"
},
"body": {
"$content-type": "application/xml; charset=utf-8",
"$content": "PEVycm9yPjxDb2RlPjQwMDwvQ29kZT48RGV0YWlsPlRoZSBjb250ZW50IHR5cGUgZm9yIGEgJ3ducy9yYXcnIG5vdGlmaWNhdGlvbiBtdXN0IGJlICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nLlRyYWNraW5nSWQ6NTNmNjhlMGItNDc1MC00ZDRkLWJiNTAtMzJjNTBmOGIyNDk1X0czLFRpbWVTdGFtcDozLzMwLzIwMTYgMjoxMDo0MSBQTTwvRGV0YWlsPjwvRXJyb3I+"
}
}
Let me mention again, I got the authentication correct as it works on Advanced REST Client on chrome and POSTMAN. The above logic app also works if i send a wns/toast notification with xml as its content-type. I however need it to be a wns/raw notification. Please help. Thank you
EDIT/PROGRESS
Thanks to MichaelB, We figured out that the content-type is being modified. I sent the request to a different URL to look at the header. The following was observed:
Content-Type: application/octet-stream; charset=utf-8
If I use the above Content-Type on POSTMAN. It actually fails as well. So this could be 1 step. Why is Azure Logic Apps adding charset-utf-8 to the end of my content type. Can I stop it?

Resources