I have created an Azure Function which connects to an API. This is the code:
public static async Task<HttpResponse> RunProduction(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
_log = log;
API_URL = #"{API_URL}";
BEARER_TOKEN = Environment.GetEnvironmentVariable("{ENV_NAME}");
if (BEARER_TOKEN.Equals("")) throw new Exception("Bearer token could not be retrieved");
var response = req.HttpContext.Response;
response.Clear();
response.StatusCode = 200;
response.ContentType = "text/plain";
//This is where the API will be called.
//The method is not changing anything in the response (yet)
response = await ExecuteMethods(req, response);
return response;
}
I am testing the Function locally with Postman. In Postman, I have the following headers:
Every time I test the Function, I receive a 406 Not Acceptable. This even happens when I comment the line where the method ExecuteMethods() is being called.
Any ideas how I can get rid of the 406-error and get my 200-statuscode again?
Related
Is there a way to send a payload that is received on the service buss queue to be sent to an API in APIM using function app? I'm planning to do this on the ServiceBusTrigger function. I already have the message/payload on the QueueMessage, I just need to directly call the API and send the value of the QueueMessage to the API
public static void Run([ServiceBusTrigger("sbq-messagequery", Connection = "ServiceBusConnection")]
QueueMessage queueItem, ILogger log)
{
dynamic data = JsonConvert.SerializeObject(queueItem);
log.LogInformation($"C# ServiceBus queue trigger function processed message: {data}");
log.LogWarning($"Id = {queueItem.Payload}");
}
You have to do an HttpRequest in your Trigger method.
Please find advice for using the HttpClient in Azure Functions in the documentation
[FunctionName("MyHttpTrigger")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
var response = await _client.GetAsync("https://microsoft.com");
var message = _service.GetMessage();
return new OkObjectResult("Response from function with injected dependencies.");
}
In your case it might be a POST request:
public static void Run([ServiceBusTrigger("sbq-messagequery", Connection = "ServiceBusConnection")] QueueMessage queueItem, ILogger log)
{
dynamic data = JsonConvert.SerializeObject(queueItem);
log.LogInformation($"C# ServiceBus queue trigger function processed message: {data}");
log.LogWarning($"Id = {queueItem.Payload}");
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "https://yourtarget/api/lorem");
var json = JsonConvert.SerializeObject(queueItem.Payload);
requestMessage.Content = new StringContent(json, Encoding.UTF8, "application/json");
var response = _client.SendAsync(httpRequestMessage).Result;
}
I have created and HTTP Triggered Azure Function (v2) using .NET Core with the hopes that I can execute the function while passing in some info in the request body and then have the function return/download a file in the browser. Unfortunately I am struggling to get this working.
Below is a snippet of Code
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
string csv;
//Do some stuff to create a csv
byte[] filebytes = Encoding.UTF8.GetBytes(csv);
req.HttpContext.Response.Headers.Add("content-disposition", "attachment;filename=Export.csv");
req.HttpContext.Response.ContentType = "application/octet-stream";
return (ActionResult)new OkObjectResult(filebytes);
}
When I do a post using Postman the request is accepted but the response is 406 "unacceptable" and the output in the log states
"Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector[1]
No output formatter was found for content type 'application/octet-stream' to write the response."
I've tried multiple content types including text/plain and text/csv, all give the same response about output formatting.
If I remove or comment out the ContentType the request processes and returns a 200 but the filebytes are returned in the response body instead of being downloaded in the browser.
You'll need a FileContentResult for this:
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
string csv;
//Do some stuff to create a csv
byte[] filebytes = Encoding.UTF8.GetBytes(csv);
return new FileContentResult(filebytes, "application/octet-stream") {
FileDownloadName = "Export.csv"
};
}
While the comments correctly point out that the ideal solution is to kick off processing in the HTTP function asynchronously, return a 202 Accepted response, save the result to blob storage, have the client wait for processing to complete before starting the blob download and then delete the blob once it's been downloaded, current Azure Functions pricing is only $0.000016/GB-s so you may find that to be unnecessarily complicated unless you have quite high traffic.
I have an Azure Function that sits behind a proxy. If an update occurs to the objects that get returned we want to deprecate the Function after a period of time. I'm trying to create a response with the expected content from an HTTP Header by using what was provided in this solution.
Warning: 299 - "Deprecated API"
I try to append the Azure Function like so:
[FunctionName("MyAPI")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function,
"post", Route = null)]
HttpRequestMessage req,
TraceWriter log)
{
object response = await someService.Get();
if (settingsService.IsDeprecated)
{
var httpresponse = req.CreateResponse(HttpStatusCode.OK, response, "application/json");
httpresponse.Content.Headers.Add("Warning", "299 - Deprecated API");
return httpresponse;
}
return req.CreateResponse(HttpStatusCode.OK, response, "application/json");
}
I get the Exception
Exception while executing function: MyAPI -> Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
How do I append the "Deprecated" status warning in my API Http Response?
Change your line to
httpresponse.Headers.Add("Warning", "299 - \"Deprecated API\"");
The quotes seem to be important there to adhere to the format requirement.
I have the problem, that I can't retrieve the body of a POST statement of a JSON Object. Here is the function, which is called when executing the http-Request:
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "HttpTriggerCSharp/name/{name}")]HttpRequestMessage req, string name, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
string output = JsonConvert.SerializeObject(req.Content.ToString());
// Fetching the name from the path parameter in the request URL
return req.CreateResponse(HttpStatusCode.OK, output);
}
Im executing the POST with Postman and the following URL: http://localhost:7071/api/HttpTriggerCSharp/name/test
In the Header I wrote "Content-Type: application/json" and the Body looks like this:
{
"Benutzer":"Nenad",
"Passwort":"test"
}
My result is this: "\"System.Net.Http.StreamContent\""
Thank you for your help!
Thanks for the answers guys,
i found now an other solution with the help of a friend, this is the following:
public static async System.Threading.Tasks.Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "HttpTriggerCSharp/name/{name}")]HttpRequestMessage req, string name, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
dynamic dataArray = await req.Content.ReadAsAsync<object>();
string output = dataArray.ToString();
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<Benutzer>(output);
// Fetching the name from the path parameter in the request URL
return req.CreateResponse(HttpStatusCode.OK, data);
}
Content is an instance of HttpContent class (as you can see in your output). So you have to use an appropriate method to get the string.
If have a simple HTTP triggered function in C# which just doesn't return the result:
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
string jobId = req.Headers.GetValues("scheduler-jobid").FirstOrDefault();
string executionTime = req.Headers.GetValues("scheduler-expected-execution-time").FirstOrDefault();
return req.CreateResponse(HttpStatusCode.OK,new {
JobId = jobId,
ExecutionTime = executionTime}
);
}
I checked with POSTMAN that HTTP headers are set correctly but just get a 200 OK without a response body.
In hindsight the solution is obvious:
I had to define a HTTP Response output and without changing the code above the Azure Functions runtime automatically wires in the req.CreateResponse.