Azure / azure-functions-host

The host/runtime that powers Azure Functions
https://functions.azure.com
MIT License
1.95k stars 442 forks source link

Azure Functions v3 HttpTrigger: request body is empty #5405

Open myarotskaya opened 4 years ago

myarotskaya commented 4 years ago

HttpTrigger works incorrectly in the following conditions:

Investigative information

I've created the repository to demonstrate this issue. The source code of this repository is deployed to the Function App.

Repro steps

Expected behavior

Request's body is returned in the response.

Actual behavior

Request's body is not returned in the response.

Known workarounds

Do not send Content-Type: application/json header or send any other value in the Content-Type header.

Related information

The same code works correct in Azure Functions v2 on netcoreapp2.1 with Microsoft.NET.Sdk.Functions version 1.0.29 and in ASP.NET Core 3.1 Web Application.

There are two endpoints to check it (see the repository):

In both cases the request body will be returned in the response (I didn't deploy it to any Function App but it's reproducible locally as well).

myarotskaya commented 4 years ago

Another workaround @fabiocav mentioned: set FUNCTIONS_V2_COMPATIBILITY_MODE to true in the App Settings.

myarotskaya commented 4 years ago

Hello @pragnagopa, could you please confirm that it's a valid issue and if so, is it planned to be fixed on the Azure Functions side? Is there any ETA?

andersekenstierna commented 4 years ago

Hi. Working on a customer project and upgraded to version 3.1. I can verify that this is still an issue that needs to be resolved. Setting FUNCTIONS_V2_COMPATIBILITY_MODE to true works as a workaround though.

pragnagopa commented 4 years ago

Please continue using FUNCTIONS_V2_COMPATIBILITY_MODE. We will update this issue with further details. No ETA yet.

bstoked commented 4 years ago

Any word on this? Upgrading to v3 broke our microservices.

JohnPelaschier commented 4 years ago

Having this issue and setting FUNCTIONS_V2_COMPATIBILITY_MODE does not help for me. Runs fine locally but nothing works when deployed to Azure. Am I missing something?

TMUNYU commented 4 years ago

FUNCTIONS_V2_COMPATIBILITY_MODE is not doing the trick for me. You guys need to put a GIANT warning on the functions overview about this. I wasted so much time going in circles about this because I was not aware of this known issue. I am sure others have wasted time too. It is good to be more transparent about non obvious bugs like this.

TMUNYU commented 4 years ago

Found another work around for others. In my case I was using GET on the function. If you use POST instead the body will come in correctly. I am not using the FUNCTIONS_V2_COMPATIBILITY_MODE.

DanielTongAwesome commented 4 years ago

Problem still exist when I am using: Azure Functions Core Tools (3.0.2798 Commit hash: d9d99872a51c04b1c2783198b1ee1104da6b064f)

but after I tried it couple times, the issue suddenly disappear ... and get_json() returns json data ... this is really strange

if u are using postman:

  1. in body, header enter content-type: application/json
  2. in body type your json msg
  3. use POST and include a body

image image

MateRadz commented 4 years ago

Any update on this issue? Setting FUNCTIONS_V2_COMPATIBILITY_MODE to true does not work. What is frustrating is that it works when invoked from the Test/Run form in the portal, but does not work via Postman.

anthonychu commented 4 years ago

I was able to repro this with @myarotskaya's repo. Looks like the problem has to do with model binding reading the body stream. By the time the function executes, there's nothing left to read. @fabiocav @pragnagopa Is this the desired behavior for v3? Feels like this is a bug if there's no other way to get access to the request body in this scenario.

@bstoked @TMUNYU @DanielTongAwesome @MateRadz Can you confirm that you are all experiencing the same issue? The fact that the compatibility mode doesn't solve it for everyone might indicate a different problem. Please share a repro if possible.

MateRadz commented 4 years ago

I do not knot your internal schedule but for me it is a new issue as my function without any change in code worked for several days until the last ok at 25.08.2020, 13:15:05.009. The next call at 25.08.2020, 19:16:20.619 (UTC) was the first not working an it is like this till today. So for me it may have been related to your internal updates, if there where any. As mentioned when called directly from Test/Run on Azure Portal it works.

mike1880 commented 4 years ago

Found another work around for others. In my case I was using GET on the function. If you use POST instead the body will come in correctly. I am not using the FUNCTIONS_V2_COMPATIBILITY_MODE.

That's not true for me at least; the first time I tripped over this issue it was with a POST message

