Properly support gzipped assets.
This reverts my previous approach and applies a better approach. My previous approach expected URLs to change to have ".gz" extensions. The new approach keeps the URLs the same but checks if a file exists on-disk that has the same name with the ".gz" extension.
This commit is contained in:
parent
bb89ca0b83
commit
6d934dbd6b
2 changed files with 42 additions and 35 deletions
|
@ -291,59 +291,62 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContentType {
|
kj::StringPtr inferContentType(kj::StringPtr filename) {
|
||||||
kj::StringPtr type;
|
|
||||||
kj::StringPtr encoding;
|
|
||||||
|
|
||||||
ContentType(kj::StringPtr type): type(type), encoding(nullptr) {}
|
|
||||||
ContentType(const char* type): type(type), encoding(nullptr) {}
|
|
||||||
ContentType() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
ContentType inferContentType(kj::StringPtr filename) {
|
|
||||||
ContentType result;
|
|
||||||
kj::String scratch;
|
|
||||||
|
|
||||||
if (filename.endsWith(".gz")) {
|
|
||||||
result.encoding = "gzip";
|
|
||||||
scratch = kj::str(filename.slice(0, filename.size() - 3));
|
|
||||||
filename = scratch;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filename.endsWith(".html")) {
|
if (filename.endsWith(".html")) {
|
||||||
result.type = "text/html; charset=UTF-8";
|
return "text/html; charset=UTF-8";
|
||||||
} else if (filename.endsWith(".js")) {
|
} else if (filename.endsWith(".js")) {
|
||||||
result.type = "text/javascript; charset=UTF-8";
|
return "text/javascript; charset=UTF-8";
|
||||||
} else if (filename.endsWith(".css")) {
|
} else if (filename.endsWith(".css")) {
|
||||||
result.type = "text/css; charset=UTF-8";
|
return "text/css; charset=UTF-8";
|
||||||
} else if (filename.endsWith(".png")) {
|
} else if (filename.endsWith(".png")) {
|
||||||
result.type = "image/png";
|
return "image/png";
|
||||||
} else if (filename.endsWith(".gif")) {
|
} else if (filename.endsWith(".gif")) {
|
||||||
result.type = "image/gif";
|
return "image/gif";
|
||||||
} else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
|
} else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
|
||||||
result.type = "image/jpeg";
|
return "image/jpeg";
|
||||||
} else if (filename.endsWith(".svg")) {
|
} else if (filename.endsWith(".svg")) {
|
||||||
result.type = "image/svg+xml; charset=UTF-8";
|
return "image/svg+xml; charset=UTF-8";
|
||||||
} else if (filename.endsWith(".txt")) {
|
} else if (filename.endsWith(".txt")) {
|
||||||
result.type = "text/plain; charset=UTF-8";
|
return "text/plain; charset=UTF-8";
|
||||||
} else {
|
} else {
|
||||||
result.type = "application/octet-stream";
|
return "application/octet-stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kj::Promise<void> readFile(
|
kj::Promise<void> readFile(
|
||||||
kj::StringPtr filename, GetContext context, ContentType contentType) {
|
kj::StringPtr filename, GetContext context, kj::StringPtr contentType) {
|
||||||
KJ_IF_MAYBE(fd, tryOpen(filename, O_RDONLY)) {
|
// Do we support compression?
|
||||||
|
bool canGzip = false;
|
||||||
|
for (auto accept: context.getParams().getContext().getAcceptEncoding()) {
|
||||||
|
if (accept.getContentCoding() == "gzip") {
|
||||||
|
canGzip = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If compression is supported, look for file with .gz extension.
|
||||||
|
kj::Maybe<kj::AutoCloseFd> maybeFd;
|
||||||
|
bool isGzipped = false;
|
||||||
|
if (canGzip) {
|
||||||
|
maybeFd = tryOpen(kj::str(filename, ".gz"), O_RDONLY);
|
||||||
|
isGzipped = maybeFd != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we haven't found a suitable file yet, look for the uncompressed version.
|
||||||
|
if (maybeFd == nullptr) {
|
||||||
|
maybeFd = tryOpen(filename, O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serve it.
|
||||||
|
KJ_IF_MAYBE(fd, kj::mv(maybeFd)) {
|
||||||
auto size = getFileSize(*fd, filename);
|
auto size = getFileSize(*fd, filename);
|
||||||
kj::FdInputStream stream(kj::mv(*fd));
|
kj::FdInputStream stream(kj::mv(*fd));
|
||||||
auto response = context.getResults(capnp::MessageSize { size / sizeof(capnp::word) + 32, 0 });
|
auto response = context.getResults(capnp::MessageSize { size / sizeof(capnp::word) + 32, 0 });
|
||||||
auto content = response.initContent();
|
auto content = response.initContent();
|
||||||
content.setStatusCode(sandstorm::WebSession::Response::SuccessCode::OK);
|
content.setStatusCode(sandstorm::WebSession::Response::SuccessCode::OK);
|
||||||
content.setMimeType(contentType.type);
|
content.setMimeType(contentType);
|
||||||
if (contentType.encoding != nullptr) {
|
if (isGzipped) {
|
||||||
content.setEncoding(contentType.encoding);
|
content.setEncoding("gzip");
|
||||||
}
|
}
|
||||||
stream.read(content.getBody().initBytes(size).begin(), size);
|
stream.read(content.getBody().initBytes(size).begin(), size);
|
||||||
return kj::READY_NOW;
|
return kj::READY_NOW;
|
||||||
|
|
|
@ -40,6 +40,10 @@ mkdir -p build/.sandstorm/client/styles
|
||||||
cp -rf ../../war/styles/* build/.sandstorm/client/styles/
|
cp -rf ../../war/styles/* build/.sandstorm/client/styles/
|
||||||
mkdir -p build/.sandstorm/client/templates
|
mkdir -p build/.sandstorm/client/templates
|
||||||
cp -rf ../../war/templates/* build/.sandstorm/client/templates/
|
cp -rf ../../war/templates/* build/.sandstorm/client/templates/
|
||||||
|
|
||||||
|
echo "Compressing assets"
|
||||||
|
gfind build/.sandstorm/client -name '*.html' -o -name '*.css' -o -name '*.js' -o -name '*.txt' -o -name '*.xml' | xargs gzip -k
|
||||||
|
|
||||||
echo "Creating file list"
|
echo "Creating file list"
|
||||||
cd build/.sandstorm
|
cd build/.sandstorm
|
||||||
gfind ./client -type f -printf "%p\n" | cut -c 3- > sandstorm-files.list
|
gfind ./client -type f -printf "%p\n" | cut -c 3- > sandstorm-files.list
|
||||||
|
|
Loading…
Reference in a new issue