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

io.github.sinri.keel.web.http.fastdocs.KeelFastDocsKit Maven / Gradle / Ivy

Go to download

A website framework with VERT.X for ex-PHP-ers, exactly Ark Framework Users.

The newest version!
package io.github.sinri.keel.web.http.fastdocs;

import io.github.sinri.keel.web.http.fastdocs.page.CataloguePageBuilder;
import io.github.sinri.keel.web.http.fastdocs.page.MarkdownCssBuilder;
import io.github.sinri.keel.web.http.fastdocs.page.MarkdownPageBuilder;
import io.github.sinri.keel.web.http.fastdocs.page.PageBuilderOptions;
import io.vertx.core.Future;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.StaticHandler;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * @since 1.12
 * @since 3.0.0 TEST PASSED
 */
public class KeelFastDocsKit {
    private final StaticHandler staticHandler;
    private final String rootURLPath;
    private final String rootMarkdownFilePath;

    private String documentSubject = "FastDocs";
    private String footerText = "Public Domain";

//    private KeelEventLogger eventLogger = KeelEventLogger.from(KeelIssueRecordCenter.createSilentIssueRecorder());

    /**
     * @param rootURLPath          such as `/prefix/`
     * @param rootMarkdownFilePath such as `path/to/dir/`
     */
    public KeelFastDocsKit(String rootURLPath, String rootMarkdownFilePath) {
        this.staticHandler = StaticHandler.create();
        this.rootURLPath = rootURLPath;
        this.rootMarkdownFilePath = rootMarkdownFilePath;
    }

    /**
     * If you want to install a route for FastDocs in a certain Router,
     * which mounts URL `[schema]://[domain]/fast-docs/*` to
     * the directory contains markdown files in `resources` as `webroot/markdown/*` .
     *
     * @param router          Router
     * @param urlPathBase     such as `/fast-docs/`
     * @param docsDirPathBase such as `webroot/markdown/`
     */
    public static void installToRouter(
            Router router,
            String urlPathBase,
            String docsDirPathBase,
            String subject,
            String footer
    ) {
        if (!urlPathBase.endsWith("/")) {
            urlPathBase = urlPathBase + "/";
        }
        if (!docsDirPathBase.endsWith("/")) {
            docsDirPathBase = docsDirPathBase + "/";
        }

        KeelFastDocsKit keelFastDocsKit = new KeelFastDocsKit(urlPathBase, docsDirPathBase)
                .setDocumentSubject(subject)
                .setFooterText(footer);

        router.route(urlPathBase + "*")
                .handler(keelFastDocsKit::processRouterRequest);
    }

    public KeelFastDocsKit setDocumentSubject(String documentSubject) {
        this.documentSubject = documentSubject;
        return this;
    }

    public KeelFastDocsKit setFooterText(String footerText) {
        this.footerText = footerText;
        return this;
    }

    public void processRouterRequest(RoutingContext ctx) {
        var requestInfo = new JsonObject()
                .put("method", ctx.request().method().name())
                .put("path", ctx.request().path())
                .put("stream_id", ctx.request().streamId());
        // eventLogger.debug(event -> event.message("processRouterRequest start").context(c -> c.put("request", requestInfo)));
        if (!Objects.equals(ctx.request().method(), HttpMethod.GET)) {
            ctx.response().setStatusCode(405).end();
            // eventLogger.warning(event -> event.message("processRouterRequest ends with 405").context(c -> c.put("request", requestInfo)));
            return;
        }

        String requestPath = ctx.request().path();

        PageBuilderOptions options = new PageBuilderOptions();
        options.ctx = ctx;
        options.subjectOfDocuments = this.documentSubject;
        options.footerText = this.footerText;
        options.rootURLPath = this.rootURLPath;
        options.rootMarkdownFilePath = this.rootMarkdownFilePath;

//        eventLogger.debug(r -> r.message("requestPath: " + requestPath));
        if (requestPath.equals(rootURLPath) || requestPath.equals(rootURLPath + "/")) {
            // eventLogger.debug(event -> event.message("processRouterRequest -> 302").context(c -> c.put("request", requestInfo)));
            ctx.redirect(rootURLPath + (rootURLPath.endsWith("/") ? "" : "/") + "index.md");
        } else if (requestPath.endsWith(".md")) {
            // eventLogger.debug(event -> event.message("processRouterRequest -> processRequestWithMarkdownPath").context(c -> c.put("request", requestInfo)));
            processRequestWithMarkdownPath(options);
        } else if (requestPath.equalsIgnoreCase(this.rootURLPath + "catalogue")) {
            // eventLogger.debug(event -> event.message("processRouterRequest -> processRequestWithCatalogue").context(c -> c.put("request", requestInfo)));
            processRequestWithCatalogue(options);
        } else if (requestPath.equalsIgnoreCase(this.rootURLPath + "markdown.css")) {
            // eventLogger.debug(event -> event.message("processRouterRequest -> processRequestWithMarkdownCSS").context(c -> c.put("request", requestInfo)));
            processRequestWithMarkdownCSS(options);
        } else {
            // eventLogger.debug(event -> event.message("processRouterRequest -> processRequestWithStaticPath").context(c -> c.put("request", requestInfo)));
            processRequestWithStaticPath(options);
        }
    }

