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

io.higgs.http.server.transformers.StaticFileTransformer Maven / Gradle / Ivy

package io.higgs.http.server.transformers;

import io.higgs.core.ConfigUtil;
import io.higgs.core.FileUtil;
import io.higgs.core.ResolvedFile;
import io.higgs.core.reflect.dependency.DependencyProvider;
import io.higgs.core.reflect.dependency.Injector;
import io.higgs.http.server.HttpRequest;
import io.higgs.http.server.HttpResponse;
import io.higgs.http.server.config.HttpConfig;
import io.higgs.http.server.protocol.HttpMethod;
import io.higgs.http.server.resource.MediaType;
import io.higgs.http.server.transformers.conf.FilesConfig;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.multipart.DiskAttribute;
import io.netty.handler.codec.http.multipart.DiskFileUpload;
import org.kohsuke.MetaInfServices;

import javax.ws.rs.WebApplicationException;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Courtney Robinson 
 */
//@ProviderFor(ResponseTransformer.class)
@MetaInfServices(ResponseTransformer.class)
public class StaticFileTransformer extends BaseTransformer {
    private static Map formats = new ConcurrentHashMap<>();
    protected HttpConfig config;
    protected Path base;
    private FilesConfig conf;

    public StaticFileTransformer() {
        //inject HttpConfig
        Injector.inject(this, DependencyProvider.global());
        conf = ConfigUtil.loadYaml("static_file_config.yml", FilesConfig.class);
        base = Paths.get(config.public_directory);

        // should delete file
        DiskFileUpload.deleteOnExitTemporaryFile = conf.delete_temp_on_exit;
        // system temp directory
        DiskFileUpload.baseDirectory = conf.temp_directory;
        // should delete file on
        DiskAttribute.deleteOnExitTemporaryFile = conf.delete_temp_on_exit;
        // exit (in normal exit)
        DiskAttribute.baseDirectory = conf.temp_directory;

        //htm,html -> text/html, json -> application/json, xml -> application/xml
        Map textFormats = conf.custom_mime_types;
        //map multiple extensions to the same content type
        for (String commaSeparatedExtensions : textFormats.keySet()) {
            String[] extensions = commaSeparatedExtensions.split(",");
            String contentType = textFormats.get(commaSeparatedExtensions);
            for (String extension : extensions) {
                formats.put(extension, contentType);
            }
        }
        setPriority(conf.priority); //after JSON
    }

    /**
     * Overrides the default behaviour in
     * {@link BaseTransformer#canTransform(Object, HttpRequest, MediaType, HttpMethod, ChannelHandlerContext)}
     * for a custom check on static files
     */
    @Override
    public boolean canTransform(Object response, HttpRequest request, MediaType mediaType, HttpMethod method,
                                ChannelHandlerContext ctx) {
        return isStaticFileResponse(response);
    }

    @Override
    public void transform(Object response, HttpRequest request, HttpResponse res, MediaType mediaType,
                          HttpMethod method,
                          ChannelHandlerContext ctx) {
        if (response != null) {
            if (response instanceof File) {
                response = FileUtil.resolve(base, (File) response);
            } else if (response instanceof Path) {
                response = FileUtil.resolve(base, (Path) response);
            } else if (response instanceof WebApplicationException) {
                WebApplicationException ex = (WebApplicationException) response;
                res.setStatus(HttpResponseStatus.valueOf(ex.getResponse().getStatus()));
                if (ex.getMessage() != null && !ex.getMessage().isEmpty()) {
                    byte[] msg = ex.getMessage().getBytes();
                    ByteBuf buf = ctx.alloc().heapBuffer(msg.length);
                    res.resetContent(buf);
                }
            }
            if (response instanceof ResolvedFile) {
                writeResponseFromStream((ResolvedFile) response, res, request, mediaType, method, ctx);
            } else {
                res.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
                if (isError(response)) {
                    log.warn("Unexpected error to static file transformer", response);
                } else {
                    log.warn(String.format("Expecting an input stream or file,%s received",
                            response.getClass().getName()));
                }
            }
        }
    }

    private void writeResponseFromStream(ResolvedFile response, HttpResponse res, HttpRequest request,
                                         MediaType mediaType, HttpMethod method, ChannelHandlerContext ctx) {
        res.setManagedWriter(new StaticFileWriter(ctx, res, response, request, formats, conf));
    }

    @Override
    public ResponseTransformer instance() {
        return new StaticFileTransformer();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy