less todo (last-modified / HTTP 304)

This commit is contained in:
ed 2019-06-18 20:23:46 +00:00
parent 5b1e73ff71
commit d59ad1b119
3 changed files with 58 additions and 15 deletions

View file

@ -62,9 +62,7 @@ pip install black bandit pylint flake8 # vscode tooling
roughly sorted by priority
* http error handling (conn.status or handler-retval)
* look into android thumbnail cache file format
* last-modified header
* support pillow-simd
* figure out the deal with pixel3a not being connectable as hotspot
* pixel3a having unpredictable 3sec latency in general :||||

View file

@ -8,6 +8,7 @@ __copyright__ = 2019
__license__ = "MIT"
__url__ = "https://github.com/9001/copyparty/"
import locale
import argparse
from textwrap import dedent
@ -35,6 +36,18 @@ class RiceFormatter(argparse.HelpFormatter):
def main():
for x in [
"en_US.UTF-8",
"English_United States.UTF8",
"English_United States.1252",
]:
try:
locale.setlocale(locale.LC_ALL, x)
print("Locale:", x)
break
except:
continue
ap = argparse.ArgumentParser(
formatter_class=RiceFormatter,
prog="copyparty",

View file

@ -6,6 +6,7 @@ import os
import stat
import time
from datetime import datetime
import calendar
import mimetypes
import cgi
@ -45,7 +46,7 @@ class HttpCli(object):
return False
try:
mode, self.req, _ = headerlines[0].split(" ")
self.mode, self.req, _ = headerlines[0].split(" ")
except:
raise Pebkac("bad headers:\n" + "\n".join(headerlines))
@ -99,12 +100,12 @@ class HttpCli(object):
self.vpath = unquotep(vpath)
try:
if mode == "GET":
if self.mode in ["GET", "HEAD"]:
return self.handle_get()
elif mode == "POST":
elif self.mode == "POST":
return self.handle_post()
else:
raise Pebkac('invalid HTTP mode "{0}"'.format(mode))
raise Pebkac('invalid HTTP mode "{0}"'.format(self.mode))
except Pebkac as ex:
try:
@ -114,6 +115,8 @@ class HttpCli(object):
return False
return True
def reply(self, body, status="200 OK", mime="text/html", headers=[]):
# TODO something to reply with user-supplied values safely
response = [
@ -139,7 +142,7 @@ class HttpCli(object):
self.reply(b"<pre>" + body.encode("utf-8"), *list(args), **kwargs)
def handle_get(self):
self.log("GET " + self.req)
self.log("{:4} {}".format(self.mode, self.req))
# "embedded" resources
if self.vpath.startswith(".cpr"):
@ -312,15 +315,41 @@ class HttpCli(object):
self.parser.drop()
def tx_file(self, path):
sz = os.path.getsize(fsenc(path))
mime = mimetypes.guess_type(path)[0]
header = "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: {}\r\nContent-Length: {}\r\n\r\n".format(
mime, sz
).encode(
"utf-8"
)
file_ts = os.path.getmtime(fsenc(path))
file_dt = datetime.utcfromtimestamp(file_ts)
file_lastmod = file_dt.strftime("%a, %b %d %Y %H:%M:%S GMT")
self.s.send(header)
do_send = True
if "if-modified-since" in self.headers:
cli_lastmod = self.headers["if-modified-since"]
try:
cli_dt = time.strptime(cli_lastmod, "%a, %b %d %Y %H:%M:%S GMT")
cli_ts = calendar.timegm(cli_dt)
do_send = int(file_ts) > int(cli_ts)
except:
self.log("bad lastmod format: {}".format(cli_lastmod))
do_send = file_lastmod != cli_lastmod
status = "200 OK"
if not do_send:
status = "304 Not Modified"
headers = [
"HTTP/1.1 " + status,
"Connection: Keep-Alive",
"Content-Type: " + mimetypes.guess_type(path)[0],
"Content-Length: " + str(os.path.getsize(fsenc(path))),
"Last-Modified: " + file_lastmod,
]
headers = "\r\n".join(headers).encode("utf-8") + b"\r\n\r\n"
self.s.send(headers)
logmsg = "{:4} {} {}".format("", self.req, status)
if self.mode == "HEAD" or not do_send:
self.log(logmsg)
return True
with open(fsenc(path), "rb") as f:
while True:
@ -333,6 +362,9 @@ class HttpCli(object):
except ConnectionResetError:
return False
self.log(logmsg)
return True
def tx_mounts(self):
html = self.conn.tpl_mounts.render(this=self)
self.reply(html.encode("utf-8"))