Merge "Allow use server.go for testing against local site"
This commit is contained in:
@@ -338,7 +338,7 @@ public class WebAppInitializer extends GuiceServletContextListener implements Fi
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
|
||||
bind(GerritOptions.class).toInstance(new GerritOptions(false, false, ""));
|
||||
bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
|
||||
}
|
||||
});
|
||||
|
@@ -1,160 +0,0 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// 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 com.google.gerrit.httpd.raw;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.escape.Escaper;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.google.common.html.HtmlEscapers;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.gerrit.launcher.GerritLauncher;
|
||||
import com.google.gerrit.server.util.time.TimeUtil;
|
||||
import com.google.gerrit.util.http.CacheHeaders;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.jgit.util.RawParseUtils;
|
||||
|
||||
public class BazelBuild {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final Path sourceRoot;
|
||||
|
||||
public BazelBuild(Path sourceRoot) {
|
||||
this.sourceRoot = sourceRoot;
|
||||
}
|
||||
|
||||
// builds the given label.
|
||||
public void build(Label label) throws IOException, BuildFailureException {
|
||||
ProcessBuilder proc = newBuildProcess(label);
|
||||
proc.directory(sourceRoot.toFile()).redirectErrorStream(true);
|
||||
logger.atInfo().log("building %s", label.fullName());
|
||||
long start = TimeUtil.nowMs();
|
||||
Process rebuild = proc.start();
|
||||
byte[] out;
|
||||
try (InputStream in = rebuild.getInputStream()) {
|
||||
out = ByteStreams.toByteArray(in);
|
||||
} finally {
|
||||
rebuild.getOutputStream().close();
|
||||
}
|
||||
|
||||
int status;
|
||||
try {
|
||||
status = rebuild.waitFor();
|
||||
} catch (InterruptedException e) {
|
||||
String msg = "interrupted waiting for: " + Joiner.on(' ').join(proc.command());
|
||||
logger.atSevere().withCause(e).log(msg);
|
||||
throw new InterruptedIOException(msg);
|
||||
}
|
||||
if (status != 0) {
|
||||
logger.atWarning().log("build failed: %s", new String(out, UTF_8));
|
||||
throw new BuildFailureException(out);
|
||||
}
|
||||
|
||||
long time = TimeUtil.nowMs() - start;
|
||||
logger.atInfo().log("UPDATED %s in %.3fs", label.fullName(), time / 1000.0);
|
||||
}
|
||||
|
||||
// Represents a label in bazel.
|
||||
static class Label {
|
||||
protected final String pkg;
|
||||
protected final String name;
|
||||
|
||||
public String fullName() {
|
||||
return "//" + pkg + ":" + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fullName();
|
||||
}
|
||||
|
||||
// Label in Bazel style.
|
||||
Label(String pkg, String name) {
|
||||
this.name = name;
|
||||
this.pkg = pkg;
|
||||
}
|
||||
}
|
||||
|
||||
static class BuildFailureException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
final byte[] why;
|
||||
|
||||
BuildFailureException(byte[] why) {
|
||||
this.why = why;
|
||||
}
|
||||
|
||||
public void display(String rule, HttpServletResponse res) throws IOException {
|
||||
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
res.setContentType("text/html");
|
||||
res.setCharacterEncoding(UTF_8.name());
|
||||
CacheHeaders.setNotCacheable(res);
|
||||
|
||||
Escaper html = HtmlEscapers.htmlEscaper();
|
||||
try (PrintWriter w = res.getWriter()) {
|
||||
w.write("<html><title>BUILD FAILED</title><body>");
|
||||
w.format("<h1>%s FAILED</h1>", html.escape(rule));
|
||||
w.write("<pre>");
|
||||
w.write(html.escape(RawParseUtils.decode(why)));
|
||||
w.write("</pre>");
|
||||
w.write("</body></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ProcessBuilder newBuildProcess(Label label) throws IOException {
|
||||
Properties properties = GerritLauncher.loadBuildProperties(sourceRoot.resolve(".bazel_path"));
|
||||
String bazel = firstNonNull(properties.getProperty("bazel"), "bazel");
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add(bazel);
|
||||
cmd.add("build");
|
||||
if (GerritLauncher.isJdk9OrLater()) {
|
||||
String v = GerritLauncher.getJdkVersionPostJdk8();
|
||||
cmd.add("--host_java_toolchain=@bazel_tools//tools/jdk:toolchain_java" + v);
|
||||
cmd.add("--java_toolchain=@bazel_tools//tools/jdk:toolchain_java" + v);
|
||||
}
|
||||
cmd.add(label.fullName());
|
||||
ProcessBuilder proc = new ProcessBuilder(cmd);
|
||||
if (properties.containsKey("PATH")) {
|
||||
proc.environment().put("PATH", properties.getProperty("PATH"));
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
/** returns the root relative path to the artifact for the given label */
|
||||
public Path targetPath(Label l) {
|
||||
return sourceRoot.resolve("bazel-bin").resolve(l.pkg).resolve(l.name);
|
||||
}
|
||||
|
||||
/** Label for the polygerrit component zip. */
|
||||
public Label polygerritComponents() {
|
||||
return new Label("polygerrit-ui", "polygerrit_components.bower_components.zip");
|
||||
}
|
||||
|
||||
/** Label for the fonts zip file. */
|
||||
public Label fontZipLabel() {
|
||||
return new Label("polygerrit-ui", "fonts.zip");
|
||||
}
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
// Copyright (C) 2015 The Android Open Source Project
|
||||
//
|
||||
// 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 com.google.gerrit.httpd.raw;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.gerrit.launcher.GerritLauncher;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
/* Bower component servlet only used in development mode */
|
||||
class BowerComponentsDevServlet extends ResourceServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Path bowerComponents;
|
||||
private final Path zip;
|
||||
|
||||
BowerComponentsDevServlet(Cache<Path, Resource> cache, BazelBuild builder) throws IOException {
|
||||
super(cache, true);
|
||||
|
||||
Objects.requireNonNull(builder);
|
||||
BazelBuild.Label label = builder.polygerritComponents();
|
||||
try {
|
||||
builder.build(label);
|
||||
} catch (BazelBuild.BuildFailureException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
zip = builder.targetPath(label);
|
||||
bowerComponents = GerritLauncher.newZipFileSystem(zip).getPath("/");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path getResourcePath(String pathInfo) throws IOException {
|
||||
return bowerComponents.resolve(pathInfo);
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// 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 com.google.gerrit.httpd.raw;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.gerrit.launcher.GerritLauncher;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
/* Font servlet only used in development mode */
|
||||
class FontsDevServlet extends ResourceServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Path fonts;
|
||||
|
||||
FontsDevServlet(Cache<Path, Resource> cache, BazelBuild builder) throws IOException {
|
||||
super(cache, true);
|
||||
Objects.requireNonNull(builder);
|
||||
|
||||
BazelBuild.Label zipLabel = builder.fontZipLabel();
|
||||
try {
|
||||
builder.build(zipLabel);
|
||||
} catch (BazelBuild.BuildFailureException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
Path zip = builder.targetPath(zipLabel);
|
||||
Objects.requireNonNull(zip);
|
||||
|
||||
fonts = GerritLauncher.newZipFileSystem(zip).getPath("/");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Path getResourcePath(String pathInfo) throws IOException {
|
||||
return fonts.resolve(pathInfo);
|
||||
}
|
||||
}
|
@@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.httpd.raw;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static java.nio.file.Files.exists;
|
||||
import static java.nio.file.Files.isReadable;
|
||||
|
||||
@@ -222,7 +221,8 @@ public class StaticModule extends ServletModule {
|
||||
@CanonicalWebUrl @Nullable String canonicalUrl,
|
||||
@GerritServerConfig Config cfg,
|
||||
GerritApi gerritApi) {
|
||||
String cdnPath = cfg.getString("gerrit", null, "cdnPath");
|
||||
String cdnPath =
|
||||
options.useDevCdn() ? options.devCdn() : cfg.getString("gerrit", null, "cdnPath");
|
||||
String faviconPath = cfg.getString("gerrit", null, "faviconPath");
|
||||
return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi);
|
||||
}
|
||||
@@ -233,29 +233,8 @@ public class StaticModule extends ServletModule {
|
||||
return new PolyGerritUiServlet(cache, polyGerritBasePath());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
BowerComponentsDevServlet getBowerComponentsServlet(@Named(CACHE) Cache<Path, Resource> cache)
|
||||
throws IOException {
|
||||
return getPaths().isDev() ? new BowerComponentsDevServlet(cache, getPaths().builder) : null;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
FontsDevServlet getFontsServlet(@Named(CACHE) Cache<Path, Resource> cache) throws IOException {
|
||||
return getPaths().isDev() ? new FontsDevServlet(cache, getPaths().builder) : null;
|
||||
}
|
||||
|
||||
private Path polyGerritBasePath() {
|
||||
Paths p = getPaths();
|
||||
if (options.forcePolyGerritDev()) {
|
||||
checkArgument(
|
||||
p.sourceRoot != null, "no source root directory found for PolyGerrit developer mode");
|
||||
}
|
||||
|
||||
if (p.isDev()) {
|
||||
return p.sourceRoot.resolve("polygerrit-ui").resolve("app");
|
||||
}
|
||||
|
||||
return p.warFs != null
|
||||
? p.warFs.getPath("/polygerrit_ui")
|
||||
@@ -265,7 +244,6 @@ public class StaticModule extends ServletModule {
|
||||
|
||||
private static class Paths {
|
||||
private final FileSystem warFs;
|
||||
private final BazelBuild builder;
|
||||
private final Path sourceRoot;
|
||||
private final Path unpackedWar;
|
||||
private final boolean development;
|
||||
@@ -285,21 +263,19 @@ public class StaticModule extends ServletModule {
|
||||
launcherLoadedFrom.getParentFile().getParentFile().getParentFile().toURI());
|
||||
sourceRoot = null;
|
||||
development = false;
|
||||
builder = null;
|
||||
return;
|
||||
}
|
||||
warFs = getDistributionArchive(launcherLoadedFrom);
|
||||
if (warFs == null) {
|
||||
unpackedWar = makeWarTempDir();
|
||||
development = true;
|
||||
} else if (options.forcePolyGerritDev()) {
|
||||
} else if (options.useDevCdn()) {
|
||||
unpackedWar = null;
|
||||
development = true;
|
||||
} else {
|
||||
unpackedWar = null;
|
||||
development = false;
|
||||
sourceRoot = null;
|
||||
builder = null;
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -307,7 +283,6 @@ public class StaticModule extends ServletModule {
|
||||
}
|
||||
|
||||
sourceRoot = getSourceRootOrNull();
|
||||
builder = new BazelBuild(sourceRoot);
|
||||
}
|
||||
|
||||
private static Path getSourceRootOrNull() {
|
||||
@@ -376,21 +351,15 @@ public class StaticModule extends ServletModule {
|
||||
private final Paths paths;
|
||||
private final HttpServlet polyGerritIndex;
|
||||
private final PolyGerritUiServlet polygerritUI;
|
||||
private final BowerComponentsDevServlet bowerComponentServlet;
|
||||
private final FontsDevServlet fontServlet;
|
||||
|
||||
@Inject
|
||||
PolyGerritFilter(
|
||||
Paths paths,
|
||||
@Named(POLYGERRIT_INDEX_SERVLET) HttpServlet polyGerritIndex,
|
||||
PolyGerritUiServlet polygerritUI,
|
||||
@Nullable BowerComponentsDevServlet bowerComponentServlet,
|
||||
@Nullable FontsDevServlet fontServlet) {
|
||||
PolyGerritUiServlet polygerritUI) {
|
||||
this.paths = paths;
|
||||
this.polyGerritIndex = polyGerritIndex;
|
||||
this.polygerritUI = polygerritUI;
|
||||
this.bowerComponentServlet = bowerComponentServlet;
|
||||
this.fontServlet = fontServlet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,22 +377,6 @@ public class StaticModule extends ServletModule {
|
||||
GuiceFilterRequestWrapper reqWrapper = new GuiceFilterRequestWrapper(req);
|
||||
String path = pathInfo(req);
|
||||
|
||||
// Special case assets during development that are built by Bazel and not
|
||||
// served out of the source tree.
|
||||
//
|
||||
// In the war case, these are either inlined, or live under
|
||||
// /polygerrit_ui in the war file, so we can just treat them as normal
|
||||
// assets.
|
||||
if (paths.isDev()) {
|
||||
if (path.startsWith("/bower_components/")) {
|
||||
bowerComponentServlet.service(reqWrapper, res);
|
||||
return;
|
||||
} else if (path.startsWith("/fonts/")) {
|
||||
fontServlet.service(reqWrapper, res);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPolyGerritIndex(path)) {
|
||||
polyGerritIndex.service(reqWrapper, res);
|
||||
return;
|
||||
|
@@ -168,8 +168,18 @@ public class Daemon extends SiteProgram {
|
||||
@Option(name = "--headless", usage = "Don't start the UI frontend")
|
||||
private boolean headless;
|
||||
|
||||
@Option(name = "--polygerrit-dev", usage = "Force PolyGerrit UI for development")
|
||||
private boolean polyGerritDev;
|
||||
private String devCdn = "";
|
||||
|
||||
@Option(name = "--dev-cdn", usage = "Use specified cdn for serving static content.")
|
||||
private void setDevCdn(String cdn) {
|
||||
if (cdn == null) {
|
||||
cdn = "";
|
||||
}
|
||||
if (cdn.endsWith("/")) {
|
||||
cdn = cdn.substring(0, cdn.length() - 1);
|
||||
}
|
||||
devCdn = cdn;
|
||||
}
|
||||
|
||||
@Option(
|
||||
name = "--init",
|
||||
@@ -463,8 +473,7 @@ public class Daemon extends SiteProgram {
|
||||
new AbstractModule() {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(GerritOptions.class)
|
||||
.toInstance(new GerritOptions(headless, replica, polyGerritDev));
|
||||
bind(GerritOptions.class).toInstance(new GerritOptions(headless, replica, devCdn));
|
||||
if (inMemoryTest) {
|
||||
bind(String.class)
|
||||
.annotatedWith(SecureStoreClassName.class)
|
||||
|
@@ -17,12 +17,12 @@ package com.google.gerrit.server.config;
|
||||
public class GerritOptions {
|
||||
private final boolean headless;
|
||||
private final boolean slave;
|
||||
private final boolean forcePolyGerritDev;
|
||||
private final String devCdn;
|
||||
|
||||
public GerritOptions(boolean headless, boolean slave, boolean forcePolyGerritDev) {
|
||||
public GerritOptions(boolean headless, boolean slave, String devCdn) {
|
||||
this.headless = headless;
|
||||
this.slave = slave;
|
||||
this.forcePolyGerritDev = forcePolyGerritDev;
|
||||
this.devCdn = devCdn;
|
||||
}
|
||||
|
||||
public boolean headless() {
|
||||
@@ -33,7 +33,11 @@ public class GerritOptions {
|
||||
return !slave;
|
||||
}
|
||||
|
||||
public boolean forcePolyGerritDev() {
|
||||
return !headless && forcePolyGerritDev;
|
||||
public String devCdn() {
|
||||
return devCdn;
|
||||
}
|
||||
|
||||
public boolean useDevCdn() {
|
||||
return !headless && devCdn.length() > 0;
|
||||
}
|
||||
}
|
||||
|
@@ -181,7 +181,7 @@ public class InMemoryModule extends FactoryModule {
|
||||
// support Path-based Configs, only FileBasedConfig.
|
||||
bind(Path.class).annotatedWith(SitePath.class).toInstance(Paths.get("."));
|
||||
bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
|
||||
bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
|
||||
bind(GerritOptions.class).toInstance(new GerritOptions(false, false, ""));
|
||||
|
||||
bind(GitRepositoryManager.class).to(InMemoryRepositoryManager.class);
|
||||
bind(InMemoryRepositoryManager.class).in(SINGLETON);
|
||||
|
@@ -39,12 +39,11 @@ npm install
|
||||
It may complain about a missing `typescript@2.3.4` peer dependency, which is
|
||||
harmless.
|
||||
|
||||
## Running locally against production data
|
||||
## Serving files locally
|
||||
|
||||
#### Go server
|
||||
|
||||
To test the local Polymer frontend against gerrit-review.googlesource.com
|
||||
simply execute:
|
||||
To test the local Polymer frontend against production data or a local test site execute:
|
||||
|
||||
```sh
|
||||
./polygerrit-ui/run-server.sh
|
||||
@@ -53,10 +52,7 @@ simply execute:
|
||||
npm run start
|
||||
```
|
||||
|
||||
Then visit http://localhost:8081
|
||||
|
||||
This method is based on a
|
||||
[simple hand-written Go webserver](https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/server.go).
|
||||
These commands start the [simple hand-written Go webserver](https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/server.go).
|
||||
Mostly it just switches between serving files locally and proxying the real
|
||||
server based on the file name. It also does some basic response rewriting, e.g.
|
||||
it patches the `config/server/info` response with plugin information provided on
|
||||
@@ -66,6 +62,12 @@ the command line:
|
||||
./polygerrit-ui/run-server.sh --plugins=plugins/my_plugin/static/my_plugin.js,plugins/my_plugin/static/my_plugin.html
|
||||
```
|
||||
|
||||
## Running locally against production data
|
||||
|
||||
### Local website
|
||||
|
||||
Start [Go server](#go-server) and then visit http://localhost:8081
|
||||
|
||||
The biggest draw back of this method is that you cannot log in, so cannot test
|
||||
scenarios that require it.
|
||||
|
||||
@@ -89,9 +91,11 @@ Set up a local test site once:
|
||||
3. Optionally [populate](https://gerrit.googlesource.com/gerrit/+/master/contrib/populate-fixture-data.py) your test site with some test data.
|
||||
|
||||
For running a locally built Gerrit war against your test instance use
|
||||
[this command](https://gerrit-review.googlesource.com/Documentation/dev-readme.html#run_daemon),
|
||||
and add the `--polygerrit-dev` option, if you want to serve the Polymer frontend
|
||||
directly from the sources in `polygerrit_ui/app/` instead of from the war:
|
||||
[this command](https://gerrit-review.googlesource.com/Documentation/dev-readme.html#run_daemon).
|
||||
|
||||
If you want to serve the Polymer frontend directly from the sources in `polygerrit_ui/app/` instead of from the war:
|
||||
1. Start [Go server](#go-server)
|
||||
2. Add the `--dev-cdn` option:
|
||||
|
||||
```sh
|
||||
$(bazel info output_base)/external/local_jdk/bin/java \
|
||||
@@ -99,9 +103,11 @@ $(bazel info output_base)/external/local_jdk/bin/java \
|
||||
-jar bazel-bin/gerrit.war daemon \
|
||||
-d $GERRIT_SITE \
|
||||
--console-log \
|
||||
--polygerrit-dev
|
||||
--dev-cdn http://localhost:8081
|
||||
```
|
||||
|
||||
*NOTE* You can use any other cdn here, for example: https://cdn.googlesource.com/polygerrit_ui/678.0
|
||||
|
||||
## Running Tests
|
||||
|
||||
This step requires the `web-component-tester` npm module.
|
||||
|
@@ -64,11 +64,12 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
http.Handle("/", http.FileServer(http.Dir("app")))
|
||||
http.Handle("/", addDevHeadersMiddleware(http.FileServer(http.Dir("app"))))
|
||||
http.Handle("/bower_components/",
|
||||
http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components"))))
|
||||
addDevHeadersMiddleware(
|
||||
http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components")))))
|
||||
http.Handle("/fonts/",
|
||||
http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts"))))
|
||||
addDevHeadersMiddleware(http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts")))))
|
||||
|
||||
http.HandleFunc("/index.html", handleIndex)
|
||||
http.HandleFunc("/changes/", handleProxy)
|
||||
@@ -92,6 +93,14 @@ func main() {
|
||||
log.Fatal(http.ListenAndServe(*port, &server{}))
|
||||
}
|
||||
|
||||
func addDevHeadersMiddleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(writer http.ResponseWriter, req *http.Request) {
|
||||
writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
writer.Header().Set("Cache-Control", "public, max-age=10, must-revalidate")
|
||||
h.ServeHTTP(writer, req)
|
||||
})
|
||||
}
|
||||
|
||||
func openDataArchive(path string) (*zip.ReadCloser, error) {
|
||||
absBinPath, err := resourceBasePath()
|
||||
if err != nil {
|
||||
|
Reference in New Issue
Block a user