\n
Successfully
\n
Shortener url: http://localhost:8080/urlid/')
+ __M_writer('\nUrl shortener\n\n \n
Successfully
\n
Shortener url: http://localhost:8080/')
__M_writer(str(hash_id))
__M_writer('
\n
\n \n\n\n')
return ''
@@ -29,6 +29,6 @@ def render_body(context,**pageargs):
"""
__M_BEGIN_METADATA
-{"filename": "/home/mohammad/workspace/projects/urlshortner/templates/successfully.mak", "uri": "successfully.mak", "source_encoding": "ascii", "line_map": {"16": 0, "22": 1, "23": 6, "24": 6, "30": 24}}
+{"filename": "/home/mohammad/workspace/urlshortener/templates/successfully.mak", "uri": "successfully.mak", "source_encoding": "ascii", "line_map": {"16": 0, "22": 1, "23": 6, "24": 6, "30": 24}}
__M_END_METADATA
"""
diff --git a/templates/.successfully.mak.swp b/templates/.successfully.mak.swp
new file mode 100644
index 0000000000000000000000000000000000000000..386bf5186c5f5b00044fe432a30a900bd40cf751
GIT binary patch
literal 12288
zcmeI&J#W-77zc2d5s4Q86H`c8TZe!|l`~;P3^$$10uuNVbB@l5Bio^Os(_CIW5=$1
z1GbL+ENnbca^-|XRf!4lf22oF96PpuQijN$C$C;kqo?~%7{zVI&Ue}CclYkI^pLUI
zYFXE^>>phg(<`?7w0R*vvTo^HSt#B)ek4hJojBuDDU5Q#;o^ixx8$6
zJc9rPt|V}SJx(7bebe3eL3H;HedGuTKmY;|fB*y_009U<;J*$6
zxv_;b+WL?kBnJt9c&w$@Z>#d7;A20*+pS@B`sZ=ue71F*omP}?b)?yEdd_KH3un8g
z+#6;(Rb|!HGbLX*rJBi5d8DhLCao;Xs##=d(yk^k`3yWlD_Q0uRKckH(3$AsaJ}F|
MB@N#
-Url shortener
-
-
-
Can not found page
-
-
-
diff --git a/templates/successfully.mak b/templates/successfully.mak
index 0c4f3ac..8f8c22a 100644
--- a/templates/successfully.mak
+++ b/templates/successfully.mak
@@ -3,7 +3,7 @@
Successfully
-
Shortener url: http://localhost:8080/urlid/${hash_id}
+
Shortener url: http://localhost:8080/${hash_id}
diff --git a/url_shortener.py b/url_shortener.py
index af6b055..c5707a9 100644
--- a/url_shortener.py
+++ b/url_shortener.py
@@ -1,7 +1,10 @@
+import hashlib
+import binascii
import functools
from os.path import join, abspath, dirname
from mako.lookup import TemplateLookup
-from nanohttp import Controller, RestController, context, html, text, HttpFound, Static, settings, action
+from nanohttp import Controller, RestController, context, html, text, HttpFound, Static, \
+ settings, action, HttpNotFound
from hashids import Hashids
@@ -33,59 +36,56 @@ def wrapper(*args, **kwargs):
template = functools.partial(action, content_type='text/html', inner_decorator=render_template)
-class UrlShortenerController(RestController):
+db = {}
+
+
+class Codec:
+ def store(self, url):
+ if not url.startswith('http'):
+ url = f'http://{url}'
+
+ key = hashlib.sha1(url.encode()).digest()
+ if key not in db:
+ db[key] = url
+
+ return binascii.hexlify(key).decode()
+
+ def resolve(self, hexstring):
+ hexstring = hexstring.encode()
+ key = binascii.unhexlify(hexstring)
+ if key not in db:
+ raise HttpNotFound()
+
+ return db[key]
+
+codec = Codec()
+
+
+class Root(RestController):
+
+ def _find_handler(self, remaining_paths):
+ if len(remaining_paths) > 0:
+ return self.resolve, remaining_paths
+ return super()._find_handler(remaining_paths)
+
+ @template('index.mak')
+ def get(self):
+ return dict()
+
@template('successfully.mak')
def post(self):
- url = context.form.get('url')
- from pudb import set_trace; set_trace()
-
- if url in list_url:
- key = list_url.index(url)
- else:
- key = len(list_url)
- list_url.append(url)
-
- hash_id = hashids.encode(key)
- return dict(
- hash_id=hash_id
- )
-
-
-class UrlIdController(RestController):
- @template('notfoundpage.html')
- def get(self, url_id: str=None):
- print('url id: ', url_id)
-
- try:
- if url_id != None:
- key = hashids.decode(url_id)[0]
- print('key ', key)
-
- if key < len(list_url):
- url = list_url[key]
- else:
- url = None
- else:
- url = None
- except:
- url = None
-
- print('url: ', url)
-
- if url != None:
- if 'http://' in url:
- raise HttpFound(url)
- else:
- raise HttpFound('http://' + url)
- else:
- return dict()
-
-
-class Root(Controller):
- urlshortener = UrlShortenerController()
- urlid = UrlIdController()
+ return dict(hash_id=codec.store(context.form.get('url')))
- @template('index.mak')
- def index(self):
- return dict( )
+ @text
+ def resolve(self, hexstring):
+ raise HttpFound(codec.resolve(hexstring))
+
+
+if __name__ == '__main__':
+ from nanohttp import quickstart, configure
+ configure()
+ try:
+ quickstart(Root())
+ except KeyboardInterrupt:
+ print('CTLR+C just pressed')
From 0f0d74d481f30bedb2fbeef04081d341527f6bc9 Mon Sep 17 00:00:00 2001
From: Mohammad
Date: Wed, 23 May 2018 09:57:08 +0430
Subject: [PATCH 07/16] Done
---
.url_shortener.py.swp | Bin 12288 -> 0 bytes
__pycache__/__init__.cpython-36.pyc | Bin 0 -> 132 bytes
a | 0
alsjdf | 0
.../notfoundpage.html.cpython-36.pyc | Bin 1140 -> 0 bytes
makomodules/notfoundpage.html.py | 31 ------------------
templates/.successfully.mak.swp | Bin 12288 -> 0 bytes
url_shortener.py | 1 +
8 files changed, 1 insertion(+), 31 deletions(-)
delete mode 100644 .url_shortener.py.swp
create mode 100644 __pycache__/__init__.cpython-36.pyc
delete mode 100644 a
delete mode 100644 alsjdf
delete mode 100644 makomodules/__pycache__/notfoundpage.html.cpython-36.pyc
delete mode 100644 makomodules/notfoundpage.html.py
delete mode 100644 templates/.successfully.mak.swp
diff --git a/.url_shortener.py.swp b/.url_shortener.py.swp
deleted file mode 100644
index 9b343ce3d061b6ecb25513fb5aea75d0daffc263..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 12288
zcmeI2&x;&I6vr!qny68uCStsl#?U>RaW>J2Va~yxLtF5Yb
zcZ`XGAb9qo;zcm{g9z$BAfEK(E=2Ix$sc&qh@gpHqTkoQW@e+C_23~;&3tycyI#Hb
z>RYd>S*BY%5A8q5?{4g7IId;v#2B0HY~ISgz=oigZ^hBVwWG!mF+tNq@DVw#_PF6)3M`#U;f^W{dB2E53_M`(+id3RnfK0#*U5
zfK|XMU=^?mSOu&CRspNPMW_J%x_|Og#&%zhcpf|n4uc(F6F7SXV`spp;1h5H90${254aI*0e@{^>>M}^
zeg;2*Wv~R^0MCL0U^BP@{JEa7AHgzM0`GxW!DHYMm;z(q59oOooB`i}li+pmGFSwU
zgS!Cfz6G4S3|fLW!3JEf2fyR|H*gAk1YQHLfGO|-FklAU2JB%KunJfO{uc#!aU?2?
zjq6O#Oik~YXqV3ce=lJBu1?)H%i-AZCKOp)o>8lklm}QRGkhlNpcdhor
zF-AwWx`)+U2YQ@0&i%0wN~MXJs9ZdihQYixzB2B#l*X-*kenOU&us!3cfz?;2{&)(
zDB0t&AIq*W2@iV--kswECv{$RU}1-QUhMaT=kaEfJD%6`!`Snj2^0whp+oth7JMI^
zJs{J#?FO8-ZPDRnn-)>0&IcBGzV{iiXolPild71v!@#&*
zUw6H*-ONL1BQYpsOC1^=sd|k$f#SkDfKF{FTq3n`DORlt&`ToU2-neR5J2rt8b$p^
z&!0yTvTRT^uA#uWa+Eto_-9{X+!l-f;zXy3P;RZ^bztRn{kR?BS_zU9+IWd?x;hWC
zB0R+^#jGQzksej9n5am^=Q-r}@}2pZDfQ9dx%ev_LLnAJzScY|rD>tfB=l7>LcY|<
zGU<7fPtq)-qN)^1xmvUHqJMaBpT;vNkq4#8t7I@(^Gqk86|
zm=wx_jv{8WIB6K^Wt-l>A>5&6d}C;
z6|Dq~rm)ja?QosbH%76Gs#%tpql>jM!6xD*CYqFFZMTdt9w@f
diff --git a/__pycache__/__init__.cpython-36.pyc b/__pycache__/__init__.cpython-36.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c8f8bc51174cbedc7942218e11a806ad6ddfe1ef
GIT binary patch
literal 132
zcmXr!<>ji_|38WW2p)q77+?f49Dul(1xTbY1T$zd`mJOr0tq9CUxxY_`MIh3x%nB1
zxw(lc`sMjW*~JBk$*KCKMLES8`9&qEd8tME@$s2?nI-Y@dIgoYIBatBQ%ZAE?LbBq
H12F>t2OA(z
literal 0
HcmV?d00001
diff --git a/a b/a
deleted file mode 100644
index e69de29..0000000
diff --git a/alsjdf b/alsjdf
deleted file mode 100644
index e69de29..0000000
diff --git a/makomodules/__pycache__/notfoundpage.html.cpython-36.pyc b/makomodules/__pycache__/notfoundpage.html.cpython-36.pyc
deleted file mode 100644
index c8ab866b4177e98830c7bf6ef55b743c0c613db2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1140
zcmb7DOK;RL5Vn)-quFj>^a4m|)!QCQC|ppxtU$C>6=JFSkWem`H})oJlQ?o5`cQi+
zSAGcp0f`IZCvfnUQxE(Bkbv=qLREUfmM4?(c>I0inFsB*`~K@s|C58z7j$V@pg)FH
zY=U5j;RL1F$EoF8sqNbsalGgF4#=8c<8{BmoBjl|e3#jNi#h%ztNCqK_orCHpAL~f
z!)Nf8ODGA=#E(>$Sy7hWdRNR%1NX~^$JDou`O
z|1s$rErK`>umJ_52Fu+499FRm;souXJ$!~vt>Zh&I>8LT#iuq{ZLm2f4ztcMM$F!>
zJe@Oy(JROrFm(o9tefU`D#POVN6%pByS<20*6*oUCA_~Ylg=1A2kbqsGWNW&i`yFt
zcGM}%MVu;`flga=&|_qh2M|{`=KL{iAA{DGmuB)WG`H^l(o-yEJXwH~&nF4{Z
zi!E49n2sgq!7}L1X~#s9rm>`L1hgE|6T5@ewPzcHwN*W}z4LODY^{M|Yh$pk9g_&z
zGG6uHjOGl}O8=9gHc4q12P7-gAtY*w0N{8Ob4JFEHA#3zhY5#cBG+@|qBRIK9PB{S
z+kb7PjNuImQObbBxd0+%p>7g>m_uh3V=CiBUJ^G9z-F&XQ{T`lZh@G`b(qf8X*Z{T
E0s8(~%m4rY
diff --git a/makomodules/notfoundpage.html.py b/makomodules/notfoundpage.html.py
deleted file mode 100644
index c2e4ffb..0000000
--- a/makomodules/notfoundpage.html.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- coding:ascii -*-
-from mako import runtime, filters, cache
-UNDEFINED = runtime.UNDEFINED
-STOP_RENDERING = runtime.STOP_RENDERING
-__M_dict_builtin = dict
-__M_locals_builtin = locals
-_magic_number = 10
-_modified_time = 1526721980.4338439
-_enable_loop = True
-_template_filename = '/home/mohammad/workspace/projects/urlshortner/templates/notfoundpage.html'
-_template_uri = 'notfoundpage.html'
-_source_encoding = 'ascii'
-_exports = []
-
-
-def render_body(context,**pageargs):
- __M_caller = context.caller_stack._push_frame()
- try:
- __M_locals = __M_dict_builtin(pageargs=pageargs)
- __M_writer = context.writer()
- __M_writer('\nUrl shortener\n\n \n
Can not found page
\n \n\n\n')
- return ''
- finally:
- context.caller_stack._pop_frame()
-
-
-"""
-__M_BEGIN_METADATA
-{"filename": "/home/mohammad/workspace/projects/urlshortner/templates/notfoundpage.html", "uri": "notfoundpage.html", "source_encoding": "ascii", "line_map": {"16": 0, "21": 1, "27": 21}}
-__M_END_METADATA
-"""
diff --git a/templates/.successfully.mak.swp b/templates/.successfully.mak.swp
deleted file mode 100644
index 386bf5186c5f5b00044fe432a30a900bd40cf751..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 12288
zcmeI&J#W-77zc2d5s4Q86H`c8TZe!|l`~;P3^$$10uuNVbB@l5Bio^Os(_CIW5=$1
z1GbL+ENnbca^-|XRf!4lf22oF96PpuQijN$C$C;kqo?~%7{zVI&Ue}CclYkI^pLUI
zYFXE^>>phg(<`?7w0R*vvTo^HSt#B)ek4hJojBuDDU5Q#;o^ixx8$6
zJc9rPt|V}SJx(7bebe3eL3H;HedGuTKmY;|fB*y_009U<;J*$6
zxv_;b+WL?kBnJt9c&w$@Z>#d7;A20*+pS@B`sZ=ue71F*omP}?b)?yEdd_KH3un8g
z+#6;(Rb|!HGbLX*rJBi5d8DhLCao;Xs##=d(yk^k`3yWlD_Q0uRKckH(3$AsaJ}F|
MB@N#
Date: Thu, 24 May 2018 13:21:21 +0430
Subject: [PATCH 08/16] Create restfulpy
---
.idea/inspectionProfiles/Project_Default.xml | 14 +
.idea/misc.xml | 7 +
.idea/modules.xml | 8 +
.idea/urlshortener.iml | 18 +
.idea/vcs.xml | 7 +
.idea/workspace.xml | 593 ++++++++++++++++++
__pycache__/url_shortener.cpython-36.pyc | Bin 2692 -> 3013 bytes
data/api-documents/api/index.md | 45 ++
data/api-documents/api/legend.md | 47 ++
data/logs/urlshortener-error.log | 0
data/logs/urlshortener.log | 0
.../__pycache__/index.mak.cpython-36.pyc | Bin 1228 -> 0 bytes
.../successfully.mak.cpython-36.pyc | Bin 1281 -> 0 bytes
setup.py | 36 ++
url_shortener.py | 1 +
urlshortener.egg-info/PKG-INFO | 10 +
urlshortener.egg-info/SOURCES.txt | 20 +
urlshortener.egg-info/dependency_links.txt | 1 +
urlshortener.egg-info/entry_points.txt | 3 +
urlshortener.egg-info/requires.txt | 4 +
urlshortener.egg-info/top_level.txt | 1 +
urlshortener/__init__.py | 35 ++
.../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 1220 bytes
urlshortener/controllers/__init__.py | 0
.../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 157 bytes
.../__pycache__/helpers.cpython-36.pyc | Bin 0 -> 1138 bytes
.../__pycache__/root.cpython-36.pyc | Bin 0 -> 1015 bytes
.../__pycache__/urls.cpython-36.pyc | Bin 0 -> 1491 bytes
urlshortener/controllers/helpers.py | 28 +
urlshortener/controllers/root.py | 24 +
urlshortener/controllers/urls.py | 43 ++
urlshortener/makomodules/__init__.py | 0
.../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 157 bytes
.../makomodules}/index.mak.py | 0
.../makomodules}/successfully.mak.py | 0
urlshortener/models/__init__.py | 0
.../__pycache__/__init__.cpython-36.pyc | Bin 0 -> 152 bytes
urlshortener/models/urls.py | 17 +
.../templates}/index.mak | 0
.../templates}/successfully.mak | 0
urlshortener/tests/__init__.py | 0
.../tests/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 151 bytes
.../tests/__pycache__/helpers.cpython-36.pyc | Bin 0 -> 417 bytes
.../__pycache__/test_root.cpython-36.pyc | Bin 0 -> 1051 bytes
urlshortener/tests/helpers.py | 8 +
urlshortener/tests/test_root.py | 18 +
wsgi.py | 48 ++
47 files changed, 1036 insertions(+)
create mode 100644 .idea/inspectionProfiles/Project_Default.xml
create mode 100644 .idea/misc.xml
create mode 100644 .idea/modules.xml
create mode 100644 .idea/urlshortener.iml
create mode 100644 .idea/vcs.xml
create mode 100644 .idea/workspace.xml
create mode 100644 data/api-documents/api/index.md
create mode 100644 data/api-documents/api/legend.md
create mode 100644 data/logs/urlshortener-error.log
create mode 100644 data/logs/urlshortener.log
delete mode 100644 makomodules/__pycache__/index.mak.cpython-36.pyc
delete mode 100644 makomodules/__pycache__/successfully.mak.cpython-36.pyc
create mode 100644 setup.py
create mode 100644 urlshortener.egg-info/PKG-INFO
create mode 100644 urlshortener.egg-info/SOURCES.txt
create mode 100644 urlshortener.egg-info/dependency_links.txt
create mode 100644 urlshortener.egg-info/entry_points.txt
create mode 100644 urlshortener.egg-info/requires.txt
create mode 100644 urlshortener.egg-info/top_level.txt
create mode 100644 urlshortener/__init__.py
create mode 100644 urlshortener/__pycache__/__init__.cpython-36.pyc
create mode 100644 urlshortener/controllers/__init__.py
create mode 100644 urlshortener/controllers/__pycache__/__init__.cpython-36.pyc
create mode 100644 urlshortener/controllers/__pycache__/helpers.cpython-36.pyc
create mode 100644 urlshortener/controllers/__pycache__/root.cpython-36.pyc
create mode 100644 urlshortener/controllers/__pycache__/urls.cpython-36.pyc
create mode 100644 urlshortener/controllers/helpers.py
create mode 100644 urlshortener/controllers/root.py
create mode 100644 urlshortener/controllers/urls.py
create mode 100644 urlshortener/makomodules/__init__.py
create mode 100644 urlshortener/makomodules/__pycache__/__init__.cpython-36.pyc
rename {makomodules => urlshortener/makomodules}/index.mak.py (100%)
rename {makomodules => urlshortener/makomodules}/successfully.mak.py (100%)
create mode 100644 urlshortener/models/__init__.py
create mode 100644 urlshortener/models/__pycache__/__init__.cpython-36.pyc
create mode 100644 urlshortener/models/urls.py
rename {templates => urlshortener/templates}/index.mak (100%)
rename {templates => urlshortener/templates}/successfully.mak (100%)
create mode 100644 urlshortener/tests/__init__.py
create mode 100644 urlshortener/tests/__pycache__/__init__.cpython-36.pyc
create mode 100644 urlshortener/tests/__pycache__/helpers.cpython-36.pyc
create mode 100644 urlshortener/tests/__pycache__/test_root.cpython-36.pyc
create mode 100644 urlshortener/tests/helpers.py
create mode 100644 urlshortener/tests/test_root.py
create mode 100644 wsgi.py
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..0a29b70
--- /dev/null
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..f99b311
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..fb066f6
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/urlshortener.iml b/.idea/urlshortener.iml
new file mode 100644
index 0000000..99c45df
--- /dev/null
+++ b/.idea/urlshortener.iml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..4d51f89
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..37f2ca9
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,593 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TemplateLookup
+ lookup
+ import urlshortener
+
+
+ $PROJECT_DIR$/../leo
+ $PROJECT_DIR$
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ DEFINITION_ORDER
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1527057401177
+
+
+ 1527057401177
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/__pycache__/url_shortener.cpython-36.pyc b/__pycache__/url_shortener.cpython-36.pyc
index c694f337880211d2434e2de986cb0523acc2a055..b538cd25dae26a4f405392cb18d4dfb6654a7b1b 100644
GIT binary patch
literal 3013
zcmZ`*&668P74Po(&}dfL)qY}|;0QZTA_&?5!4-@#CQFC|&Q@Z(0t|<#+3D75r1?;~
zTiC0TFN~|~i&NYwxbyFD>?^1I3!HebN3wUJ7^z?Py#9Lq-tYZ-e%$SbfB)S3<39sJ
z{zc9`8_>QBMctx=aKdR$qNb)1weKuqP_x`A+{i7w$SeHFr#QyRTSX8Bw(aKaB8O4=leHT`R6f*C`R#YeLD{
zrnn~hHK{2jza!;Umx#BfA&mckLNAQE!S}K652R$j2cJD8gM)9-smBAyxRWX?O)EK3
zvqXtR4t!3Y(-Gs8vu8m~pRy$bXF10y46zSR!ty2*bqwMKS&}9F8is1Jgo!niSC?!;
zYx0zpS2Qf3otmi+wac0ImaL`+u+5*T_9v|ufSaez(wPJ!nEN%x#W^-DU4g}^UK~Ce
zi@p?Up6h-wSGs>9`bpW(N~M!B75!?|$8qoV%Szws-%x|LX^j(=Xf5Rdm}bIEtp^(y
zhnn!qB%h0qrK}`G=xip8pWEP?&Z*Gx+O5WyqU1sjT;nDZLp6Qe)Qvf>0}zAH-O;>E
zO?N#xM)>@L{QKtNxGKb9QH_(LNciF7N=^Y|sW_a=T#YNKMJXh{#IN3lvoq6rER)$x
z$bEG2CJ5q$wE6W|NEhG|wC$C#!`pe4Cb_yZTulU%+Gvuls$3ZlwQAtV>#&l13&lGq
zZh#oDbK18-VYdEj@m)|V3^-wzI`Vr^F93W`^dW*AHtJZ^m*6^d=2lk1kzy{=N+tlp
zSFo`QfVd0A;!O~wE1)Vw8i^e4a2INqdjJC8ct;g1asjRg*(03(D-cUMfjq9M+T(0V
z|4RPGo>EOG(4IKR0}~hV2iWtbEqQZE5qY->Vh#~F32M?{4RTe_7A=&w4i5o9Az({t
z^*BQ+05Fa7>;#f-ocz%EqD;XmFjzdvv(XuJ!|Ay|W>F#^
z83zJvoT)go9&dzowWq*C;ypZ42L!b9M42
zU9|%z?rS(d;jgC33yHD*KbE?)O6kv_e{E{pnu^*B
z(Zonv%XXmAScY-K%ZaZ%;z<17lD|QL5M9Md{u~vr;cAhJ{a-*?@7l4uu99I8%3t7|
zyC{B%0z+tm^_^kQBkyAeCRGEK?ke=D$n$mhaZ@<=CpgG%`w_ITD0EK1I$qE1xe_&)
zeTb$Q@2K#rd6rHsxtTU__9#1@OR?BJdUXH6_mBD$yk2KutP*_iwtOF^TdI)n;zF%T
z4H1tLV=vKf62sbjdkmWkRC=fh%A~B2O(jB0woss9vW>zX&3Y6GPj*q@1!oB;vXO_+
z9@zs`6y%xGF>)syW0d7U74T&xq>%WzVs9eTngLg5NiH$k4V58ZH1R?gG*15FtHIM}5lZCe;4{&_3Qp
literal 2692
zcmZuzOLJQ_6xQRu?A#wYu8A{qKL`g%%-ykyBp?
z?VC`{pCBZWv?Ky+R?>E;t5vaD
zt%{#EE-kXz8-
zQVEPdBk3K|yZATUk_>v>1>>fuU7X)DliZG6EDK%dmFiKqc2`xCGPmlhrrDcLdM(%f
zw5hFb%2H{!_O&whR6icVn0jDcFtSzY0^e@kvUc)CGp(hI?%3QGLzft3ZBg$U7v)1+
zG&SrL-^$IXkY=`SM}_IaU$x&gd1-r81XzofJvxg4_vU*|)yQe7Opl2bIItSpMi-L8X?+G7=5**d$8E9BCrVq)2{!D(RJ4{l^4wD5vU~>lU;e#Pe@gFY2@*EU1
z0P&E_$(;TIQ!Sap!UfaU=4?zCbI_<+y(
zIN5=uymSo7Y3tZFagi?|Qdx?2Yb=
z1|W$?xyh~7x&udZ?ZO;Sb^%Ux?QipPsy^4c(SXVRM7gN+aEf$S+3eV@F4C%&O7{X6
zkMkIStjAoiGp&bi^>}fHg!zN~)0yfrGowaZRV&?}?7R3!olho8Z=&xcqlXMaN!U}Veje%>(CUHRM#92Isb_EvPC+-V7d2cWlWN%L9O!jI2sD6f
zx(UTINfALM5lnF)1Mo=lLjYU^G5~l(cj+5l-Z^&45)!q60>OLJI`%&g9b82-qtQC7%asuLIn&>LMj4y+NuWGe6J
zmrx4ngm2Kw!H_)x!pmzJMErE-B
zI-LEsJVlBPi0mEAmy>)~^^uqZfFc6_0um?53`q>{*ODN=L&L&*1uz38_CK2g8TYup
zWq~pXy<|^AW`Y?U=;BFZxeXR{kLXWqFvn4T|0@Zy4p4qaYIv>ihrJ(2&Avzb0gwk*
zb8r1u8O}M7?hrB@km@IT|2G?=?y}Eyb!4LjxdRs9n$cjEzy-R6ywUYcn*{)OcNT*3
zMt2sE;ElMky$$XNC%S+KW*ctgB8)s>%x*lh)Ym!Z|GZ!1Nv+^dkK>tk>_Lcozj4b=*MC#Vt-T
z)*k?AtKSEKbA7tOoxJ7@T`<6J;uNI)W4bJe2vi6%Qt_E|k{qRz;OnNbvz8CGGg$*;
z7>myu5i~482=EGY={CA_+c`g7hpCukJh2IzwQ+;Kw?F8$&R-tGK%{`&NuKvt69{G@
zy>B#He4<-Ef`PlZ6&?@W5;2Xs-m|(3m5UqG$Nxe!#+XJAX{7q{$?q@UEsb&Jk~*&&
zB#uT?I!1w6N@G~)HVRLd6kDq(@b&S`((BklMqz5$DN0NL!ANPPFX0H%#l@3c+afQQ
u7s5;XYx>hZ>1r@MhMIm5DDF)DZNfp9?&*V=@p)Aba-d8bM1fVJ%Et_
diff --git a/data/api-documents/api/index.md b/data/api-documents/api/index.md
new file mode 100644
index 0000000..34551db
--- /dev/null
+++ b/data/api-documents/api/index.md
@@ -0,0 +1,45 @@
+
+
+| Parameter | Value |
+| --------- | ----------- |
+| Author | TestEngine |
+| Version | 0.1.0-planning.0 |
+| Status | Implemented |
+
+
+index
+=====
+## GET `/`
+
+Role: user
+
+
+
+### Status:
+
+`200 OK`
+
+### Response Headers:
+
+```
+Content-Type: text/html; charset=utf-8
+Content-Length: 363
+```
+### Response Body:
+
+```json
+
+Url shortener
+
+
+
+
+
+
+```
+
+
diff --git a/data/api-documents/api/legend.md b/data/api-documents/api/legend.md
new file mode 100644
index 0000000..de1c0ab
--- /dev/null
+++ b/data/api-documents/api/legend.md
@@ -0,0 +1,47 @@
+
+
+#### Legend
+
+
+##### Paging
+
+| Param | Meaning |
+| ------ | ------------------ |
+| take | Rows per page |
+| skip | Skip N rows |
+
+
+##### Search & Filtering
+
+You can search and filter the result via query-string:
+
+ /path/to/resource?field=[op]value1[,value2]
+
+| Operator | Meaning | Example |
+| --------- | ------- | --------------- |
+| | = | id=2 |
+| ! | != | id=!2 |
+| > | > | id=>2 |
+| >= | >= | id=>=2 |
+| < | < | id=<2 |
+| <= | <= | id=<=2 |
+| % | LIKE | title=u%s |
+| ~,% | ILIKE | title=~u%s |
+| IN() | IN | id=IN(2,3,4) |
+| !IN() | NOT IN | id=!IN(2,3,4) |
+| BETWEEN() | BETWEEN | id=BETWEEN(2,9) |
+
+
+##### Sorting
+
+You can sort like this:
+
+
+ /path/to/resource?sort=[op]value
+
+
+| Operator | Meaning |
+| --------- | ------- |
+| | ASC |
+| \- | DESC |
+
diff --git a/data/logs/urlshortener-error.log b/data/logs/urlshortener-error.log
new file mode 100644
index 0000000..e69de29
diff --git a/data/logs/urlshortener.log b/data/logs/urlshortener.log
new file mode 100644
index 0000000..e69de29
diff --git a/makomodules/__pycache__/index.mak.cpython-36.pyc b/makomodules/__pycache__/index.mak.cpython-36.pyc
deleted file mode 100644
index 888040591e29f9a54e360a630dd353eca16b6d37..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1228
zcmb7D&2A($5Oz=Z{G=z7WFsU52Q-@79N0#1n{-AjN)|T*@}_kAjVF&f1`{QejIu#3=dXk&H2
z{}PTl1;Y>vN+bgu$PVtv5QhQc!9|24uwC5cJ>2I5yu~^=W+5K32ye449nrzW8YN{hz=5`r_>N
zMN%lq6R8R+C1uH#(wC;D8Bc1hE_h~5(&*9@O52L-#By1e)N+%Eit+2`l3w0!J-V(-
zO(sMZco49FJM#bg29BA5xkDG|BDhEII=7$L&RxKQpMrNGL_>&0cMD_gBgJyAzbYGk&<3swVfjH#8531L`~0)|
z`e3rr>s)C$mfRMK9ZpVPEzc%nnpvT$!^xw99@A!xv07F6{G_QHI|i9&Y4Q+y#OR@>
zqVfs$rUsyvU)#yJq7r;4nT(Ss5dTRw%}NSLe@lVK;bi&nxlxiP9{5v>GyzdS)1;LO
zlv``;(6sBeGg_8h6JtRvHzajq3UaOiirXXPTf#(U$*O^Q6P4>-Y0yi%nAECnv!F#k
zQd%b-)0y8+?XHN04}rm_}r!+6?mkhb#7Jw5X=m=A&;?C9S+
H9PIuLm-cEe
diff --git a/makomodules/__pycache__/successfully.mak.cpython-36.pyc b/makomodules/__pycache__/successfully.mak.cpython-36.pyc
deleted file mode 100644
index 676d4f426310a90849a85006706f896f8c77ffa0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1281
zcma)5&2HQ_5GM7vvb^iMPI}2{;Q~eXkjQX>AXqDl1c(y^K{i1)0SfjYa79{@P5pqR
z>L096n^S>2NZuk(kppio%ibl5S$)?nK!A{}jM_diR&V{oupLhp#Ul
zgjrSau&6Rx6qJRhl{`^3O?cQyp|VP9UUC^~UetnWu0qu$30LZ<5#sz#K~FBWzmFJ~
zswB@7+?E2L2eZxk45lJr7U&oq<0ZPZE+*PqV20n}OBT=JS^|G>I>N@UY09ZgmFZR1U5H5#Wt_4}
zq;oC!VR!zxnCzYt=_&H~J
zQ_MJhA~`P)y5MP+Ykp8u#_}>9@9))T2fJ%{+5Q!r=4bjg6?s~Y6JEk~!M@p=&`{C-
z+QIt2&keiGa{&eJP9mjcRi=~K)kO~BR>#9k>v|l9qDrX9Dy7Hw_U`S47k8uZ>;5RL
z*V2VR{M&C3g`F-?)Jjl;M!x9-l;AQ}8WNk$xNboBBT1nHx8wME%<@FX^9Fh`FO8jY
zZ8qLaA00k^Iz4=3yi*B6Nn=BL6U22@cSlE_=_M8Dai(Pt8ixceRF|pqR}_@=uNOO{
z_ekD=(C5Sd*WJ*@RZ+1<{7Zk|sn5-(