From dd6dbdd90a7beb9aca5836accfe83839277365b5 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 26 Oct 2024 17:56:54 +0000 Subject: [PATCH] http 304: client-option to force-disable cache an extremely brutish workaround for issues such as #110 where browsers receive an HTTP 304 and misinterpret as HTTP 200 option `--no304=1` adds the button `no304` to the controlpanel which can be enabled to force-disable caching in that browser the button is default-disabled; by specifying `--no304=2` instead of `--no304=1` the button becomes default-enabled can also always be enabled by accessing `/?setck=no304=y` --- copyparty/__main__.py | 1 + copyparty/httpcli.py | 38 +++++++++++++++++++------------------- copyparty/web/splash.html | 15 ++++++++++++--- copyparty/web/splash.js | 6 ++++++ scripts/tl.js | 5 ++++- scripts/tl.py | 5 ++++- tests/util.py | 2 +- 7 files changed, 47 insertions(+), 25 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index fb1de83c..05336755 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1461,6 +1461,7 @@ def add_ui(ap, retry): ap2.add_argument("--pb-url", metavar="URL", type=u, default="https://github.com/9001/copyparty", help="powered-by link; disable with \033[33m-np\033[0m") ap2.add_argument("--ver", action="store_true", help="show version on the control panel (incompatible with \033[33m-nb\033[0m)") ap2.add_argument("--k304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable k304 on the controlpanel (workaround for buggy reverse-proxies); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on") + ap2.add_argument("--no304", metavar="NUM", type=int, default=0, help="configure the option to enable/disable no304 on the controlpanel (workaround for buggy caching in browsers); [\033[32m0\033[0m] = hidden and default-off, [\033[32m1\033[0m] = visible and default-off, [\033[32m2\033[0m] = visible and default-on") ap2.add_argument("--md-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for README.md docs (volflag=md_sbf); see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox") ap2.add_argument("--lg-sbf", metavar="FLAGS", type=u, default="downloads forms popups scripts top-navigation-by-user-activation", help="list of capabilities to ALLOW for prologue/epilogue docs (volflag=lg_sbf)") ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)") diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index b3e60e66..ac21a84b 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -125,6 +125,8 @@ _ = (argparse, threading) NO_CACHE = {"Cache-Control": "no-cache"} +ALL_COOKIES = "k304 no304 js idxh dots cppwd cppws".split() + H_CONN_KEEPALIVE = "Connection: Keep-Alive" H_CONN_CLOSE = "Connection: Close" @@ -795,6 +797,10 @@ class HttpCli(object): k304 = self.cookies.get("k304") return k304 == "y" or (self.args.k304 == 2 and k304 != "n") + def no304(self) -> bool: + no304 = self.cookies.get("no304") + return no304 == "y" or (self.args.no304 == 2 and no304 != "n") + def _build_html_head(self, maybe_html: Any, kv: dict[str, Any]) -> None: html = str(maybe_html) is_jinja = html[:2] in "%@%" @@ -1199,9 +1205,6 @@ class HttpCli(object): if "ups" in self.uparam: return self.tx_ups() - if "k304" in self.uparam: - return self.set_k304() - if "setck" in self.uparam: return self.setck() @@ -3428,6 +3431,9 @@ class HttpCli(object): if do_send and c_lastmod: t = "sending body due to If-Modified-Since cli(%s) file(%s)" self.log(t % (c_lastmod, file_lastmod), 6) + elif not do_send and self.no304(): + do_send = True + self.log("sending body due to no304") return file_lastmod, do_send, True @@ -4460,7 +4466,9 @@ class HttpCli(object): dbwt=vs["dbwt"], url_suf=suf, k304=self.k304(), + no304=self.no304(), k304vis=self.args.k304 > 0, + no304vis=self.args.no304 > 0, ver=S_VERSION if self.args.ver else "", chpw=self.args.chpw and self.uname != "*", ahttps="" if self.is_https else "https://" + self.host + self.req, @@ -4468,29 +4476,21 @@ class HttpCli(object): self.reply(html.encode("utf-8")) return True - def set_k304(self) -> bool: - v = self.uparam["k304"].lower() - if v in "yn": - dur = 86400 * 299 - else: - dur = 0 - v = "x" - - ck = gencookie("k304", v, self.args.R, False, dur) - self.out_headerlist.append(("Set-Cookie", ck)) - self.redirect("", "?h#cc") - return True - def setck(self) -> bool: k, v = self.uparam["setck"].split("=", 1) - t = 0 if v == "" else 86400 * 299 + t = 0 if v in ("", "x") else 86400 * 299 ck = gencookie(k, v, self.args.R, False, t) self.out_headerlist.append(("Set-Cookie", ck)) - self.reply(b"o7\n") + if "cc" in self.ouparam: + self.redirect("", "?h#cc") + else: + self.reply(b"o7\n") return True def set_cfg_reset(self) -> bool: - for k in ("k304", "js", "idxh", "dots", "cppwd", "cppws"): + for k in ALL_COOKIES: + if k not in self.cookies: + continue cookie = gencookie(k, "x", self.args.R, False) self.out_headerlist.append(("Set-Cookie", cookie)) diff --git a/copyparty/web/splash.html b/copyparty/web/splash.html index 9a5701c3..d9cd7a39 100644 --- a/copyparty/web/splash.html +++ b/copyparty/web/splash.html @@ -129,11 +129,20 @@ {% if k304 or k304vis %} {% if k304 %} -
  • disable k304 (currently enabled) +
  • disable k304 (currently enabled) {%- else %} -
  • enable k304 (currently disabled) +
  • enable k304 (currently disabled) {% endif %} -
    enabling this will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general
  • +
    enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general
    + {% endif %} + + {% if no304 or no304vis %} + {% if no304 %} +
  • disable no304 (currently enabled) + {%- else %} +
  • enable no304 (currently disabled) + {% endif %} +
  • {% endif %}
  • reset client settings
  • diff --git a/copyparty/web/splash.js b/copyparty/web/splash.js index 64b79805..ebeed1bd 100644 --- a/copyparty/web/splash.js +++ b/copyparty/web/splash.js @@ -34,6 +34,9 @@ var Ls = { "ta2": "gjenta for å bekrefte nytt passord:", "ta3": "fant en skrivefeil; vennligst prøv igjen", "aa1": "innkommende:", + "ab1": "skru av no304", + "ac1": "skru på no304", + "ad1": "no304 stopper all bruk av cache. Hvis ikke k304 var nok, prøv denne. Vil mangedoble dataforbruk!", }, "eng": { "d2": "shows the state of all active threads", @@ -80,6 +83,9 @@ var Ls = { "ta2": "重复以确认新密码:", "ta3": "发现拼写错误;请重试", "aa1": "正在接收的文件:", //m + "ab1": "关闭 k304", + "ac1": "开启 k304", + "ad1": "启用 no304 将禁用所有缓存;如果 k304 不够,可以尝试此选项。这将消耗大量的网络流量!", //m } }; diff --git a/scripts/tl.js b/scripts/tl.js index 05b98a81..aa1f5bd1 100644 --- a/scripts/tl.js +++ b/scripts/tl.js @@ -54,7 +54,7 @@ var tl_cpanel = { "cc1": "other stuff:", "h1": "disable k304", // TLNote: "j1" explains what k304 is "i1": "enable k304", - "j1": "enabling this will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general", + "j1": "enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general", "k1": "reset client settings", "l1": "login for more:", "m1": "welcome back,", // TLNote: "welcome back, USERNAME" @@ -76,6 +76,9 @@ var tl_cpanel = { "ta2": "repeat to confirm new password:", "ta3": "found a typo; please try again", "aa1": "incoming files:", + "ab1": "disable no304", + "ac1": "enable no304", + "ad1": "enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!", }, }; diff --git a/scripts/tl.py b/scripts/tl.py index 01992a5b..2499fc62 100755 --- a/scripts/tl.py +++ b/scripts/tl.py @@ -89,7 +89,7 @@ var tl_cpanel = {{ "cc1": "other stuff:", "h1": "disable k304", // TLNote: "j1" explains what k304 is "i1": "enable k304", - "j1": "enabling this will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general", + "j1": "enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), but it will also make things slower in general", "k1": "reset client settings", "l1": "login for more:", "m1": "welcome back,", // TLNote: "welcome back, USERNAME" @@ -111,6 +111,9 @@ var tl_cpanel = {{ "ta2": "repeat to confirm new password:", "ta3": "found a typo; please try again", "aa1": "incoming files:", + "ab1": "disable no304", + "ac1": "enable no304", + "ad1": "enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!", }}, }}; diff --git a/tests/util.py b/tests/util.py index e0421462..17d80f54 100644 --- a/tests/util.py +++ b/tests/util.py @@ -137,7 +137,7 @@ class Cfg(Namespace): ex = "au_vol mtab_age reg_cap s_thead s_tbody th_convt" ka.update(**{k: 9 for k in ex.split()}) - ex = "db_act k304 loris re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo" + ex = "db_act k304 loris no304 re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo" ka.update(**{k: 0 for k in ex.split()}) ex = "ah_alg bname chpw_db doctitle df exit favico idp_h_usr ipa html_head lg_sbf log_fk md_sbf name og_desc og_site og_th og_title og_title_a og_title_v og_title_i shr tcolor textfiles unlist vname xff_src R RS SR"