/* * Copyright 2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ratpack.site; import asset.pipeline.ratpack.AssetPipelineModule; import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; import ratpack.dropwizard.metrics.DropwizardMetricsModule; import ratpack.func.Block; import ratpack.func.Pair; import ratpack.groovy.template.MarkupTemplateModule; import ratpack.groovy.template.TextTemplateModule; import ratpack.guice.Guice; import ratpack.newrelic.NewRelicModule; import ratpack.registry.Registry; import ratpack.rx.RxRatpack; import ratpack.server.BaseDir; import ratpack.server.RatpackServer; import ratpack.site.github.GitHubData; import ratpack.site.github.RatpackVersion; import ratpack.site.github.RatpackVersions; import static ratpack.groovy.Groovy.groovyMarkupTemplate; public class SiteMain { public static void main(String... args) throws Exception { RxRatpack.initialize(); RatpackServer.start(b -> b .serverConfig(s -> s .baseDir(BaseDir.find()) .env() .require("/github", SiteModule.GitHubConfig.class) ) .registry( Guice.registry(s -> s .module(NewRelicModule.class) .module(new AssetPipelineModule()) .module(new DropwizardMetricsModule(), c -> c.csv(csv -> csv.enable(false)) ) .module(SiteModule.class) .module(MarkupTemplateModule.class, conf -> { conf.setAutoNewLine(true); conf.setUseDoubleQuotes(true); conf.setAutoIndent(true); }) .module(TextTemplateModule.class, conf -> conf.setStaticallyCompile(true) ) ) ) .handlers(c -> { int longCache = 60 * 60 * 24 * 365; // one year int shortCache = 60 * 10; // ten mins c .all(ctx -> { //noinspection ConstantConditions String host = ctx.getRequest().getHeaders().get("host"); if (host != null && (host.endsWith("ratpack-framework.org") || host.equals("www.ratpack.io"))) { ctx.redirect(301, "http://ratpack.io" + ctx.getRequest().getRawUri()); return; } if (ctx.getRequest().getPath().isEmpty() || ctx.getRequest().getPath().equals("index.html")) { ctx.getResponse().getHeaders().set("X-UA-Compatible", "IE=edge,chrome=1"); } ctx.next(); }) // No longer needed and hasnt been for a while. Cache busting automatically handled by the AssetPipelineHandler // .prefix("assets", assets -> assets // .all(ctx -> { // int cacheFor = ctx.getRequest().getQuery().isEmpty() ? shortCache : longCache; // ctx.getResponse().getHeaders().add("Cache-Control", "max-age=" + cacheFor + ", public"); // ctx.next(); // }) // .files(f -> f.dir("assets").indexFiles("index.html")) // ) .get("index.html", ctx -> { ctx.redirect(301, "/"); }) .get(ctx -> ctx.render(groovyMarkupTemplate("index.gtpl"))) .get("resources", ctx -> ctx.render(groovyMarkupTemplate("resources.gtpl"))) .path("reset", ctx -> ctx.byMethod(methods -> { Block impl = () -> { ctx.get(GitHubData.class).forceRefresh(); ctx.render("ok"); }; if (ctx.getServerConfig().isDevelopment()) { methods.get(impl); } methods.post(impl); }) ) .prefix("versions", v -> v .get(ctx -> ctx.render( ctx.get(RatpackVersions.class).getAll() .map(all -> groovyMarkupTemplate("versions.gtpl", m -> m.put("versions", all))) ) ) .get(":version", ctx -> ctx.render( ctx.get(RatpackVersions.class).getAll() .map(all -> all.version(ctx.getAllPathTokens().get("version"))) .onNull(() -> ctx.clientError(404)) .flatMap(version -> ctx.get(GitHubData.class).closed(version).map(i -> Pair.of(version, i))) .map(p -> groovyMarkupTemplate("version.gtpl", m -> m.put("version", p.left).put("issues", p.right))) ) ) ) .prefix("manual", c1 -> c1 .fileSystem("manual", c2 -> c2 .get(ctx -> ctx.redirect(301, "/manual/current")) .prefix(":label", c3 -> c3 .all(ctx -> { String label = ctx.getPathTokens().get("label"); ctx.get(RatpackVersions.class).getAll().then(all -> { if (label.equals("current") || all.isReleased(label)) { ctx.getResponse().getHeaders().add("Cache-Control", "max-age=" + longCache + ", public"); } else if (label.equals("snapshot") || all.isUnreleased(label)) { ctx.getResponse().getHeaders().add("Cache-Control", "max-age=" + shortCache + ", public"); } RatpackVersion version; switch (label) { case "current": version = all.getCurrent(); break; case "snapshot": version = all.getSnapshot(); break; default: version = all.version(label); if (version == null) { ctx.clientError(404); return; } break; } ctx.next(Registry.single(ctx.getFileSystemBinding().binding(version.getVersion()))); }); }) .files(f -> f.indexFiles("index.html")) ) ) ) .get("robots.txt", ctx -> ctx.get(RatpackVersions.class).getAll() .map(RatpackVersions.All::getAll) .map(v -> FluentIterable.from(v).transform(i -> "Disallow: /manual/" + i.getVersion()).join(Joiner.on("\n"))) .map(s -> "User-agent: *\nDisallow: /manual/snapshot\n" + s) .then(ctx::render) ) .get("favicon.ico", ctx -> { ctx.getResponse().getHeaders().add("Cache-Control", "max-age=" + longCache + ", public"); ctx.next(); }) .files(f -> f.dir("public").indexFiles("index.html")); }) ); } }