copyparty 1.16.7__py3-none-any.whl → 1.16.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
copyparty/__version__.py CHANGED
@@ -1,8 +1,8 @@
1
1
  # coding: utf-8
2
2
 
3
- VERSION = (1, 16, 7)
3
+ VERSION = (1, 16, 8)
4
4
  CODENAME = "COPYparty"
5
- BUILD_DT = (2024, 12, 23)
5
+ BUILD_DT = (2025, 1, 11)
6
6
 
7
7
  S_VERSION = ".".join(map(str, VERSION))
8
8
  S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
copyparty/httpcli.py CHANGED
@@ -1889,7 +1889,7 @@ class HttpCli(object):
1889
1889
  return self.handle_stash(False)
1890
1890
 
1891
1891
  if "save" in opt:
1892
- post_sz, _, _, _, path, _ = self.dump_to_file(False)
1892
+ post_sz, _, _, _, _, path, _ = self.dump_to_file(False)
1893
1893
  self.log("urlform: %d bytes, %r" % (post_sz, path))
1894
1894
  elif "print" in opt:
1895
1895
  reader, _ = self.get_body_reader()
@@ -1970,11 +1970,11 @@ class HttpCli(object):
1970
1970
  else:
1971
1971
  return read_socket(self.sr, bufsz, remains), remains
1972
1972
 
1973
- def dump_to_file(self, is_put ) :
1974
- # post_sz, sha_hex, sha_b64, remains, path, url
1973
+ def dump_to_file(self, is_put ) :
1974
+ # post_sz, halg, sha_hex, sha_b64, remains, path, url
1975
1975
  reader, remains = self.get_body_reader()
1976
1976
  vfs, rem = self.asrv.vfs.get(self.vpath, self.uname, False, True)
1977
- rnd, _, lifetime, xbu, xau = self.upload_flags(vfs)
1977
+ rnd, lifetime, xbu, xau = self.upload_flags(vfs)
1978
1978
  lim = vfs.get_dbv(rem)[0].lim
1979
1979
  fdir = vfs.canonical(rem)
1980
1980
  if lim:
@@ -2122,12 +2122,14 @@ class HttpCli(object):
2122
2122
  # small toctou, but better than clobbering a hardlink
2123
2123
  wunlink(self.log, path, vfs.flags)
2124
2124
 
2125
+ halg = "sha512"
2125
2126
  hasher = None
2126
2127
  copier = hashcopy
2127
2128
  if "ck" in self.ouparam or "ck" in self.headers:
2128
- zs = self.ouparam.get("ck") or self.headers.get("ck") or ""
2129
+ halg = zs = self.ouparam.get("ck") or self.headers.get("ck") or ""
2129
2130
  if not zs or zs == "no":
2130
2131
  copier = justcopy
2132
+ halg = ""
2131
2133
  elif zs == "md5":
2132
2134
  hasher = hashlib.md5(**USED4SEC)
2133
2135
  elif zs == "sha1":
@@ -2161,7 +2163,7 @@ class HttpCli(object):
2161
2163
  raise
2162
2164
 
2163
2165
  if self.args.nw:
2164
- return post_sz, sha_hex, sha_b64, remains, path, ""
2166
+ return post_sz, halg, sha_hex, sha_b64, remains, path, ""
2165
2167
 
2166
2168
  at = mt = time.time() - lifetime
2167
2169
  cli_mt = self.headers.get("x-oc-mtime")
@@ -2272,19 +2274,30 @@ class HttpCli(object):
2272
2274
  self.args.RS + vpath + vsuf,
2273
2275
  )
2274
2276
 
2275
- return post_sz, sha_hex, sha_b64, remains, path, url
2277
+ return post_sz, halg, sha_hex, sha_b64, remains, path, url
2276
2278
 
2277
2279
  def handle_stash(self, is_put ) :
2278
- post_sz, sha_hex, sha_b64, remains, path, url = self.dump_to_file(is_put)
2280
+ post_sz, halg, sha_hex, sha_b64, remains, path, url = self.dump_to_file(is_put)
2279
2281
  spd = self._spd(post_sz)
2280
2282
  t = "%s wrote %d/%d bytes to %r # %s"
2281
2283
  self.log(t % (spd, post_sz, remains, path, sha_b64[:28])) # 21
2282
2284
 
2283
- ac = self.uparam.get(
2284
- "want", self.headers.get("accept", "").lower().split(";")[-1]
2285
- )
2285
+ mime = "text/plain; charset=utf-8"
2286
+ ac = self.uparam.get("want") or self.headers.get("accept") or ""
2287
+ if ac:
2288
+ ac = ac.split(";", 1)[0].lower()
2289
+ if ac == "application/json":
2290
+ ac = "json"
2286
2291
  if ac == "url":
