GoogleCloudPlatform / functions-framework-java

FaaS (Function as a service) framework for writing portable Java functions
Apache License 2.0
131 stars 63 forks source link

com.google.cloud.functions.HttpRequest instance does not support form-data with more than 1 file on the same field #127

Open elgsylvain85 opened 2 years ago

elgsylvain85 commented 2 years ago

I am creating a gcloud http function which must receive a "form-data" form with a "medias" field which can contain up to 3 files, here is the basic code:

Gcloud Java function :

package functions;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import java.io.IOException;

public class HelloWorld implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException {
    var parts = request.getParts();

    parts.forEach(
            (e1, e2) -> {
                System.out.println(e1);
                System.out.println(e2.getFileName().get());
            });

  }
}

My simple request :

curl --location --request POST 'http://localhost:8080/' \
--form 'medias=@"/file1.jpeg"' \
--form 'medias=@"/file2.jpeg"'

Oddly, "request.getParts();" returns a "Map<String, HttpPart>" and therefore I don't see how to retrieve multiple files of the same submitted parameter. In debugging, I get a nice "java.lang.IllegalStateException: Duplicate key medias (attempted merging values com.google.cloud.functions.invoker.http.HttpRequestImpl$HttpPartImpl@49e848cf and com.google.cloud.functions.invoker.http .HttpRequestImpl$HttpPartImpl@6d5d7015)"

I can see that "getQueryParameters()" return correctly "Map<String, List>" and not "Map<String, String>" because a parameter name can have many value but why "getParts()" return "Map<String, HttpPart>" and not "Map<String, List>" ?

maven :

<dependency>
    <groupId>com.google.cloud.functions</groupId>
    <artifactId>functions-framework-api</artifactId>
    <version>1.0.4</version>
    <scope>provided</scope>
</dependency>
HKWinterhalter commented 10 months ago

Hi @elgsylvain85, is this still a concern for you?

I follow your point - it does appear that the implementation of getParts chose to return Map<String, HttpPart>. This does fulfill the Collection interface, but you're correct that this doesn't support duplicate field names / keys. I also noticed that RFC2388 says that field names should be unique, but I believe in practice forms often have multiple values mapped to one name (e.g. radio buttons).