mdddev commented 4 years ago

I stumbled on this while investigating why the request body received from a (deployed to azure) function app is empty. Contrary to the above, I don't see this behaviour running locally. Even with content-type set to application/json I can successfully pass along a non-empty body.

PS C:\Users\me\source\project> func -v 3.0.2931

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.7" />
  </ItemGroup>
</Project>
namespace my.namespace
{
    public static class Notify
    {
        [FunctionName(nameof(Notify))]
        public static async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "notify")] HttpRequest req,
        [Queue("name", Connection = "connName")] IAsyncCollector<string> myDestinationQueue,
        ILogger log)
        {
                using var r = new StreamReader(req.Body, Encoding.UTF8);
                var bodyStr = await r.ReadToEndAsync();
                await myDestinationQueue.AddAsync(bodyStr);
                // do stuff...
                return new OkObjectResult(1);
        }
    }
}
MateRadz commented 4 years ago

I do not knot your internal schedule but for me it is a new issue as my function without any change in code worked for several days until the last ok at 25.08.2020, 13:15:05.009. The next call at 25.08.2020, 19:16:20.619 (UTC) was the first not working an it is like this till today. So for me it may have been related to your internal updates, if there where any. As mentioned when called directly from Test/Run on Azure Portal it works.

The simplest workaround which worked for me was redeployment of function with MS provided example http trigger function. After that worked I copied my source to the function and after deploying again it started to work.

prabh-62 commented 4 years ago

I tried to reproduce the issue with a new func project however I couldn't

System

Steps

prabh-62 commented 4 years ago

@anthonychu The issue with @myarotskaya's git repo is the order of parameters

myarotskaya_issue

Once, the order of parameters is fixed, the request body comes through

myarotskaya_issue_fixed
prabh-62 commented 4 years ago

Created https://github.com/Azure/azure-functions-host/issues/6780

mike1880 commented 4 years ago

I tried to reproduce the issue with a new func project however I couldn't

I can confirm this is now working for me with Microsoft.NET.Sdk.Functions 3.0.9, both in local emulator and in Azure itself, and with Get as well as Post.

siamaksh1367 commented 3 years ago

Use Https instead of http with the default setup of an http trigger azure function , that worked for me

KenticoDevTrev commented 3 years ago

Ultimately i had to switch to POST and use in function Model Binding, and NOT rely on parsing the request body. It seems no matter how hard I try, the body is often empty when the azure function is 'waking up' (first hit on a cold function), but on subsequent hits it is valid and works.

FUNCTIONS_V2_COMPATIBILITY_MODE to true didn't do me any good.

This is my new start:

[FunctionName("GetComics")]
        [FixedDelayRetry(5, "00:00:02")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]
            GetComicsRequest Request,
            ILogger log
            )
        {
        ...
        var Response = new ComicResponse()
                {
                    Date = (Comics.Count > 0 ? Comics[0].Date : Request.Date != DateTimeHelper.ZERO_TIME ? Request.Date : DateTime.Now),
                    Comics = Comics
                };
                return new JsonResult(Response);
        }
cbailiss commented 1 year ago

I have also been suffering with the issue of an empty body with a runtime v4 app based on C# .NET 6 LTS.

I have a working set of code that has run fine in production for years (earlier version of the runtime). After moving it to .NET 6 LTS and runtime v4, the following code at the start of the function definition was not returning the request body:

                string sRequestBody = null;
                if (oRequest.Body != null)
                {
                    using (StreamReader oReader = new StreamReader(oRequest.Body))
                    {
                        sRequestBody = await oReader.ReadToEndAsync();
                    }
                }

The function was originally declared as:

        [FunctionName("TestPost")]
        public static async Task<IActionResult> TestPost(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = TrainDataHttpRoutes.Test)]
            ExecutionContext context, HttpRequest oRequest, ILogger oLog)

What fixed it was removing the ExecutionContext parameter:

        [FunctionName("TestPost")]
        public static async Task<IActionResult> TestPost(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = TrainDataHttpRoutes.Test)]
            HttpRequest oRequest, ILogger oLog)

Just posting here in case helps others as this caused me a lot of frustration to figure out.

cbailiss commented 1 year ago

I have now suffered a recurrence of this issue. The above Azure Function has been running fine for the last 3 weeks has now suddenly stopped working with the issue again being an empty body. I've made no changes/done no deployments since 3 weeks ago. What was working yesterday has suddenly stopped working today with no change/intervention from me. The exact same test case (same request) that worked a week ago is not working today. This bug in Azure Functions is very frustrating.