    private Future getRelativePathOfRequest(RoutingContext ctx) {
        String requestPath = ctx.request().path();

        if (!requestPath.startsWith(this.rootURLPath)) {
            return Future.failedFuture("Not match url root");
        }
        var raw = requestPath.substring(this.rootURLPath.length());
        return Future.succeededFuture(URLDecoder.decode(raw, StandardCharsets.UTF_8));
    }

    protected void processRequestWithMarkdownPath(PageBuilderOptions options) {
        getRelativePathOfRequest(options.ctx)
                .compose(relativePathOfMarkdownFile -> {
                    // eventLogger.debug(r -> r.message("processRequestWithMarkdownPath relativePathOfMarkdownFile: " + relativePathOfMarkdownFile));
                    String markdownFilePath = this.rootMarkdownFilePath + relativePathOfMarkdownFile;
                    // eventLogger.debug(r -> r.message("processRequestWithMarkdownPath file: " + markdownFilePath));
                    File x = new File(markdownFilePath);
                    // eventLogger.debug(r -> r.message("abs: " + x.getAbsolutePath()));
                    String markdownContent;
                    try {
                        InputStream resourceAsStream = getClass().getClassLoader()
                                .getResourceAsStream(markdownFilePath);
                        if (resourceAsStream == null) {
                            throw new IOException("resourceAsStream is null");
                        }
                        byte[] bytes = resourceAsStream.readAllBytes();
                        markdownContent = new String(bytes);
                    } catch (IOException e) {
                        // eventLogger.exception(e, r -> r.message("Cannot read target file " + markdownFilePath));
                        return Future.failedFuture("Cannot read target file: " + e.getMessage());
                    }

                    options.markdownContent = markdownContent;

                    return Future.succeededFuture(new MarkdownPageBuilder(options));
                })
                .onFailure(throwable -> {
                    //eventLogger.exception(throwable, r -> r.message("processRequestWithMarkdownPath 404"));
                    options.ctx.response().setStatusCode(404).end();
                })
                .compose(MarkdownPageBuilder::respond)
                .compose(v -> {
                    // eventLogger.debug(r -> r.message("processRequestWithMarkdownPath ends"));
                    return Future.succeededFuture();
                });

    }

    protected void processRequestWithCatalogue(PageBuilderOptions options) {
        options.fromDoc = options.ctx.request().getParam("from_doc");
        new CataloguePageBuilder(options).respond()
                .compose(v -> {
                    //eventLogger.debug(r -> r.message("processRequestWithCatalogue ends"));
                    return Future.succeededFuture();
                });
    }

    protected void processRequestWithMarkdownCSS(PageBuilderOptions options) {
        new MarkdownCssBuilder(options).respond()
                .compose(v -> {
                    // eventLogger.debug(r -> r.message("processRequestWithMarkdownCSS ends"));
                    return Future.succeededFuture();
                });
    }

    protected void processRequestWithStaticPath(PageBuilderOptions options) {
        this.staticHandler.handle(options.ctx);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy