This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new e37b35d79 Adds support for serving statichit content out of a 
directory (#9107)
e37b35d79 is described below

commit e37b35d79e4760d42c258a98a369c9ba827a5935
Author: Leif Hedstrom <zw...@apache.org>
AuthorDate: Thu Nov 17 08:25:52 2022 -0700

    Adds support for serving statichit content out of a directory (#9107)
    
    * Adds support for serving static files out of a directory
    
    * Change makePath to take a output container, and return string_view instead
    
    * Fixes per AMC's review
    
    * Make all clang compilers happy, maybe
---
 plugins/experimental/statichit/statichit.cc | 85 ++++++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 15 deletions(-)

diff --git a/plugins/experimental/statichit/statichit.cc 
b/plugins/experimental/statichit/statichit.cc
index 09bc68609..7b2824f55 100644
--- a/plugins/experimental/statichit/statichit.cc
+++ b/plugins/experimental/statichit/statichit.cc
@@ -33,6 +33,7 @@
 #include <sstream>
 
 #include <string>
+#include <filesystem>
 #include <getopt.h>
 
 #include <netinet/in.h>
@@ -62,21 +63,74 @@ static int StaticHitInterceptHook(TSCont contp, TSEvent 
event, void *edata);
 static int StaticHitTxnHook(TSCont contp, TSEvent event, void *edata);
 
 struct StaticHitConfig {
-  explicit StaticHitConfig(const std::string &filePath, const std::string 
&mimeType, bool disableExact)
-    : filePath(filePath), mimeType(mimeType), disableExact(disableExact)
+  explicit StaticHitConfig(const std::string &fileOrDir, const std::string 
&mimeType, bool exact) : mimeType(mimeType)
   {
+    std::filesystem::path base_path{fileOrDir};
+
+    if (!base_path.is_absolute()) {
+      base_path = std::filesystem::path(TSConfigDirGet()) / base_path;
+    }
+    base_path = std::filesystem::weakly_canonical(base_path);
+
+    if (std::filesystem::is_directory(base_path)) {
+      dirPath      = base_path;
+      filePath     = "";
+      disableExact = true;
+    } else {
+      dirPath      = "";
+      filePath     = base_path;
+      disableExact = exact;
+    }
   }
 
   ~StaticHitConfig() { TSContDestroy(cont); }
 
+  std::string_view
+  makePath(TSHttpTxn txnp, std::string &output) const
+  {
+    std::string_view ret = {};
+
+    if (!dirPath.empty()) {
+      TSMBuffer reqp;
+      TSMLoc hdr_loc = nullptr, url_loc = nullptr;
+
+      if (TS_SUCCESS == TSHttpTxnClientReqGet(txnp, &reqp, &hdr_loc)) {
+        if (TS_SUCCESS == TSHttpHdrUrlGet(reqp, hdr_loc, &url_loc)) {
+          int path_len = 0;
+          auto path    = TSUrlPathGet(reqp, url_loc, &path_len);
+
+          std::filesystem::path requested_file_path(
+            std::filesystem::weakly_canonical(dirPath / std::string_view{path, 
static_cast<size_t>(path_len)}));
+
+          TSHandleMLocRelease(reqp, hdr_loc, url_loc);
+          TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc);
+
+          if (std::equal(dirPath.begin(), dirPath.end(), 
requested_file_path.begin()) &&
+              std::filesystem::is_regular_file(requested_file_path)) {
+            output = requested_file_path.string();
+            ret    = {output.c_str(), output.size()};
+          }
+        } else {
+          TSHandleMLocRelease(reqp, TS_NULL_MLOC, hdr_loc);
+        }
+      }
+    } else {
+      ret = filePath;
+    }
+
+    return ret;
+  }
+
+  std::filesystem::path dirPath;
   std::string filePath;
-  std::string mimeType;
 
-  int successCode = 200;
-  int failureCode = 404;
-  int maxAge      = 0;
+  std::string mimeType = "";
+  int successCode      = 200;
+  int failureCode      = 404;
+  int maxAge           = 0;
 
   bool disableExact = false;
+  bool isDirectory  = false;
 
   TSCont cont;
 };
@@ -166,12 +220,16 @@ struct StaticHitRequest {
   std::string mimeType;
 
   static StaticHitRequest *
-  createStaticHitRequest(StaticHitConfig *tc)
+  createStaticHitRequest(StaticHitConfig *tc, TSHttpTxn txn)
   {
     StaticHitRequest *shr = new StaticHitRequest;
     std::ifstream ifstr;
+    std::string output;
+    std::string_view filePath = tc->makePath(txn, output);
 
-    ifstr.open(tc->filePath);
+    VDEBUG("Requested file path: %s", filePath.data());
+
+    ifstr.open(filePath.data());
     if (!ifstr) {
       shr->statusCode = tc->failureCode;
       return shr;
@@ -485,9 +543,9 @@ StaticHitInterceptHook(TSCont contp, TSEvent event, void 
*edata)
 static void
 StaticHitSetupIntercept(StaticHitConfig *cfg, TSHttpTxn txn)
 {
-  StaticHitRequest *req = StaticHitRequest::createStaticHitRequest(cfg);
+  StaticHitRequest *req = StaticHitRequest::createStaticHitRequest(cfg, txn);
+
   if (req == nullptr) {
-    VERROR("could not create request for %s", cfg->filePath.c_str());
     return;
   }
 
@@ -651,15 +709,12 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, 
char * /* errbuf ATS_UNUSE
   }
 
   if (filePath.size() == 0) {
-    printf("Need to specify --file-path\n");
+    VERROR("Need to specify --file-path\n");
     return TS_ERROR;
   }
 
-  if (filePath.find('/') != 0) {
-    filePath = std::string(TSConfigDirGet()) + '/' + filePath;
-  }
-
   StaticHitConfig *tc = new StaticHitConfig(filePath, mimeType, disableExact);
+
   if (maxAge > 0) {
     tc->maxAge = maxAge;
   }

Reply via email to