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`
This commit is contained in:
ed 2024-10-26 17:56:54 +00:00
parent 63013cc565
commit dd6dbdd90a
7 changed files with 47 additions and 25 deletions

View file

@ -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("--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("--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("--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("--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("--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)") ap2.add_argument("--no-sb-md", action="store_true", help="don't sandbox README/PREADME.md documents (volflags: no_sb_md | sb_md)")

View file

@ -125,6 +125,8 @@ _ = (argparse, threading)
NO_CACHE = {"Cache-Control": "no-cache"} NO_CACHE = {"Cache-Control": "no-cache"}
ALL_COOKIES = "k304 no304 js idxh dots cppwd cppws".split()
H_CONN_KEEPALIVE = "Connection: Keep-Alive" H_CONN_KEEPALIVE = "Connection: Keep-Alive"
H_CONN_CLOSE = "Connection: Close" H_CONN_CLOSE = "Connection: Close"
@ -795,6 +797,10 @@ class HttpCli(object):
k304 = self.cookies.get("k304") k304 = self.cookies.get("k304")
return k304 == "y" or (self.args.k304 == 2 and k304 != "n") 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: def _build_html_head(self, maybe_html: Any, kv: dict[str, Any]) -> None:
html = str(maybe_html) html = str(maybe_html)
is_jinja = html[:2] in "%@%" is_jinja = html[:2] in "%@%"
@ -1199,9 +1205,6 @@ class HttpCli(object):
if "ups" in self.uparam: if "ups" in self.uparam:
return self.tx_ups() return self.tx_ups()
if "k304" in self.uparam:
return self.set_k304()
if "setck" in self.uparam: if "setck" in self.uparam:
return self.setck() return self.setck()
@ -3428,6 +3431,9 @@ class HttpCli(object):
if do_send and c_lastmod: if do_send and c_lastmod:
t = "sending body due to If-Modified-Since cli(%s) file(%s)" t = "sending body due to If-Modified-Since cli(%s) file(%s)"
self.log(t % (c_lastmod, file_lastmod), 6) 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 return file_lastmod, do_send, True
@ -4460,7 +4466,9 @@ class HttpCli(object):
dbwt=vs["dbwt"], dbwt=vs["dbwt"],
url_suf=suf, url_suf=suf,
k304=self.k304(), k304=self.k304(),
no304=self.no304(),
k304vis=self.args.k304 > 0, k304vis=self.args.k304 > 0,
no304vis=self.args.no304 > 0,
ver=S_VERSION if self.args.ver else "", ver=S_VERSION if self.args.ver else "",
chpw=self.args.chpw and self.uname != "*", chpw=self.args.chpw and self.uname != "*",
ahttps="" if self.is_https else "https://" + self.host + self.req, ahttps="" if self.is_https else "https://" + self.host + self.req,
@ -4468,29 +4476,21 @@ class HttpCli(object):
self.reply(html.encode("utf-8")) self.reply(html.encode("utf-8"))
return True 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: def setck(self) -> bool:
k, v = self.uparam["setck"].split("=", 1) 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) ck = gencookie(k, v, self.args.R, False, t)
self.out_headerlist.append(("Set-Cookie", ck)) self.out_headerlist.append(("Set-Cookie", ck))
if "cc" in self.ouparam:
self.redirect("", "?h#cc")
else:
self.reply(b"o7\n") self.reply(b"o7\n")
return True return True
def set_cfg_reset(self) -> bool: 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) cookie = gencookie(k, "x", self.args.R, False)
self.out_headerlist.append(("Set-Cookie", cookie)) self.out_headerlist.append(("Set-Cookie", cookie))

View file

@ -129,11 +129,20 @@
{% if k304 or k304vis %} {% if k304 or k304vis %}
{% if k304 %} {% if k304 %}
<li><a id="h" href="{{ r }}/?k304=n">disable k304</a> (currently enabled) <li><a id="h" href="{{ r }}/?cc&setck=k304=n">disable k304</a> (currently enabled)
{%- else %} {%- else %}
<li><a id="i" href="{{ r }}/?k304=y" class="r">enable k304</a> (currently disabled) <li><a id="i" href="{{ r }}/?cc&setck=k304=y" class="r">enable k304</a> (currently disabled)
{% endif %} {% endif %}
<blockquote id="j">enabling this will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), <em>but</em> it will also make things slower in general</blockquote></li> <blockquote id="j">enabling k304 will disconnect your client on every HTTP 304, which can prevent some buggy proxies from getting stuck (suddenly not loading pages), <em>but</em> it will also make things slower in general</blockquote></li>
{% endif %}
{% if no304 or no304vis %}
{% if no304 %}
<li><a id="ab" href="{{ r }}/?cc&setck=no304=n">disable no304</a> (currently enabled)
{%- else %}
<li><a id="ac" href="{{ r }}/?cc&setck=no304=y" class="r">enable no304</a> (currently disabled)
{% endif %}
<blockquote id="ad">enabling no304 will disable all caching; try this if k304 wasn't enough. This will waste a huge amount of network traffic!</blockquote></li>
{% endif %} {% endif %}
<li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li> <li><a id="k" href="{{ r }}/?reset" class="r" onclick="localStorage.clear();return true">reset client settings</a></li>

View file

@ -34,6 +34,9 @@ var Ls = {
"ta2": "gjenta for å bekrefte nytt passord:", "ta2": "gjenta for å bekrefte nytt passord:",
"ta3": "fant en skrivefeil; vennligst prøv igjen", "ta3": "fant en skrivefeil; vennligst prøv igjen",
"aa1": "innkommende:", "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": { "eng": {
"d2": "shows the state of all active threads", "d2": "shows the state of all active threads",
@ -80,6 +83,9 @@ var Ls = {
"ta2": "重复以确认新密码:", "ta2": "重复以确认新密码:",
"ta3": "发现拼写错误;请重试", "ta3": "发现拼写错误;请重试",
"aa1": "正在接收的文件:", //m "aa1": "正在接收的文件:", //m
"ab1": "关闭 k304",
"ac1": "开启 k304",
"ad1": "启用 no304 将禁用所有缓存;如果 k304 不够,可以尝试此选项。这将消耗大量的网络流量!", //m
} }
}; };

View file

@ -54,7 +54,7 @@ var tl_cpanel = {
"cc1": "other stuff:", "cc1": "other stuff:",
"h1": "disable k304", // TLNote: "j1" explains what k304 is "h1": "disable k304", // TLNote: "j1" explains what k304 is
"i1": "enable k304", "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), <em>but</em> 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), <em>but</em> it will also make things slower in general",
"k1": "reset client settings", "k1": "reset client settings",
"l1": "login for more:", "l1": "login for more:",
"m1": "welcome back,", // TLNote: "welcome back, USERNAME" "m1": "welcome back,", // TLNote: "welcome back, USERNAME"
@ -76,6 +76,9 @@ var tl_cpanel = {
"ta2": "repeat to confirm new password:", "ta2": "repeat to confirm new password:",
"ta3": "found a typo; please try again", "ta3": "found a typo; please try again",
"aa1": "incoming files:", "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!",
}, },
}; };

View file

@ -89,7 +89,7 @@ var tl_cpanel = {{
"cc1": "other stuff:", "cc1": "other stuff:",
"h1": "disable k304", // TLNote: "j1" explains what k304 is "h1": "disable k304", // TLNote: "j1" explains what k304 is
"i1": "enable k304", "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), <em>but</em> 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), <em>but</em> it will also make things slower in general",
"k1": "reset client settings", "k1": "reset client settings",
"l1": "login for more:", "l1": "login for more:",
"m1": "welcome back,", // TLNote: "welcome back, USERNAME" "m1": "welcome back,", // TLNote: "welcome back, USERNAME"
@ -111,6 +111,9 @@ var tl_cpanel = {{
"ta2": "repeat to confirm new password:", "ta2": "repeat to confirm new password:",
"ta3": "found a typo; please try again", "ta3": "found a typo; please try again",
"aa1": "incoming files:", "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!",
}}, }},
}}; }};

View file

@ -137,7 +137,7 @@ class Cfg(Namespace):
ex = "au_vol mtab_age reg_cap s_thead s_tbody th_convt" ex = "au_vol mtab_age reg_cap s_thead s_tbody th_convt"
ka.update(**{k: 9 for k in ex.split()}) 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()}) 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" 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"