Skip to content

Commit

Permalink
Merge pull request #12639 from rstudio/aj-prefer-precompressed-assets
Browse files Browse the repository at this point in the history
Add support for serving static files precompressed with Gzip/Brotli
  • Loading branch information
atheriel committed Jan 28, 2023
2 parents 389a9d9 + a193399 commit 3d5918d
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/cpp/core/http/Message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ namespace core {
namespace http {

// encodings
const char * const kBrotliEncoding = "br";
const char * const kGzipEncoding = "gzip";
const char * const kDeflateEncoding = "deflate";

Expand Down
22 changes: 22 additions & 0 deletions src/cpp/core/http/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,28 @@ void fileRequestHandler(const std::string& wwwLocalPath,
return;
}

#ifndef _WIN32
// To avoid the runtime CPU cost of compression, also check if there is a
// precompressed version of the file available and substitute it in if so.
// This is akin to the (gzip|brotli)_static directive for NGINX.
FilePath precompressed = FilePath(filePath.getAbsolutePath() + ".br");
if (request.acceptsEncoding(kBrotliEncoding) && precompressed.exists())
{
pResponse->setContentType(filePath.getMimeContentType());
pResponse->setContentEncoding(kBrotliEncoding);
pResponse->setCacheableFile(precompressed, request);
return;
}
precompressed = FilePath(filePath.getAbsolutePath() + ".gz");
if (request.acceptsEncoding(kGzipEncoding) && precompressed.exists())
{
pResponse->setContentType(filePath.getMimeContentType());
pResponse->setContentEncoding(kGzipEncoding);
pResponse->setCacheableFile(precompressed, request);
return;
}
#endif

// return requested file
pResponse->setCacheableFile(filePath, request);
}
Expand Down
1 change: 1 addition & 0 deletions src/cpp/core/include/core/http/Message.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class FilePath;
namespace http {

// encodings
extern const char * const kBrotliEncoding;
extern const char * const kGzipEncoding;
extern const char * const kDeflateEncoding;
extern const char * const kTransferEncoding;
Expand Down
16 changes: 11 additions & 5 deletions src/cpp/core/include/core/http/Response.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <boost/optional.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/make_shared.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/filtering_stream.hpp>
Expand Down Expand Up @@ -209,7 +210,8 @@ class Response : public Message
Error setBody(std::istream& is,
const Filter& filter,
std::streamsize buffSize = 128,
bool padding = false)
bool padding = false,
bool enableRuntimeCompression = true)
{
try
{
Expand All @@ -224,7 +226,7 @@ class Response : public Message
filteringStream.push(filter, buffSize);

// handle gzip
if (contentEncoding() == kGzipEncoding)
if (contentEncoding() == kGzipEncoding && enableRuntimeCompression)
#ifdef _WIN32
// never gzip on win32
removeHeader("Content-Encoding");
Expand Down Expand Up @@ -287,7 +289,8 @@ class Response : public Message
// send the file from its stream
try
{
return setBody(*pIfs, filter, buffSize, padding);
bool precompressed = boost::algorithm::ends_with(filePath.getAbsolutePath(), ".gz");
return setBody(*pIfs, filter, buffSize, padding, !precompressed);
}
catch(const std::exception& e)
{
Expand Down Expand Up @@ -320,10 +323,13 @@ class Response : public Message
}

// set content type
setContentType(filePath.getMimeContentType());
if (contentType().empty())
{
setContentType(filePath.getMimeContentType());
}

// gzip if possible
if (request.acceptsEncoding(kGzipEncoding))
if (contentEncoding().empty() && request.acceptsEncoding(kGzipEncoding))
setContentEncoding(kGzipEncoding);

Error error = setBody(filePath, filter, 128, usePadding(request, filePath));
Expand Down

0 comments on commit 3d5918d

Please sign in to comment.