2287
2292
  t = url
2293
+ elif ac == "json" or "j" in self.uparam:
2294
+ jmsg = {"fileurl": url, "filesz": post_sz}
2295
+ if halg:
2296
+ jmsg[halg] = sha_hex[:56]
2297
+ jmsg["sha_b64"] = sha_b64
2298
+
2299
+ mime = "application/json"
2300
+ t = json.dumps(jmsg, indent=2, sort_keys=True)
2288
2301
  else:
2289
2302
  t = "{}\n{}\n{}\n{}\n".format(post_sz, sha_b64, sha_hex[:56], url)
2290
2303
 
@@ -2294,7 +2307,7 @@ class HttpCli(object):
2294
2307
  h["X-OC-MTime"] = "accepted"
2295
2308
  t = "" # some webdav clients expect/prefer this
2296
2309
 
2297
- self.reply(t.encode("utf-8"), 201, headers=h)
2310
+ self.reply(t.encode("utf-8", "replace"), 201, mime=mime, headers=h)
2298
2311
  return True
2299
2312
 
2300
2313
  def bakflip(
@@ -2967,7 +2980,7 @@ class HttpCli(object):
2967
2980
  self.redirect(vpath, "?edit")
2968
2981
  return True
2969
2982
 
2970
- def upload_flags(self, vfs ) :
2983
+ def upload_flags(self, vfs ) :
2971
2984
  if self.args.nw:
2972
2985
  rnd = 0
2973
2986
  else:
@@ -2975,10 +2988,6 @@ class HttpCli(object):
2975
2988
  if vfs.flags.get("rand"): # force-enable
2976
2989
  rnd = max(rnd, vfs.flags["nrand"])
2977
2990
 
2978
- ac = self.uparam.get(
2979
- "want", self.headers.get("accept", "").lower().split(";")[-1]
2980
- )
2981
- want_url = ac == "url"
2982
2991
  zs = self.uparam.get("life", self.headers.get("life", ""))
2983
2992
  if zs:
2984
2993
  vlife = vfs.flags.get("lifetime") or 0
@@ -2988,7 +2997,6 @@ class HttpCli(object):
2988
2997
 
2989
2998
  return (
2990
2999
  rnd,
2991
- want_url,
2992
3000
  lifetime,
2993
3001
  vfs.flags.get("xbu") or [],
2994
3002
  vfs.flags.get("xau") or [],
@@ -3041,7 +3049,14 @@ class HttpCli(object):
3041
3049
  if not nullwrite:
3042
3050
  bos.makedirs(fdir_base)
3043
3051
 
3044
- rnd, want_url, lifetime, xbu, xau = self.upload_flags(vfs)
3052
+ rnd, lifetime, xbu, xau = self.upload_flags(vfs)
3053
+ zs = self.uparam.get("want") or self.headers.get("accept") or ""
3054
+ if zs:
3055
+ zs = zs.split(";", 1)[0].lower()
3056
+ if zs == "application/json":
3057
+ zs = "json"
3058
+ want_url = zs == "url"
3059
+ want_json = zs == "json" or "j" in self.uparam
3045
3060
 
3046
3061
  files = []
3047
3062
  # sz, sha_hex, sha_b64, p_file, fname, abspath
@@ -3363,7 +3378,9 @@ class HttpCli(object):
3363
3378
  msg += "\n" + errmsg
3364
3379
 
3365
3380
  self.reply(msg.encode("utf-8", "replace"), status=sc)
3366
- elif "j" in self.uparam:
3381
+ elif want_json:
3382
+ if len(jmsg["files"]) == 1:
3383
+ jmsg["fileurl"] = jmsg["files"][0]["url"]
3367
3384
  jtxt = json.dumps(jmsg, indent=2, sort_keys=True).encode("utf-8", "replace")
3368
3385
  self.reply(jtxt, mime="application/json", status=sc)
3369
3386
  else:
@@ -4531,12 +4548,12 @@ class HttpCli(object):
4531
4548
  else self.conn.hsrv.nm.map(self.ip) or host
4532
4549
  )
4533
4550
  # safer than html_escape/quotep since this avoids both XSS and shell-stuff
4534
- pw = re.sub(r"[<>&$?`\"']", "_", self.pw or "pw")
4551
+ pw = re.sub(r"[<>&$?`\"']", "_", self.pw or "hunter2")
4535
4552
  vp = re.sub(r"[<>&$?`\"']", "_", self.uparam["hc"] or "").lstrip("/")
4536
4553
  pw = pw.replace(" ", "%20")
4537
4554
  vp = vp.replace(" ", "%20")
4538
4555
  if pw in self.asrv.sesa:
4539
- pw = "pwd"
4556
+ pw = "hunter2"
4540
4557
 
4541
4558
  html = self.j2s(
4542
4559
  "svcs",
copyparty/up2k.py CHANGED
@@ -851,7 +851,7 @@ class Up2k(object):
851
851
  self.iacct = self.asrv.iacct
852
852
  self.grps = self.asrv.grps
853
853
 
854
- have_e2d = self.args.idp_h_usr
854
+ have_e2d = self.args.idp_h_usr or self.args.chpw or self.args.shr
855
855
  vols = list(all_vols.values())
856
856
  t0 = time.time()
857
857
 
@@ -1112,6 +1112,7 @@ class Up2k(object):
1112
1112
  reg = {}
1113
1113
  drp = None
1114
1114
  emptylist = []
1115
+ dotpart = "." if self.args.dotpart else ""
1115
1116
  snap = os.path.join(histpath, "up2k.snap")
1116
1117
  if bos.path.exists(snap):
1117
1118
  with gzip.GzipFile(snap, "rb") as f:
@@ -1124,6 +1125,8 @@ class Up2k(object):
1124
1125
  except:
1125
1126
  pass
1126
1127
 
1128
+ reg = reg2 # diff-golf
1129
+
1127
1130
  if reg2 and "dwrk" not in reg2[next(iter(reg2))]:
1128
1131
  for job in reg2.values():
1129
1132
  job["dwrk"] = job["wark"]
@@ -1131,7 +1134,8 @@ class Up2k(object):
1131
1134
  rm = []
1132
1135
  for k, job in reg2.items():
1133
1136
  job["ptop"] = ptop
1134
- if "done" in job:
1137
+ is_done = "done" in job
1138
+ if is_done:
1135
1139
  job["need"] = job["hash"] = emptylist
1136
1140
  else:
1137
1141
  if "need" not in job:
@@ -1139,10 +1143,13 @@ class Up2k(object):
1139
1143
  if "hash" not in job:
1140
1144
  job["hash"] = []
1141
1145
 
1142
- fp = djoin(ptop, job["prel"], job["name"])
1146
+ if is_done:
1147
+ fp = djoin(ptop, job["prel"], job["name"])
1148
+ else:
1149
+ fp = djoin(ptop, job["prel"], dotpart + job["name"] + ".PARTIAL")
1150
+
1143
1151
  if bos.path.exists(fp):
1144
- reg[k] = job
1145
- if "done" in job:
1152
+ if is_done:
1146
1153
  continue
1147
1154
  job["poke"] = time.time()
1148
1155
  job["busy"] = {}
@@ -1150,11 +1157,18 @@ class Up2k(object):
1150
1157
  self.log("ign deleted file in snap: %r" % (fp,))
1151
1158
  if not n4g:
1152
1159
  rm.append(k)
1153
- continue
1154
1160
 
1155
1161
  for x in rm:
1156
1162
  del reg2[x]
1157
1163
 
1164
+ # optimize pre-1.15.4 entries
1165
+ if next((x for x in reg.values() if "done" in x and "poke" in x), None):
1166
+ zsl = "host tnam busy sprs poke t0c".split()
1167
+ for job in reg.values():
1168
+ if "done" in job:
1169
+ for k in zsl:
1170
+ job.pop(k, None)
1171
+
1158
1172
  if drp is None:
1159
1173
  drp = [k for k, v in reg.items() if not v["need"]]
1160
1174
  else:
@@ -2989,7 +3003,7 @@ class Up2k(object):
2989
3003
  if wark in reg:
2990
3004
  del reg[wark]
2991
3005
  job["hash"] = job["need"] = []
2992
- job["done"] = True
3006
+ job["done"] = 1
2993
3007
  job["busy"] = {}
2994
3008
 
2995
3009
  if lost:
Binary file
copyparty/web/svcs.html CHANGED
@@ -9,7 +9,7 @@
9
9
  <meta name="theme-color" content="#{{ tcolor }}">
10
10
  <link rel="stylesheet" media="screen" href="{{ r }}/.cpr/splash.css?_={{ ts }}">
11
11
  <link rel="stylesheet" media="screen" href="{{ r }}/.cpr/ui.css?_={{ ts }}">
12
- <style>ul{padding-left:1.3em}li{margin:.4em 0}</style>
12
+ <style>ul{padding-left:1.3em}li{margin:.4em 0}.txa{float:right;margin:0 0 0 1em}</style>
13
13
  {{ html_head }}
14
14
  </head>
15
15
 
@@ -31,15 +31,22 @@
31
31
  <br />
32
32
  <span class="os win lin mac">placeholders:</span>
33
33
  <span class="os win">
34
- {% if accs %}<code><b>{{ pw }}</b></code>=password, {% endif %}<code><b>W:</b></code>=mountpoint
34
+ {% if accs %}<code><b id="pw0">{{ pw }}</b></code>=password, {% endif %}<code><b>W:</b></code>=mountpoint
35
35
  </span>
36
36
  <span class="os lin mac">
37
- {% if accs %}<code><b>{{ pw }}</b></code>=password, {% endif %}<code><b>mp</b></code>=mountpoint
37
+ {% if accs %}<code><b id="pw0">{{ pw }}</b></code>=password, {% endif %}<code><b>mp</b></code>=mountpoint
38
38
  </span>
39
+ <a href="#" id="setpw">use real password</a>
39
40
  </p>
40
41
 
41
42
 
42
43
 
44
+ {% if args.idp_h_usr %}
45
+ <p style="line-height:2em"><b>WARNING:</b> this server is using IdP-based authentication, so this stuff may not work as advertised. Depending on server config, these commands can probably only be used to access areas which don't require authentication, unless you auth using any non-IdP accounts defined in the copyparty config. Please see <a href="https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients">the IdP docs</a></p>
46
+ {% endif %}
47
+
48
+
49
+
43
50
  {% if not args.no_dav %}
44
51
  <h1>WebDAV</h1>
45
52
 
@@ -229,6 +236,60 @@
229
236
 
230
237
 
231
238
 
239
+ <div class="os win">
240
+ <h1>ShareX</h1>
241
+
242
+ <p>to upload screenshots using ShareX <a href="https://github.com/ShareX/ShareX/releases/tag/v12.4.1">v12</a> or <a href="https://getsharex.com/">v15+</a>, save this as <code>copyparty.sxcu</code> and run it:</p>
243
+
244
+ <pre class="dl" name="copyparty.sxcu">
245
+ { "Name": "copyparty",
246
+ "RequestURL": "http{{ s }}://{{ ep }}/{{ rvp }}",
247
+ "Headers": {
248
+ {% if accs %}"pw": "<b>{{ pw }}</b>",{% endif %}
249
+ "accept": "url"
250
+ },
251
+ "DestinationType": "ImageUploader, TextUploader, FileUploader",
252
+ "FileFormName": "f" }
253
+ </pre>
254
+ </div>
255
+
256
+
257
+
258
+ <div class="os mac">
259
+ <h1>ishare</h1>
260
+
261
+ <p>to upload screenshots using <a href="https://isharemac.app/">ishare</a>, save this as <code>copyparty.iscu</code> and run it:</p>
262
+
263
+ <pre class="dl" name="copyparty.iscu">
264
+ { "Name": "copyparty",
265
+ "RequestURL": "http{{ s }}://{{ ep }}/{{ rvp }}",
266
+ "Headers": {
267
+ {% if accs %}"pw": "<b>{{ pw }}</b>",{% endif %}
268
+ "accept": "json"
269
+ },
270
+ "ResponseURL": "{{ '{{fileurl}}' }}",
271
+ "FileFormName": "f" }
272
+ </pre>
273
+ </div>
274
+
275
+
276
+
277
+ <div class="os lin">
278
+ <h1>flameshot</h1>
279
+
280
+ <p>to upload screenshots using <a href="https://flameshot.org/">flameshot</a>, save this as <code>flameshot.sh</code> and run it:</p>
281
+
282
+ <pre class="dl" name="flameshot.sh">
283
+ #!/bin/bash
284
+ pw="<b>{{ pw }}</b>"
285
+ url="http{{ s }}://{{ ep }}/{{ rvp }}"
286
+ filename="$(date +%Y-%m%d-%H%M%S).png"
287
+ flameshot gui -s -r | curl -sT- "$url$filename?want=url&pw=$pw" | xsel -ib
288
+ </pre>
289
+ </div>
290
+
291
+
292
+
232
293
  </div>
233
294
  <a href="#" id="repl">π</a>
234
295
  <script>
copyparty/web/svcs.js.gz CHANGED
Binary file
copyparty/web/ui.css.gz CHANGED
Binary file
copyparty/web/up2k.js.gz CHANGED
Binary file
copyparty/web/util.js.gz CHANGED
Binary file
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: copyparty
3
- Version: 1.16.7
3
+ Version: 1.16.8
4
4
  Summary: Portable file server with accelerated resumable uploads, deduplication, WebDAV, FTP, zeroconf, media indexer, video thumbnails, audio transcoding, and write-only folders
5
5
  Author-email: ed <copyparty@ocv.me>
6
6
  License: MIT
@@ -147,6 +147,7 @@ turn almost any device into a file server with resumable uploads/downloads using
147
147
  * [listen on port 80 and 443](#listen-on-port-80-and-443) - become a *real* webserver
148
148
  * [reverse-proxy](#reverse-proxy) - running copyparty next to other websites
149
149
  * [real-ip](#real-ip) - teaching copyparty how to see client IPs
150
+ * [reverse-proxy performance](#reverse-proxy-performance)
150
151
  * [prometheus](#prometheus) - metrics/stats can be enabled
151
152
  * [other extremely specific features](#other-extremely-specific-features) - you'll never find a use for these
152
153
  * [custom mimetypes](#custom-mimetypes) - change the association of a file extension
@@ -195,6 +196,7 @@ just run **[copyparty-sfx.py](https://github.com/9001/copyparty/releases/latest/
195
196
  * or if you cannot install python, you can use [copyparty.exe](#copypartyexe) instead
196
197
  * or install [on arch](#arch-package) ╱ [on NixOS](#nixos-module) ╱ [through nix](#nix-package)
197
198
  * or if you are on android, [install copyparty in termux](#install-on-android)
199
+ * or maybe you have a [synology nas / dsm](./docs/synology-dsm.md)
198
200
  * or if your computer is messed up and nothing else works, [try the pyz](#zipapp)
199
201
  * or if you prefer to [use docker](./scripts/docker/) 🐋 you can do that too
200
202
  * docker has all deps built-in, so skip this step:
@@ -701,7 +703,7 @@ dragdrop is the recommended way, but you may also:
701
703
 
702
704
  * select some files (not folders) in your file explorer and press CTRL-V inside the browser window
703
705
  * use the [command-line uploader](https://github.com/9001/copyparty/tree/hovudstraum/bin#u2cpy)
704
- * upload using [curl or sharex](#client-examples)
706
+ * upload using [curl, sharex, ishare, ...](#client-examples)
705
707
 
706
708
  when uploading files through dragdrop or CTRL-V, this initiates an upload using `up2k`; there are two browser-based uploaders available:
707
709
  * `[🎈] bup`, the basic uploader, supports almost every browser since netscape 4.0
@@ -1159,6 +1161,8 @@ on macos, connect from finder:
1159
1161
 
1160
1162
  in order to grant full write-access to webdav clients, the volflag `daw` must be set and the account must also have delete-access (otherwise the client won't be allowed to replace the contents of existing files, which is how webdav works)
1161
1163
 
1164
+ > note: if you have enabled [IdP authentication](#identity-providers) then that may cause issues for some/most webdav clients; see [the webdav section in the IdP docs](https://github.com/9001/copyparty/blob/hovudstraum/docs/idp.md#connecting-webdav-clients)
1165
+
1162
1166
 
1163
1167
  ### connecting to webdav from windows
1164
1168
 
@@ -1724,10 +1728,16 @@ some reverse proxies (such as [Caddy](https://caddyserver.com/)) can automatical
1724
1728
 
1725
1729
  for improved security (and a 10% performance boost) consider listening on a unix-socket with `-i unix:770:www:/tmp/party.sock` (permission `770` means only members of group `www` can access it)
1726
1730
 
1727
- example webserver configs:
1731
+ example webserver / reverse-proxy configs:
1728
1732
 
1729
- * [nginx config](contrib/nginx/copyparty.conf) -- entire domain/subdomain
1730
- * [apache2 config](contrib/apache/copyparty.conf) -- location-based
1733
+ * [apache config](contrib/apache/copyparty.conf)
1734
+ * caddy uds: `caddy reverse-proxy --from :8080 --to unix///dev/shm/party.sock`
1735
+ * caddy tcp: `caddy reverse-proxy --from :8081 --to http://127.0.0.1:3923`
1736
+ * [haproxy config](contrib/haproxy/copyparty.conf)
1737
+ * [lighttpd subdomain](contrib/lighttpd/subdomain.conf) -- entire domain/subdomain
1738
+ * [lighttpd subpath](contrib/lighttpd/subpath.conf) -- location-based (not optimal, but in case you need it)
1739
+ * [nginx config](contrib/nginx/copyparty.conf) -- recommended
1740
+ * [traefik config](contrib/traefik/copyparty.yaml)
1731
1741
 
1732
1742
 
1733
1743
  ### real-ip
@@ -1739,6 +1749,38 @@ if you (and maybe everybody else) keep getting a message that says `thank you fo
1739
1749
  for most common setups, there should be a helpful message in the server-log explaining what to do, but see [docs/xff.md](docs/xff.md) if you want to learn more, including a quick hack to **just make it work** (which is **not** recommended, but hey...)
1740
1750
 
1741
1751
 
1752
+ ### reverse-proxy performance
1753
+
1754
+ most reverse-proxies support connecting to copyparty either using uds/unix-sockets (`/dev/shm/party.sock`, faster/recommended) or using tcp (`127.0.0.1`)
1755
+
1756
+ with copyparty listening on a uds / unix-socket / unix-domain-socket and the reverse-proxy connecting to that:
1757
+
1758
+ | index.html | upload | download | software |
1759
+ | ------------ | ----------- | ----------- | -------- |
1760
+ | 28'900 req/s | 6'900 MiB/s | 7'400 MiB/s | no-proxy |
1761
+ | 18'750 req/s | 3'500 MiB/s | 2'370 MiB/s | haproxy |
1762
+ | 9'900 req/s | 3'750 MiB/s | 2'200 MiB/s | caddy |
1763
+ | 18'700 req/s | 2'200 MiB/s | 1'570 MiB/s | nginx |
1764
+ | 9'700 req/s | 1'750 MiB/s | 1'830 MiB/s | apache |
1765
+ | 9'900 req/s | 1'300 MiB/s | 1'470 MiB/s | lighttpd |
1766
+
1767
+ when connecting the reverse-proxy to `127.0.0.1` instead (the basic and/or old-fasioned way), speeds are a bit worse:
1768
+
1769
+ | index.html | upload | download | software |
1770
+ | ------------ | ----------- | ----------- | -------- |
1771
+ | 21'200 req/s | 5'700 MiB/s | 6'700 MiB/s | no-proxy |
1772
+ | 14'500 req/s | 1'700 MiB/s | 2'170 MiB/s | haproxy |
1773
+ | 11'100 req/s | 2'750 MiB/s | 2'000 MiB/s | traefik |
1774
+ | 8'400 req/s | 2'300 MiB/s | 1'950 MiB/s | caddy |
1775
+ | 13'400 req/s | 1'100 MiB/s | 1'480 MiB/s | nginx |
1776
+ | 8'400 req/s | 1'000 MiB/s | 1'000 MiB/s | apache |
1777
+ | 6'500 req/s | 1'270 MiB/s | 1'500 MiB/s | lighttpd |
1778
+
1779
+ in summary, `haproxy > caddy > traefik > nginx > apache > lighttpd`, and use uds when possible (traefik does not support it yet)
1780
+
1781
+ * if these results are bullshit because my config exampels are bad, please submit corrections!
1782
+
1783
+
1742
1784
  ## prometheus
1743
1785
 
1744
1786
  metrics/stats can be enabled at URL `/.cpr/metrics` for grafana / prometheus / etc (openmetrics 1.0.0)
@@ -2052,7 +2094,8 @@ interact with copyparty using non-browser clients
2052
2094
  * can be downloaded from copyparty: controlpanel -> connect -> [partyfuse.py](http://127.0.0.1:3923/.cpr/a/partyfuse.py)
2053
2095
  * [rclone](https://rclone.org/) as client can give ~5x performance, see [./docs/rclone.md](docs/rclone.md)
2054
2096
 
2055
- * sharex (screenshot utility): see [./contrib/sharex.sxcu](contrib/#sharexsxcu)
2097
+ * sharex (screenshot utility): see [./contrib/sharex.sxcu](./contrib/#sharexsxcu)
2098
+ * and for screenshots on macos, see [./contrib/ishare.iscu](./contrib/#ishareiscu)
2056
2099
  * and for screenshots on linux, see [./contrib/flameshot.sh](./contrib/flameshot.sh)
2057
2100
 
2058
2101
  * contextlet (web browser integration); see [contrib contextlet](contrib/#send-to-cppcontextletjson)
@@ -1,6 +1,6 @@
1
1
  copyparty/__init__.py,sha256=VR6ZZhB9IxaK5TDXDTBM_OIP5ydkrdbaEnstktLM__s,2649
2
2
  copyparty/__main__.py,sha256=acjihZUEvEwFp6d6BnT35oFqminMZBruDUfVU76YijA,113564
3
- copyparty/__version__.py,sha256=1Wa9fHXGyIQdk3lnare95TArCCnFp0OA4JizO5IAN20,252
3
+ copyparty/__version__.py,sha256=O9UOPs_HcmEufkcuaes_ZA7U8kK_sVtXCGmVqE69BnA,251
4
4
  copyparty/authsrv.py,sha256=h1OhdMR_hrqZA9NH2pMRZ-Axc_GSoUajioCZhimVVsQ,104109
5
5
  copyparty/broker_mp.py,sha256=QdOXXvV2Xn6J0CysEqyY3GZbqxQMyWnTpnba-a5lMc0,4987
6
6
  copyparty/broker_mpw.py,sha256=PpSS4SK3pItlpfD8OwVr3QmJEPKlUgaf2nuMOozixgU,3347
@@ -11,7 +11,7 @@ copyparty/cfg.py,sha256=UUmFpFbTm750Nv9RnofS80-FTpWT37EggEtmkE1wbxE,10374
11
11
  copyparty/dxml.py,sha256=lZpg-kn-kQsXRtNY1n6fRaS-b7uXzMCyv8ovKnhZcZc,1548
12
12
  copyparty/fsutil.py,sha256=IVOFG8zBQPMQDDv7RIStSJHwHiAnVNROZS37O5k465A,4524
13
13
  copyparty/ftpd.py,sha256=T97SFS7JFtvRLbJX8C4fJSYwe13vhN3-E6emtlVmqLA,17608
14
- copyparty/httpcli.py,sha256=cgeVci6xAUUp79z982xTL27v9XcWEzC5ymbmtj3v66M,214475
14
+ copyparty/httpcli.py,sha256=jiR7zHGGyVp-ZwK-j0I2eNkwbEOYDTc7xGrGzrSb0iQ,215225
15
15
  copyparty/httpconn.py,sha256=mQSgljh0Q-jyWjF4tQLrHbRKRe9WKl19kGqsGMsJpWo,6880
16
16
  copyparty/httpsrv.py,sha256=pxH_Eh8ElBLvOEDejgpP9Bvk65HNEou-03aYIcgXhrs,18090
17
17
  copyparty/ico.py,sha256=eWSxEae4wOCfheHl-m-wchYvFRAR_97kJDb4NGaB-Z8,3561
@@ -31,7 +31,7 @@ copyparty/tftpd.py,sha256=PXgG4rTmiaU_TavSyZWD5cFphdfChs9YvNY21qfExt8,13611
31
31
  copyparty/th_cli.py,sha256=1B8el4NNs5cNyJyjOPiAdvLOX2HQXaebsHn6VLdZ_gU,4630
32
32
  copyparty/th_srv.py,sha256=uAcz-wZJQEG5KavcZDkwToONZujyoOeC4oCxxKTD5us,29575
33
33
  copyparty/u2idx.py,sha256=G6MDbD4I_sJSOwaNFZ6XLTQhnEDrB12pVKuKhzQ_leE,13676
34
- copyparty/up2k.py,sha256=Uo_-zmJ9Bv8An0ph4w6Nh1883LWAsbH_H9mrX35OrpU,174570
34
+ copyparty/up2k.py,sha256=0YPdP2UHoJr0c3QhS6EsOIUPSq2JztCD43Y3D7lN6Po,175144
35
35
  copyparty/util.py,sha256=qhNakLtygJveVbZUuPvDY7Tm1E48E67CS9XBmosu5i4,95101
36
36
  copyparty/bos/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  copyparty/bos/bos.py,sha256=Wb7eWsXJgR5AFlBR9ZOyKrLTwy-Kct9RrGiOu4Jo37Y,1622
@@ -77,14 +77,14 @@ copyparty/web/rups.js.gz,sha256=nvvcG8L-fkm7zkhjnlTGhBp_KD0j08mtHEW0sB7zy-Y,854
77
77
  copyparty/web/shares.css.gz,sha256=SdPlZCBwz9tkPkgEo5pSPDOZSI079njxEfkJ64-iW3c,547
78
78
  copyparty/web/shares.html,sha256=YctvUrKuBYu42kxVylyW2_DEHm7Ik6uHqzfzVZ4N0ac,2545
79
79
  copyparty/web/shares.js.gz,sha256=emeY2-wjkh8x1JgaW6ny5fcC7XpZzZzfE1f-sEyntQ4,940
80
- copyparty/web/splash.css.gz,sha256=VxFqPvNdZtWb0u1C_GW2yYwrHq0lqPMitft9GYcv56k,1087
80
+ copyparty/web/splash.css.gz,sha256=S8_A7JJl71xACRBYGzafeaD82OacW6Fa7oKPiNyrhAs,1087
81
81
  copyparty/web/splash.html,sha256=QEnTH9QZXFmAuyVtgqOuuHKBtIdi7uclpRqe0ZMewj4,6249
82
82
  copyparty/web/splash.js.gz,sha256=4VqNznN10-bT33IJm3VWzBEJ1s08XZyxFB1TYPUkuAo,2739
83
- copyparty/web/svcs.html,sha256=S-YiS7DF5ndsy4MZXStdpIkCqSjKA9V5kIViCUQhMvw,11557
84
- copyparty/web/svcs.js.gz,sha256=k81ZvZ3I-f4fMHKrNGGOgOlvXnCBz0mVjD-8mieoWCA,520
85
- copyparty/web/ui.css.gz,sha256=v8U-1tetZzuzTpITjq8NWj1gg3jEiYDIIE8aE0dx63k,2800
86
- copyparty/web/up2k.js.gz,sha256=CC1MM_FBfxpsjgtNWupzCdnlVNI3hBbWbNSCnOSpCTY,23460
87
- copyparty/web/util.js.gz,sha256=aXgf3U-0TL9Sc7uMQhA_sMyTXLsZCH3YDe8qLJ4hpEM,15082
83
+ copyparty/web/svcs.html,sha256=s2uMblxDpYo8l-M--KB1BAF1ZiQrWf5p4v1sDjSs1MQ,14140
84
+ copyparty/web/svcs.js.gz,sha256=rcc75HMmoc3KA7Ld2j8X9AKX_elZgwUD6Vnm2F-yj_U,805
85
+ copyparty/web/ui.css.gz,sha256=0sHIwGsL3_xH8Uu6N0Ag3bKBTjf-e_yfFbKynEZXAnk,2800
86
+ copyparty/web/up2k.js.gz,sha256=f00wmaThk1CoFYzFBG_6KLG0acq60cAn3p12tngqprk,23843
87
+ copyparty/web/util.js.gz,sha256=uCCnKWT_FeG-ShKPoj0MtXnBwtdAbyDSM9AP9KiBDjw,15098
88
88
  copyparty/web/w.hash.js.gz,sha256=l3GpSJD6mcU-1CRWkIj7PybgbjlfSr8oeO3vortIrQk,1105
89
89
  copyparty/web/a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
90
90
  copyparty/web/a/partyfuse.py,sha256=9p5Hpg_IBiSimv7j9kmPhCGpy-FLXSRUOYnLjJ5JifU,28049
@@ -109,9 +109,9 @@ copyparty/web/deps/prismd.css.gz,sha256=ObUlksQVr-OuYlTz-I4B23TeBg2QDVVGRnWBz8cV
109
109
  copyparty/web/deps/scp.woff2,sha256=w99BDU5i8MukkMEL-iW0YO9H4vFFZSPWxbkH70ytaAg,8612
110
110
  copyparty/web/deps/sha512.ac.js.gz,sha256=lFZaCLumgWxrvEuDr4bqdKHsqjX82AbVAb7_F45Yk88,7033
111
111
  copyparty/web/deps/sha512.hw.js.gz,sha256=UAed2_ocklZCnIzcSYz2h4P1ycztlCLj-ewsRTud2lU,7939
112
- copyparty-1.16.7.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
113
- copyparty-1.16.7.dist-info/METADATA,sha256=olG_plZH52nO0-2ebV8squbAOF_3h66Y8_8Bs_by6Zk,141509
114
- copyparty-1.16.7.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
115
- copyparty-1.16.7.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
116
- copyparty-1.16.7.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
117
- copyparty-1.16.7.dist-info/RECORD,,
112
+ copyparty-1.16.8.dist-info/LICENSE,sha256=gOr4h33pCsBEg9uIy9AYmb7qlocL4V9t2uPJS5wllr0,1072
113
+ copyparty-1.16.8.dist-info/METADATA,sha256=-4246pvuZxdG_MtxGM7euDMxpPVVGiXgIzBEdvlRGLk,144011
114
+ copyparty-1.16.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
115
+ copyparty-1.16.8.dist-info/entry_points.txt,sha256=4zw6a3rqASywQomiYLObjjlxybaI65LYYOTJwgKz7b0,128
116
+ copyparty-1.16.8.dist-info/top_level.txt,sha256=LnYUPsDyk-8kFgM6YJLG4h820DQekn81cObKSu9g-sI,10
117
+ copyparty-1.16.8.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5