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

com.firefly.server.http2.router.handler.body.HTTPBodyHandler Maven / Gradle / Ivy

There is a newer version: 5.0.0-dev6
Show newest version
package com.firefly.server.http2.router.handler.body;

import com.firefly.codec.http2.encode.UrlEncoded;
import com.firefly.codec.http2.model.HttpHeader;
import com.firefly.codec.http2.model.HttpHeaderValue;
import com.firefly.codec.http2.model.MimeTypes;
import com.firefly.codec.http2.model.MultiPartInputStreamParser;
import com.firefly.server.http2.SimpleRequest;
import com.firefly.server.http2.router.Handler;
import com.firefly.server.http2.router.RoutingContext;
import com.firefly.utils.StringUtils;
import com.firefly.utils.io.BufferUtils;
import com.firefly.utils.io.ByteArrayPipedStream;
import com.firefly.utils.io.FilePipedStream;
import com.firefly.utils.io.IO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Pengtao Qiu
 */
public class HTTPBodyHandler implements Handler {

    private static final Logger log = LoggerFactory.getLogger("firefly-system");

    private HTTPBodyConfiguration configuration;

    public HTTPBodyHandler() {
        this(new HTTPBodyConfiguration());
    }

    public HTTPBodyHandler(HTTPBodyConfiguration configuration) {
        this.configuration = configuration;
    }

    public HTTPBodyConfiguration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(HTTPBodyConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    public void handle(RoutingContext ctx) {
        SimpleRequest request = ctx.getRequest();
        HTTPBodyHandlerSPIImpl httpBodyHandlerSPI = new HTTPBodyHandlerSPIImpl();
        httpBodyHandlerSPI.urlEncodedMap = new UrlEncoded();
        httpBodyHandlerSPI.charset = configuration.getCharset();
        ctx.setHTTPBodyHandlerSPI(httpBodyHandlerSPI);

        if (StringUtils.hasText(request.getURI().getQuery())) {
            httpBodyHandlerSPI.urlEncodedMap.decode(request.getURI().getQuery(), Charset.forName(configuration.getCharset()));
        }

        if (ctx.isAsynchronousRead()) { // receive content event has been listened
            ctx.next();
            return;
        }

        String transferEncoding = request.getFields().get(HttpHeader.TRANSFER_ENCODING);
        if (HttpHeaderValue.CHUNKED.asString().equals(transferEncoding)) {
            httpBodyHandlerSPI.pipedStream = new ByteArrayPipedStream(4 * 1024);
        } else {
            long contentLength = request.getContentLength();
            if (contentLength <= 0) { // no content
                ctx.next();
                return;
            } else {
                if (contentLength > configuration.getBodyBufferThreshold()) {
                    httpBodyHandlerSPI.pipedStream = new FilePipedStream(configuration.getTempFilePath());
                } else {
                    httpBodyHandlerSPI.pipedStream = new ByteArrayPipedStream((int) contentLength);
                }
            }
        }

        AtomicLong chunkedEncodingContentLength = new AtomicLong();
        ctx.content(buf -> {
            if (log.isDebugEnabled()) {
                log.debug("http body handler received content size -> {}", buf.remaining());
            }

            try {
                if (HttpHeaderValue.CHUNKED.asString().equals(transferEncoding)) {
                    if (chunkedEncodingContentLength.addAndGet(buf.remaining()) > configuration.getBodyBufferThreshold()
                            && httpBodyHandlerSPI.pipedStream instanceof ByteArrayPipedStream) {
                        // chunked encoding content dump to temp file
                        IO.close(httpBodyHandlerSPI.pipedStream.getOutputStream());
                        FilePipedStream filePipedStream = new FilePipedStream(configuration.getTempFilePath());
                        IO.copy(httpBodyHandlerSPI.pipedStream.getInputStream(), filePipedStream.getOutputStream());
                        filePipedStream.getOutputStream().write(BufferUtils.toArray(buf));
                        httpBodyHandlerSPI.pipedStream = filePipedStream;
                    } else {
                        httpBodyHandlerSPI.pipedStream.getOutputStream().write(BufferUtils.toArray(buf));
                    }
                } else {
                    httpBodyHandlerSPI.pipedStream.getOutputStream().write(BufferUtils.toArray(buf));
                }
            } catch (IOException e) {
                log.error("http server receives http body exception", e);
            }
        }).contentComplete(req -> {
            try {
                String contentType = MimeTypes.getContentTypeMIMEType(request.getFields().get(HttpHeader.CONTENT_TYPE));
                httpBodyHandlerSPI.pipedStream.getOutputStream().close();
                if ("application/x-www-form-urlencoded".equals(contentType)) {
                    try (InputStream inputStream = httpBodyHandlerSPI.pipedStream.getInputStream()) {
                        httpBodyHandlerSPI.urlEncodedMap.decode(IO.toString(inputStream, configuration.getCharset()),
                                Charset.forName(configuration.getCharset()));
                    }
                } else if ("multipart/form-data".equals(contentType)) {
                    httpBodyHandlerSPI.multiPartInputStreamParser = new MultiPartInputStreamParser(
                            httpBodyHandlerSPI.getInputStream(),
                            request.getFields().get(HttpHeader.CONTENT_TYPE),
                            configuration.getMultipartConfigElement(),
                            new File(configuration.getTempFilePath()));
                }
            } catch (IOException e) {
                log.error("http server ends receiving data exception", e);
            }
        }).messageComplete(req -> ctx.next());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy