Azure / azure-functions-java-worker

Java runtime and core types for Microsoft Azure Functions
MIT License
87 stars 54 forks source link

Http Requests with Transfer-Encoding: chunked report an empty body #781

Open Mrnikbobjeff opened 1 month ago

Mrnikbobjeff commented 1 month ago

Sending requests to a Java HttpTriggered function results in an empty body if transfer-encoding is set to chunked

Investigative information

Please provide the following:

Repro steps

Provide the steps required to reproduce the problem:

  1. Send a http request which does not contain content-length but uses a transfer-encoding: chunked style of sending data
  2. The function app fails to read the request body

Expected behavior

transfer-encoding: chunked works as expected

Actual behavior

The request body is empty

Known workarounds

provide the content-length client side by reading the entire request into memory. Not viable as a proxy service where we ourselves get chunked requests.

Related information

Provide any related information

package org.example.functions;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Stream;

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

/**
 * Azure Functions with HTTP Trigger.
 */
public class HttpTriggerJava {
    /**
     * This function listens at endpoint "/api/HttpTriggerJava". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/HttpTriggerJava
     * 2. curl {your host}/api/HttpTriggerJava?name=HTTP%20Query
     */
    @FunctionName("HttpTriggerJava")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.POST},
                    authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) throws Exception {
        context.getLogger().info("Java HTTP trigger processed a request.");
//
           return request.createResponseBuilder(HttpStatus.OK).body("Hello").build();
    }
}
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.Threading;
using System.Net.Http;
using System.Net;
using Microsoft.Azure.Functions.Worker;
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("http://localhost:50251/api/HttpTriggerJava") };

            using var request = new HttpRequestMessage()
            {
                Method = HttpMethod.Post
            };

            //request.Content = new StringContent(await (new StreamReader(pdfRequest.Payload)).ReadToEndAsync());
            request.Content = new StreamContent(req.Body);
            request.Content.Headers.Add("Content-Type", "application/octet-stream");
            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());
        }
    }
}