1 from flask
import Flask
, redirect
, request
, render_template
4 from datetime
import datetime
5 from urllib
import urlencode
6 from urlparse
import urlparse
, parse_qs
8 from couchdb
.client
import Server
10 google_apps_verify
= os
.environ
.get('GOOGLE_VERIFICATION', None)
13 os
.environ
.get('HEROKU_HOST', 'localhost:5000'),
19 couch_url
= os
.environ
.get('CLOUDANT_URL', 'http://localhost:5984/')
21 server
= Server(couch_url
)
25 if not db_name
in server
:
26 server
.create(db_name
)
28 return server
[db_name
]
32 def add_redirect(source
, destination
, strip_path
=False, strip_query
=False,
33 prefer_destination
=False):
38 doc
['destination']=destination
39 doc
['strip_path']=strip_path
40 doc
['strip_query']=strip_query
41 doc
['prefer_destination']=prefer_destination
45 def get_redirect(source
):
47 return db
[source
]['destination']
51 def del_redirect(source
):
53 destination
= db
[source
]['destination']
59 failure_template
= "snap.html"
61 def __init__(self
, redirects
=None):
63 if not isinstance(redirects
, dict):
64 raise TypeError('Router expects a dict of redirects')
66 self
.redirects
= redirects
68 self
.db
= get_db(db_name
)
70 def create(self
, src
, dst
):
71 self
.db
[src
] = {'destination': dst
, 'created': datetime
.now()}
73 def current_redirects(self
):
77 destination
= self
.db
[name
]['destination']
78 ret
.append({'source': name
.decode('idna'), 'destination': destination
.decode('idna')})
80 for name
in self
.redirects
.keys():
81 ret
.append({'source': name
.decode('idna'), 'destination': self
.redirects
['name'].decode('idna')})
85 def redirect(self
, hostname
, uri
):
86 if hostname
in self
.db
and 'destination' in self
.db
[hostname
]:
87 destination
= self
.db
[hostname
]['destination']
89 elif hostname
in self
.redirects
:
90 destination
= self
.redirects
[hostname
]
93 return render_template(self
.failure_template
, hostname
=hostname
, uri
=uri
)
95 urlbits
= urlparse(destination
)
97 if not urlbits
.netloc
:
98 urlbits
= urlparse('http://' + destination
)
99 if not urlbits
.netloc
:
100 return render_template(self
.failure_template
, hostname
=hostname
, uri
=uri
)
101 scheme
= urlbits
.scheme
or 'http'
103 destination
= scheme
+ '://' + urlbits
.netloc
108 query
= parse_qs(urlbits
.query
)
109 for key
, value
in query
.items():
110 query
[key
] = value
[0]
111 if request
.args
and (in_db
and not self
.db
[hostname
].get('strip_query')):
112 prefer_destination
= in_db
and self
.db
[hostname
].get('prefer_destination')
113 for key
, value
in request
.args
.items():
114 if key
in query
and prefer_destination
:
118 query_string
= '?' + urlencode(query
)
123 fragment
= '#' + urlbits
.fragment
127 if in_db
and self
.db
[hostname
].get('strip_path'):
130 path
= '/' + '/'.join([
131 urlbits
.path
.strip('/'),
135 destination
+= path
+ query_string
+ fragment
137 if os
.environ
.get('DEBUG_REDIRECT') and True or False:
140 return redirect(destination
)
142 rtr
= Router(redirects
)
146 template
= 'dash.html'
148 def __init__(self
, urls
=None):
150 if not isinstance(urls
, list):
151 raise TypeError('Dash expects a list of urls')
155 def is_dash(self
, url
):
156 return url
in self
.urls
158 def render(self
, uri
):
159 return render_template(self
.template
, redirects
=rtr
.current_redirects())
161 def __call__(self
, uri
):
162 return self
.render(uri
)
164 dash
= Dash(dashboards
)
166 @app.route('/_dash/')
167 @app.route('/_dash/<path:uri>')
168 def show_dash(uri
=None):
172 @app.route('/<path:uri>')
173 def uri_router(uri
=''):
174 if google_apps_verify
and uri
== 'google'+google_apps_verify
+'.html':
175 return 'google-site-verification: google'+google_apps_verify
+'.html'
177 hostname
= request
.host
179 if dash
.is_dash(hostname
):
182 return rtr
.redirect(hostname
, uri
)
184 if __name__
== '__main__':
185 port
= int(os
.environ
.get('PORT', 5000))
186 app
.debug
= os
.environ
.get('DEBUG') and True or False
187 app
.run('0.0.0.0', port
=port
)