All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.mike10004.vhs.bmp.NettyMultipartFormDataParser Maven / Gradle / Ivy

There is a newer version: 0.32
Show newest version
package io.github.mike10004.vhs.bmp;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.io.ByteSource;
import com.google.common.net.HttpHeaders;
import com.google.common.net.MediaType;
import io.github.mike10004.vhs.harbridge.ContentDisposition;
import io.github.mike10004.vhs.harbridge.FormDataPart;
import io.github.mike10004.vhs.harbridge.MultipartFormDataParser;
import io.github.mike10004.vhs.harbridge.TypedContent;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.HttpData;
import io.netty.handler.codec.http.multipart.HttpDataFactory;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static java.util.Objects.requireNonNull;

/**
 * Form data parser that uses Netty's implementation under the hood.
 */
public class NettyMultipartFormDataParser implements MultipartFormDataParser {

    private static final Logger log = LoggerFactory.getLogger(NettyMultipartFormDataParser.class);

    public NettyMultipartFormDataParser() {
    }

    protected HttpRequest mockRequest(MediaType contentType, byte[] data) {
        DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, io.netty.handler.codec.http.HttpMethod.POST, "", Unpooled.wrappedBuffer(data));
        request.headers().set(HttpHeaders.CONTENT_TYPE, contentType.toString());
        return request;
    }

    @Override
    public List decodeMultipartFormData(MediaType contentType, byte[] content) throws BadMultipartFormDataException, RuntimeIOException {
        HttpDataFactory dataFactory = new DefaultHttpDataFactory(false);
        HttpRequest request = mockRequest(contentType, content);
        HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(dataFactory, request);
        List parts = new ArrayList<>();
        while (decoder.hasNext()) {
            InterfaceHttpData data = decoder.next();
            if (data != null) {
                try {
                    switch (data.getHttpDataType()) {
                        case Attribute:
                            handleAttribute((Attribute) data, parts);
                            break;
                        case FileUpload:
                            handleFileUpload((FileUpload) data, parts);
                            break;
                        case InternalAttribute:
                            handleInternalAttribute(data, parts);
                            break;
                        default:
                            log.info("unhandled HttpDataType: {}", data.getHttpDataType());
                    }
                } catch (IOException e) {
                    throw new RuntimeIOException("netty threw exception", e);
                } finally {
                    data.release();
                }
            }
        }
        log.debug("{} parts parsed from form data", parts.size());
        return parts;
    }

    @SuppressWarnings("unused") // not sure what to do with these, if anything, so the parts list goes unused
    protected void handleInternalAttribute(InterfaceHttpData attr, List parts) {
        log.debug("internal attribute of {} encountered: {} name={}", attr.getClass(), attr.getHttpDataType(), attr.getName());
    }

    protected void handleAttribute(Attribute attr, List parts) throws IOException {
        parts.add(toFormDataPart(attr, null));
    }

    @Nullable
    protected String maybeGetFilename(HttpData httpData) {
        requireNonNull(httpData, "httpData");
        if (httpData instanceof FileUpload) {
            return ((FileUpload)httpData).getFilename();
        }
        return null;
    }

    protected FormDataPart toFormDataPart(HttpData httpData, @Nullable String partContentType) throws IOException {
        byte[] parsedContent = httpData.get();
        TypedContent file = TypedContent.identity(ByteSource.wrap(parsedContent), partContentType);
        String name = httpData.getName();
        ContentDisposition disposition = ContentDisposition.builder("form-data")
                .filename(maybeGetFilename(httpData))
                .name(name)
                .build();
        Multimap headers = ArrayListMultimap.create();
        return new FormDataPart(headers, disposition, file);
    }

    protected void handleFileUpload(FileUpload fileUpload, List parts) throws IOException {
        parts.add(toFormDataPart(fileUpload, fileUpload.getContentType()));
    }


}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy