initial commit

This commit is contained in:
dave 2017-02-06 23:11:40 -08:00
commit ac7ec124c8
7 changed files with 174 additions and 0 deletions

11
README.txt Normal file
View File

@ -0,0 +1,11 @@
IMGHOST
The simplest imghost
Install like:
pip3 install -r requirements.txt
python3 setup.py install
imghost
Then visit http://127.0.0.1:3000/

1
imghost/__init__.py Normal file
View File

@ -0,0 +1 @@
__version__ = "0.0.0"

119
imghost/api.py Normal file
View File

@ -0,0 +1,119 @@
import cherrypy
import logging
import os
import cgi
import tempfile
import subprocess
class Mountable(object):
"""
Macro for encapsulating a component's config and methods into one object.
:param conf: cherrypy config dict for use when mounting this component
"""
def __init__(self, conf=None):
self.conf = conf if conf else {'/': {}}
def mount(self, path):
"""
Mount this component into the cherrypy tree
:param path: where to mount it e.g. /v1
:return: self
"""
cherrypy.tree.mount(self, path, self.conf)
return self
class tempFileStorage(cgi.FieldStorage):
def make_file(self, binary=None):
return tempfile.NamedTemporaryFile()
def noBodyProcess():
cherrypy.request.process_request_body = False
cherrypy.tools.noBodyProcess = cherrypy.Tool('before_request_body', noBodyProcess)
type2ext = {
"image/png": "png",
"image/jpg": "jpg",
"image/gif": "gif"
}
class ImgHostApiV1(Mountable):
@cherrypy.expose
@cherrypy.tools.noBodyProcess()
def upload(self, theFile=None):
# convert the header keys to lower case
lcHDRS = {}
for key, val in cherrypy.request.headers.items():
lcHDRS[key.lower()] = val
if int(lcHDRS['content-length']) > 10**7:
raise Exception("File size max of 10MB exceeded")
formFields = tempFileStorage(fp=cherrypy.request.rfile,
headers=lcHDRS,
environ={'REQUEST_METHOD': 'POST'},
keep_blank_values=True)
theFile = formFields['theFile']
# os.link(theFile.file.name, '/tmp/' + theFile.filename)
try:
ext = type2ext[str(theFile.type)]
except KeyError:
raise Exception("File type not allowed")
sha = subprocess.check_output(["sha512sum", theFile.file.name])
sha = sha.decode("UTF-8").split(" ")[0]
imgpath = os.path.join("i", "{}.{}".format(sha[0:8], ext))
os.link(theFile.file.name, os.path.join("ui", imgpath))
raise cherrypy.HTTPRedirect("/" + imgpath)
class ImgHostApi(object):
def __init__(self):
ui_path = os.path.join(os.getcwd(), 'ui')
self.ui = Mountable(conf={'/': {
'tools.staticdir.on': True,
'tools.staticdir.dir': ui_path,
'tools.staticdir.index': 'index.html'}}).mount('/')
self.app_v1 = ImgHostApiV1().mount('/api/v1')
cherrypy.config.update({
'sessionFilter.on': False,
'tools.sessions.on': False,
'tools.sessions.locking': 'explicit',
# 'tools.sessions.timeout': 525600,
'request.show_tracebacks': True,
'server.socket_port': 3000, # TODO configurable port
'server.thread_pool': 25,
'server.socket_host': '0.0.0.0',
'server.socket_timeout': 5,
'log.screen': False,
'engine.autoreload.on': False
})
def run(self):
cherrypy.engine.start()
cherrypy.engine.block()
logging.info("API has shut down")
def stop(self):
cherrypy.engine.exit()
logging.info("API shutting down...")
def main():
logging.basicConfig(level=logging.DEBUG,
format="%(asctime)-15s %(levelname)-8s %(name)s %(filename)s:%(lineno)d %(message)s")
api = ImgHostApi()
api.run()

11
requirements.txt Normal file
View File

@ -0,0 +1,11 @@
appdirs==1.4.0
cheroot==5.1.0
CherryPy==10.0.0
imghost==0.0.0
packaging==16.8
pkg-resources==0.0.0
portend==1.8
pyparsing==2.1.10
pytz==2016.10
six==1.10.0
tempora==1.6.1

23
setup.py Normal file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env python3
from setuptools import setup
from imghost import __version__
with open("./requirements.txt") as reqf:
deps = reqf.read().strip().split("\n")
setup(name='imghost',
version=__version__,
description='minimal img hoster',
url='http://',
author='dpedu',
author_email='git@davepedu.com',
packages=[
'imghost'
],
entry_points={
'console_scripts': [
'imghost = imghost.api:main'
]
},
install_requires=deps,
zip_safe=False)

1
ui/i/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*

8
ui/index.html Normal file
View File

@ -0,0 +1,8 @@
<html>
<body>
<form method="post" action="/api/v1/upload" enctype="multipart/form-data">
File: <input type="file" name="theFile"/> <br/>
<input type="submit"/>
</form>
</body>
</html>