When trying to use the request body stream as content for another HttpRequest, the dotnet-isolated function app seems to have issues with certain backend servers which see the request body as empty. The exact same http call in a in-process .NET 8 function works. Materializing the request body and using StringContent for the HttpRequest Content property eliminates this issue.
in-process:
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net;
using System.Threading;
namespace FunctionApp2
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<IActionResult> GeneratePdfAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "documents/{tenant}/{engine}/{template}")] HttpRequest body,
string engine,
string tenant,
string template,
CancellationToken ct)
{
using var client = new HttpClient() { BaseAddress = new Uri("https://my-backend-func.azurewebsites.net/api/") };
using var request = new HttpRequestMessage(HttpMethod.Post, new Uri($"pdf/{Uri.EscapeDataString(tenant)}/{Uri.EscapeDataString(template)}", UriKind.Relative));
//request.Content = new StringContent(await (new StreamReader(pdfRequest.Payload)).ReadToEndAsync());
request.Content = new StreamContent(body.Body);
using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, ct).ConfigureAwait(false);
if (response.StatusCode == HttpStatusCode.OK)
return new FileStreamResult(await response.Content.ReadAsStreamAsync(ct), "application/pdf");
else
return new BadRequestObjectResult(await response.Content.ReadAsStringAsync());
}
}
}
dotnet-isolated:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using System.Threading;
using System.Net.Http;
using System.Net;
using Microsoft.Azure.Functions.Worker;
using System.IO;
using Microsoft.Azure.Functions.Worker.Http;
namespace FunctionApp1
{
public class Function1
{
[Function("Function1")]
public async Task<IActionResult> GeneratePdfAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "documents/{tenant}/{engine}/{template}")] HttpRequestData req,
string engine,
string tenant,
string template,
CancellationToken ct)
{
using var client = new HttpClient() { BaseAddress = new Uri("https://my-backend-func.azurewebsites.net/api/") };
using var request = new HttpRequestMessage(HttpMethod.Post, new Uri($"pdf/{Uri.EscapeDataString(tenant)}/{Uri.EscapeDataString(template)}", UriKind.Relative));
//request.Content = new StringContent(await (new StreamReader(pdfRequest.Payload)).ReadToEndAsync());
request.Content = new StreamContent(req.Body);
using var response = await client.SendAsync(request, ct);
if (response.StatusCode == HttpStatusCode.OK)
return new FileStreamResult(await response.Content.ReadAsStreamAsync(ct), "application/pdf");
else
return new BadRequestObjectResult(await response.Content.ReadAsStringAsync());
}
}
}
I expected the behaviour of this simple POC to match between the different host runtimes. I have not found anything online explaining this behaviour.
Niklas Schilli is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.