bsmithQSC commented 1 year ago

Can anyone confirm if this has been resolved yet? On v4 and having the same issue.

tslavik commented 11 months ago

Can anyone confirm if this has been resolved yet? On v4 and having the same issue.

I do not know your language, but in typescript this is working for me: await request.json() where request is HttpRequest class.

dalee-bis commented 10 months ago

For others running into this issue, I found that switching to HttpRequestData allowed me to access the request body without needing to change any other code.

Perhaps related to this note in the payload section documentation on .NET Isolated?

Type Description
HttpRequest Use of this type requires that the app is configured with ASP.NET Core integration in .NET Isolated.
This gives you full access to the request object and overall HttpContext.
HttpRequestData A projection of the request object.
Garran-Workspace commented 7 months ago

Good day, I am getting an intermittent empty body from C# .NET 8 Http trigger Azure Function

I have also posted the issue on stackoverflow.

I am encountering an intermittent issue when calling a POST method hosted on Azure Functions using C# .NET 8 dotnet-isolated http trigger. The request body appears to be empty approximately 40% to 60% of the time without async and with async it is around 10%, and I am uncertain about the cause.

I have developed a basic function to serve as a mock API. Its sole purpose is to return an HTTP status code and a JSON object. In all cases, when I call the function, I receive a 200 response. However, in some cases, the response does not include a body.

Here is a code example with async:

[Function("TokenOk")]
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "TokenOk")] HttpRequest req)
{
    _logger.LogInformation($"Executing TokenOk function.");

    var json = new
    {
        AccessToken = "eyJhbGciOiJSUzI1....",
        ExpiryInSeconds = 3600,
        IssuedAtUTC = "2024-03-25T13:42:14.6599966Z"
    };

    // When I increase the delay to 100, to 1000, the empty body ratio gets less
    await Task.Delay(10);

    return new OkObjectResult(json);
}

Here is a code example without async:

[Function("TokenOk")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "TokenOk")] HttpRequest req)
{
    _logger.LogInformation($"Executing TokenOk function.");

    var json = new
    {
        AccessToken = "eyJhbGciOiJSUzI1....",
        ExpiryInSeconds = 3600,
        IssuedAtUTC = "2024-03-25T13:42:14.6599966Z"
    };

    return new OkObjectResult(json);
}

To investigate further, I have created a small console application to hit the endpoint multiple times and check for the presence of a response body:

Data in Response 710
Data in Response 711
Data in Response 712
Data in Response 713
Response 714 is empty
Data in Response 715
Response 716 is empty
Data in Response 717
Data in Response 718
Data in Response 719
Data in Response 720
Response 721 is empty
Response 722 is empty
Data in Response 723
Data in Response 724
Data in Response 725
Data in Response 726
Data in Response 727
Data in Response 728
Data in Response 729
Data in Response 730
Data in Response 731

Here is an example of the environment variables used in the Azure Function:

[
  {
    "name": "APPLICATIONINSIGHTS_CONNECTION_STRING",
    "value": "InstrumentationKey=...",
    "slotSetting": false
  },
  {
    "name": "AzureWebJobsStorage",
    "value": "DefaultEndpointsProtocol=http..",
    "slotSetting": false
  },
  {
    "name": "FUNCTIONS_EXTENSION_VERSION",
    "value": "~4",
    "slotSetting": false
  },
  {
    "name": "FUNCTIONS_WORKER_RUNTIME",
    "value": "dotnet-isolated",
    "slotSetting": false
  },
  {
    "name": "WEBSITE_ENABLE_SYNC_UPDATE_SITE",
    "value": "true",
    "slotSetting": false
  },
  {
    "name": "WEBSITE_RUN_FROM_PACKAGE",
    "value": "1",
    "slotSetting": false
  },
  {
    "name": "WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED",
    "value": "1",
    "slotSetting": false
  },
  {
    "name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
    "value": "true",
    "slotSetting": false
  }
]

I tried switching IActionResult with HttpResponseData, but that didn't help. I attempted changing HttpResponseData to async. I even deleted the Azure Function and recreated it, but no luck. I also tried recreating the function locally and then deploying it. This issue only occurs once it's deployed to Azure; it works perfectly locally. I have let the console app that calls the post method run for 1000 times and I still get some with an empty body.

Thank you in advance.