Skip to content

Instantly share code, notes, and snippets.

@tolgahanakgun
Last active July 13, 2023 11:12
Show Gist options
  • Save tolgahanakgun/b339701632b9c1ac81a7d704a4c2ace9 to your computer and use it in GitHub Desktop.
Save tolgahanakgun/b339701632b9c1ac81a7d704a4c2ace9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
"""Extend Python's built in HTTP server to save files
curl or wget can be used to send files with options similar to the following
curl -X PUT --upload-file somefile.txt http://localhost:8000
wget -O- --method=PUT --body-file=somefile.txt http://localhost:8000/somefile.txt
__Note__: curl automatically appends the filename onto the end of the URL so
the path can be omitted.
Windows upload & download
powershell -ep bypass -c "$wc=New-Object Net.WebClient;$wc.UploadFile('http://target.com/upload.bin', 'PUT', 'c:\\upload.bin');"
powershell -ep bypass -c "$wc=New-Object Net.WebClient;$wc.DownloadFile('http://target.com/download.bin','c:\\download.bin');"
Linux upload & download
curl -X PUT --upload-file upload.bin http://target.com/upload.bin
wget -O- --method=PUT --body-file=upload.bin http://target.com/upload.bin
wget http://target.com/download.bin -O /tmp/download.bin
curl http://target.com/download.bin -o /tmp/download.bin
"""
import os
import http.server as server
import argparse
class HTTPRequestHandler(server.SimpleHTTPRequestHandler):
"""Extend SimpleHTTPRequestHandler to handle PUT requests"""
def do_PUT(self):
"""Save a file following a HTTP PUT request"""
filename = os.path.basename(self.path)
# Don't overwrite files
if os.path.exists(filename):
self.send_response(409, 'Conflict')
self.end_headers()
reply_body = '"%s" already exists\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
file_length = int(self.headers['Content-Length'])
with open(filename, 'wb+') as output_file:
read = 0
while read < file_length:
new_read = self.rfile.read(min(66556, file_length - read))
read += len(new_read)
output_file.write(new_read)
self.send_response(201, 'Created')
self.end_headers()
reply_body = 'Saved "%s"\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
def do_DELETE(self):
filename = os.path.basename(self.path)
if os.path.exists(filename):
try:
os.remove(filename)
self.send_response(410, 'Deleted')
self.end_headers()
reply_body = '"%s" has been deleted\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
except:
self.send_response(500, 'The file cannot be deleted')
self.end_headers()
reply_body = 'Something has gone wrong and "%s" cannot be deleted\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
else:
self.send_response(409, 'Conflict')
self.end_headers()
reply_body = '"%s" does not exist\n' % filename
self.wfile.write(reply_body.encode('utf-8'))
return
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="A simple http server with download/upload/delete support")
parser.add_argument("-p","--port", help="Listening port", type=int, default=80, required=False)
args = vars(parser.parse_args())
httpd = server.HTTPServer(('', args["port"]), HTTPRequestHandler)
print(f"Server has started on 0.0.0.0:{args['port']}")
httpd.serve_forever()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment