'The type java.util.Optional is not a supported type for a multipart request

I have a facade filter service. Trying to route a REST call in one cluster into another cluster through the filter service.

@Filter({"/api/**", "/home/**"})
public class FacadeAPIFilter extends OncePerRequestHttpServerFilter {

    private final ProxyHttpClient client;

    FacadeAPIFilter(ProxyHttpClient client) {
        this.client = client;
    }

    @Override
    protected Publisher<MutableHttpResponse<?>> doFilterOnce(HttpRequest<?> request, ServerFilterChain chain) {
        try {
                MutableHttpRequest<?> mutatedRequest = mutateAPIRequest(request);
                newRequest.body(request.getBody());
                return Publishers.map(client.proxy(mutatedRequest), response -> response);
            }

        } catch (Exception x) {
            x.printStackTrace();
        }
        return chain.proceed(request);
    }

    public static MutableHttpRequest<?> mutateAPIRequest(HttpRequest<?> request) throws MalformedURLException, URISyntaxException {
        URL url = new URL(new cluster url);
        return request.mutate()
                .uri(b -> b
                        .scheme(url.getProtocol())
                        .host(url.getHost())
                )
                .headers(h -> h.remove("Host")).headers(h -> h.remove("host"));

    }
}

The REST implementations for "/api/", "/home/" are resides in different cluster with the controllers. There is no issue of the rest implementations.

Here the scenario is from cluster 1 we are trying to invoke these REST endpoints through FacadeAPIFilter routing mechanism. All the endpoints are working fine...except POST

We have a import call with adding zip file to rest end point... which inturn calls the FacadeAPIFilter for routing to the appropriate cluster.

Any solution for POST with multipart form data request routing through ProxyHttpClient in micronaut filter service.?

where we are getting these exception...

"An exception was thrown by io.micronaut.http.client.netty.DefaultHttpClient$$Lambda$1014/0x000000010131d440.operationComplete():\nio.micronaut.http.multipart.MultipartException: The type java.util.Optional is not a supported type for a multipart request body\n\tat io.micronaut.http.client.netty.DefaultHttpClient.buildMultipartRequest(DefaultHttpClient.java:2446)\n\tat io.micronaut.http.client.netty.DefaultHttpClient.buildNettyRequest(DefaultHttpClient.java:1529)\n\tat io.micronaut.http.client.netty.DefaultHttpClient.prepareRequest(DefaultHttpClient.java:2516)\n\tat io.micronaut.http.client.netty.DefaultHttpClient.streamRequestThroughChannel(DefaultHttpClient.java:1845)\n\tat io.micronaut.http.client.netty.DefaultHttpClient.lambda$null$49(DefaultHttpClient.java:2665)\n\tat io.micronaut.http.client.netty.DefaultHttpClient.lambda$addInstrumentedListener$52(DefaultHttpClient.java:2721)\n\tat io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)\n\tat io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:571)\n\tat io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:550)\n\tat io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491)\n\tat io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616)\n\tat io.netty.util.concurrent.DefaultPromise.setSuccess0(DefaultPromise.java:605)\n\tat io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:104)\n\tat io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:84)\n\tat io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:300)\n\ta



Solution 1:[1]

Not setting the body if the contentType is multipart_form_data... resolved the following update resolved the issue.

        String contentType = request.getHeaders().getContentType().isPresent() ? request.getHeaders().getContentType().get() : "";
        if( !contentType.contains(MediaType.MULTIPART_FORM_DATA)) {
            newRequest.body(request.getBody());
        }

        return Publishers.map(client.proxy(newRequest), response -> response);

Solution 2:[2]

You should never have to set the body just because the request was mutated

Also this line should be removed: Publishers.map(client.proxy(mutatedRequest), response -> response);

and replaced with just client.proxy(mutatedRequest)

Using Publishers.map will cause the reactor context to be lost and it serves no purpose in this case

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 sansrini
Solution 2 James Kleeh