commit b6de6edf9ccce43bc156e0419497a2c709063929
Author: Vetle Haflan <vetle@haflan.dev>
Date: Thu, 28 Nov 2019 20:34:20 +0100
Init with some simple Python file sharing server/client scripts
Diffstat:
A | readme.md | | | 1 | + |
A | vget.py | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | vshare.py | | | 61 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 131 insertions(+), 0 deletions(-)
diff --git a/readme.md b/readme.md
@@ -0,0 +1 @@
+Here: All sorts of useful code snippets and mini projects
diff --git a/vget.py b/vget.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python3
+
+# This script is meant as a client for 'python3 -m http.server'
+# This script either gets a given resource (flag -g) or returns autocomplete
+# suggestions based on the input argument the contents detected on the server
+#
+# To set up bash completion, run the following shell commands:
+# alias vget='/path/to/vget.py -g'
+# _vget(){ COMPREPLY=($(./vget.py ${COMP_WORDS[1]}));}
+# complete -o nospace -C _vget /path/to/vget.py
+
+import re
+import requests
+import argparse
+
+# Host aliases go here
+DEFAULT_HOST='me'
+HOST_URLS={
+ 'me': 'http://localhost:8000',
+ 'vetle': 'http://localhost:8000',
+}
+
+
+parser = argparse.ArgumentParser()
+parser.add_argument('url', type=str, nargs='?')
+parser.add_argument("-g", dest='get', action='store_true',
+ help="Actually download the resource, don't get list")
+parser.set_defaults(get_it=False)
+args = parser.parse_args()
+url = args.url
+download = args.get
+
+# TODO: Allow no arguments, and return the entire list of aliases if so
+
+# Split the URL in host and path
+# If the URL doesn't contain a path, it should be a host alias only
+if not url:
+ print(' '.join(HOST_URLS.keys()))
+ exit()
+if 'http' in url[:4]:
+ pass # in this case the url does not contain an alias
+if '/' in url:
+ alias = url.split('/')[0]
+ host = HOST_URLS[alias]
+ path = url.replace(alias, '')
+ url = host + path
+elif url in HOST_URLS:
+ alias = url
+ host = HOST_URLS[url]
+ path = '/'
+ url = host + path
+else:
+ print(' '.join(alias for alias in HOST_URLS if url in alias))
+ exit()
+
+if download:
+ r = requests.get(url)
+ filename = url.split('/')[-1]
+ open(filename, 'wb').write(r.content)
+ exit()
+
+# Otherwise download the list for autocompletion
+incomplete = path[path.rindex('/')+1:]
+path = path[:path.rindex('/')] + '/'
+url = host + path
+html = requests.get(url).text
+resources = re.findall('<a.+>(.+)</a>', html)
+resources = [alias+path+r for r in resources if incomplete in r]
+print(' '.join(resources))
diff --git a/vshare.py b/vshare.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python3
+
+# Script for quickly sharing a single file (working as a server) or
+# downloading a shared file (working as a client).
+# When working as a server, it serves the single file given as argument and
+# exits immediately after a single request has been made, i.e. when the file
+# has hopefully been downloaded once.
+# When acting as a client it downloads the file served by a vshare server
+# running at the given IP and port (another computer)
+
+import sys
+
+if len(sys.argv) < 3 or sys.argv[1] not in ['s', 'g']:
+ print("Use:")
+ print(" to serve: " + sys.argv[0] + " s <filename>")
+ print(" to get / download: " + sys.argv[0] + " g <server>")
+ exit()
+
+# If arg is 'g', get file from the given server
+if sys.argv[1] == 'g':
+ import requests
+ url = sys.argv[2]
+ if 'http' not in url[:4]:
+ url = 'http://' + url
+ res = requests.get(url)
+ filename = res.headers['Filename']
+ with open(filename, 'wb') as f:
+ f.write(res.content)
+ print("Got file '" + filename + "'")
+ exit(1)
+
+
+# If arg is 's', share the given file
+from http.server import BaseHTTPRequestHandler, HTTPServer
+FILENAME=sys.argv[2]
+
+class StoppableServer(HTTPServer):
+ def serve_forever(self):
+ self.stop = False
+ while not self.stop:
+ self.handle_request()
+
+class OneShotServer(BaseHTTPRequestHandler):
+
+ def do_GET(self):
+ self.send_response(200)
+ self.send_header('Content-type', 'application/octet-stream')
+ self.send_header('Filename', FILENAME.split('/')[-1])
+ self.end_headers()
+ with open(FILENAME, 'rb') as f:
+ self.wfile.write(f.read())
+ print('File fetched. Closing server')
+ self.server.stop = True
+
+
+vsrv = StoppableServer(('0.0.0.0', 8001), OneShotServer)
+print('Serving "' + FILENAME + '"')
+try:
+ vsrv.serve_forever()
+except Exception:
+ vsrv.shutdown()