micronaut-graphql icon indicating copy to clipboard operation
micronaut-graphql copied to clipboard

Add support for GraphQL multipart request

Open srekapalli opened this issue 4 years ago • 9 comments

Trying to make GraphQL multipart request work as per this specification https://github.com/jaydenseric/graphql-multipart-request-spec , but receiving error when I send a multipart request. Is Multipart request supported now in Micronaut/GraphQL extension ?

Error: /string - Failed to convert argument [string] for value [null] due to: Cannot deserialize instance of java.lang.String out of START_OBJECT token at [Source: UNKNOWN; line: -1, column: -1]] using codec: io.micronaut.jackson.codec.JsonMediaTypeCodec@439d545c

---- Logs ----

21:52:10.675 [nioEventLoopGroup-1-8] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matching route POST - /graphql
21:52:10.675 [nioEventLoopGroup-1-8] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matched route POST - /graphql to controller class io.micronaut.configuration.graphql.GraphQLController
21:52:10.676 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Resolved existing bean [io.micronaut.http.server.netty.FormDataHttpContentSubscriberFactory@5eeaaf88] for type [interface io.micronaut.http.server.netty.HttpContentSubscriberFactory] and qualifier [Content-Type: multipart/form-data;boundary=------------------------e67f840163e3fadc]
21:52:10.678 [nioEventLoopGroup-1-8] DEBUG i.m.c.beans.DefaultBeanIntrospector - No BeanIntrospection found for bean type: class java.lang.String
21:52:10.678 [nioEventLoopGroup-1-8] DEBUG io.micronaut.core.reflect.ClassUtils - Cannot instantiate type [class java.lang.String] without reflection. Attempting reflective instantiation
21:52:10.678 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Resolved existing bean [io.micronaut.jackson.bind.JacksonBeanPropertyBinder@69626e28] for type [interface io.micronaut.core.bind.BeanPropertyBinder] and qualifier [null]
21:52:10.678 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Registering singleton bean io.micronaut.http.server.exceptions.ConversionErrorHandler@246a6496 for type [<ConversionErrorException,Object> io.micronaut.http.server.exceptions.ExceptionHandler] using bean key <ConversionErrorException,Object> io.micronaut.http.server.exceptions.ConversionErrorHandler
21:52:10.678 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Registering singleton bean io.micronaut.http.server.exceptions.ConversionErrorHandler@246a6496 for type [<ConversionErrorException,Object> io.micronaut.http.server.exceptions.ExceptionHandler] using bean key <ConversionErrorException,Object> io.micronaut.http.server.exceptions.ConversionErrorHandler
21:52:10.679 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Registering singleton bean io.micronaut.http.server.exceptions.ConversionErrorHandler@246a6496 for type [<ConversionErrorException,Object> io.micronaut.http.server.exceptions.ExceptionHandler] using bean key <ConversionErrorException,Object> io.micronaut.http.server.exceptions.ConversionErrorHandler
21:52:10.679 [nioEventLoopGroup-1-8] DEBUG i.m.context.DefaultBeanContext - Resolved existing bean [io.micronaut.http.server.exceptions.ConversionErrorHandler@246a6496] for type [interface io.micronaut.http.server.exceptions.ExceptionHandler] and qualifier [<ConversionErrorException,Object>]
21:52:10.679 [nioEventLoopGroup-1-8] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Encoding emitted response object [ /string - Failed to convert argument [string] for value [null] due to: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
 at [Source: UNKNOWN; line: -1, column: -1]] using codec: io.micronaut.jackson.codec.JsonMediaTypeCodec@439d545c

srekapalli avatar Jul 29 '19 04:07 srekapalli

Hi @srekapalli, multipart requests are indeed not (yet) supported. Currently only the Serving over HTTP specs are implemented.

I will look into this and consider supporting the multipart spec. Do you know if other graphql implementations implement this https://github.com/jaydenseric/graphql-multipart-request-spec spec?

marceloverdijk avatar Jul 29 '19 07:07 marceloverdijk

@marceloverdijk - It looks like GraphQL-Java-Kickstart added support for that spec: https://github.com/graphql-java-kickstart/graphql-java-servlet/pull/102

sflahave avatar Jul 29 '19 11:07 sflahave

Correct graphql-java-kickstart/graphql-java-servlet does indeed support it. I was wondering if other implementations like graphqljs or the express module also support it or not, to see if that spec is widely adopted.

marceloverdijk avatar Jul 29 '19 12:07 marceloverdijk

After initial investigation Micronaut currently does not support retrieving the parts of multipart request. At least not in the sense needed to implement the https://github.com/jaydenseric/graphql-multipart-request-spec.

Micronaut does support retrieving parts, but only if the part names are known upfront, which we don't know for https://github.com/jaydenseric/graphql-multipart-request-spec.

https://github.com/micronaut-projects/micronaut-core/issues/1957 is created to provide a way to retrieve the parts. Until then https://github.com/jaydenseric/graphql-multipart-request-spec cannot be implemented unfortunately.

marceloverdijk avatar Jul 30 '19 19:07 marceloverdijk

Support for retrieving multiparts is scheduled for Micronaut Core 1.3.0 (see https://github.com/micronaut-projects/micronaut-core/issues/1957). We have to wait for that before we can implement https://github.com/jaydenseric/graphql-multipart-request-spec in micronaut-graphql.

marceloverdijk avatar Aug 02 '19 08:08 marceloverdijk

Support for retrieving multiparts is now added to Micronaut Core and will be part of Micronaut 1.3.0.

However, there is another Micronaut Core issue pending to implement this feature in Micronaut GraphqL: https://github.com/micronaut-projects/micronaut-core/issues/1971 as we currently cannot distinguish the routes.

marceloverdijk avatar Aug 16 '19 06:08 marceloverdijk

Note https://github.com/micronaut-projects/micronaut-core/issues/1971 has been released as part of Micronaut Core 1.2.1. As soon as we get closer to a Micronaut Core 1.3.0 release I will start implementing the multipart support in the Micronaut GraphQL module as all building blocks are available now.

marceloverdijk avatar Sep 11 '19 11:09 marceloverdijk

Putting this on hold to consider whether to add non-official GraphQL spec related functionality or not.

marceloverdijk avatar Jan 17 '20 06:01 marceloverdijk

Hi there! For those looking for a solution, a very basic implementation of the spec can be found here - https://gist.github.com/artipop/725c9a574c3cf0dc7b66e2061c5f4eca. You can add an Upload scalar to the RuntimeWiring:

RuntimeWiring runtimeWiring = RuntimeWiring.newRuntimeWiring()
        .scalar(CompletedFileUploadScalar.UPLOAD_SCALAR)
        ...
        .build();

and then get CompletedFileUpload in your DataFetcher like this:

CompletedFileUpload file = environment.getArgument("file");

artipop avatar May 12 '23 14:05 artipop