azure-functions-java-worker icon indicating copy to clipboard operation
azure-functions-java-worker copied to clipboard

Java azure function HTTP trigger body is reformatted

Open IISamwiseII opened this issue 5 years ago • 8 comments

When a HTTP trigger is used the body of the request is reformatted when you use the getBody() method.

There does not seem to be an method to get the raw body either. (which is currently available in the javascript azure functions)

This is causing me an issue with that I am trying to do currently as the format of the message is important to maintain the format it was parsed in.

if the content-type header is not set to application/json it seems to keep the same format as sent in.

Is this a bug or is there any work arounds for this issue i am having?

Repro steps

To reproduce this issue make sure the content-type of the request header is application/json and simply send a post request with a json in any irregular format such as below.

{"itemA":"valueA",
"itemB":"valueB"}

Expected behaviour

The expected behaviour is that there should be a way to get the raw body of the post request. ie read the body of the above example as followed

{"itemA":"valueA",
"itemB":"valueB"}

Actual behavior

There is only access to a formatted json body as shown below.

{
    "itemA":"valueA",
    "itemB":"valueB"
}

Related information

I was advised that java functions allows the use of byte arrays instead of strings for the request body and this would potentially work but this gave me the exception below

System.Private.CoreLib: Exception while executing function: Functions.usingbyte. System.Private.CoreLib: Result: Failure
Exception: ClassCastException: Cannot convert com.microsoft.azure.functions.worker.binding.RpcHttpRequestDataSource@6dad01aato type com.microsoft.azure.functions.HttpRequestMessage<java.util.Optional<byte[]>>
  • Programming language used: Java

below is an example source of both the normal String request and a byte array request which has the other error.

you will see that the log will reformat the message from the getBody request.

Source
package com.function;

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

public class Function {

    @FunctionName("usingstring")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        
		context.getLogger().info("Java HTTP trigger processed a request.");
		
        String recievedBody = request.getBody().orElse("");
        context.getLogger().info(recievedBody);

        return request.createResponseBuilder(HttpStatus.OK).body(recievedBody).build();

    }

    @FunctionName("usingbyte")
    public HttpResponseMessage httpHandler(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<byte[]>> request,
            final ExecutionContext context) {
				
        context.getLogger().info("Java HTTP trigger processed a request.");
        
		byte[] emptyByteArray = new byte[0];
        byte[] recievedBody = request.getBody().orElse(emptyByteArray);
        context.getLogger().info(recievedBody.toString());
        
		return request.createResponseBuilder(HttpStatus.OK).body(request.getBody().orElse(emptyByteArray)).build();
    }
}

IISamwiseII avatar May 17 '19 14:05 IISamwiseII

cc @maiqbal11 This is similar issue as https://github.com/Azure/azure-functions-python-worker/issues/380.

To achieve this in a non breaking way, HttpRequestMessage.java needs to expose getRawBody helper similar to javascript

pragnagopa avatar May 20 '19 16:05 pragnagopa

cc @anirudhgarg @kulkarnisonia16

pragnagopa avatar Jul 01 '19 16:07 pragnagopa

I can work with @amamounelsayed to achieve the functionality we had added for Java. Just going to mention some things to note top of mind. Since Python is in preview, we were able to change the default behavior for the body to be raw bytes. Would this be a concern for Java since it is already in GA? Would the raw bytes be exposed as an option to the user rather than the default?

maiqbal11 avatar Jul 01 '19 17:07 maiqbal11

Thanks @maiqbal11 ! Since this is a new feature, We should just expose rawBytes similar to python.

pragnagopa avatar Jul 01 '19 17:07 pragnagopa

cc @yojagad PR: https://github.com/Azure/azure-functions-host/pull/4660/files addresses this issue. @yojagad - Please verify if following function works with your changes

@FunctionName("getBytes")
  public byte[] GetHttpRequestBodyAsBytes(
      @HttpTrigger(name = "req", methods = {POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<byte[]>> request,
      final ExecutionContext context) {
    ...
  }

pragnagopa avatar Jul 23 '19 13:07 pragnagopa

Are there any news on this?

crgarcia12 avatar Jun 11 '20 06:06 crgarcia12

I still don't have a way to get the raw body of a request, and it is actively preventing me from making endpoints that can handle either JSON or multipart form data. Is there anything I can do to help? What needs to be done so that this feature is available in the cloud as well?

A simple way to get around the issue for now would be if RpcStringDataSource and RpcJsonDataSource had the additional conversion operations as follows:

JSON_DATA_OPERATIONS.addOperation(byte[].class, String::getBytes);

However, this still changes the charset used for the original data to be that of the processing machine, though I can accept that.

I have made the two lines of changes in theory on my machine, but I can't get the repo to compile at all to begin with.

UnknownJoe796 avatar Jul 14 '22 19:07 UnknownJoe796

Hi, I am having the same problem here.

As the original raw data is processed in some way, I am almost unable to verify its signature, a Use Case I require for my Stripe webhook. I do require a raw data body.

Furthermore it is not possible to use dataType "binary" (this was dicussed in https://github.com/microsoft/azure-maven-plugins/issues/1351) , as there is no chance to acknowledge/accept any mime types and not just e.g. application/octet-stream as binary content. --> i do not have control over the access header.

@UnknownJoe796 did you maybe manage to build some kind of workaround?

Here an example why this might be an issue (from StripeDoku)

Warning Stripe requires the raw body of the request to perform signature verification. If you’re using a framework, make sure it doesn’t manipulate the raw body. Any manipulation to the raw body of the request causes the verification to fail.

affom1 avatar Mar 31 '24 20:03 affom1