Creating a dynamic redirect by using any of Flask, Pyramid, or Bottle?
Question:
I want to create a webapp that dynamically redirects to a URL, based on address that user typed. When a user visit my site by a address like this:
http://mydomain1.com/a1b2c3d4
I want redirect this user to URL:
http://mydomain2.com/register.php?id=a1b2c3d4&from=mydomain1.com
Answers:
Yay, I love a good fight!
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from paste.httpserver import serve
config = Configurator()
config.add_route('redirect', '/{arg}')
def redirect_view(request):
dst = 'http://mydomain2.com/register.php?id={id}&from={host}'
args = {
'id': request.matchdict['arg'],
'host': request.host,
}
return HTTPFound(dst.format(**args))
config.add_view(redirect_view, route_name='redirect')
serve(config.make_wsgi_app(), host='0.0.0.0', port=80)
Here goes my attempt, I’m almost newbie in flask, so it should have room to improve
from flask import Flask, redirect, request
app = Flask(__name__)
host = 'domain2.org'
@app.route('/<path>')
def redirection(path):
return redirect('http://'+host+'/register.php?id='+path+'&from='+request.host)
if __name__ == '__main__':
app.run()
Edited to add the host to the from parameter
My solution was to use a Werkzeug rule using the path type :
host = 'domain2.org'
@app.route('/<path:path>')
def redirection(path):
return redirect('http://%s/%s' % (host, path), code=301)
This can be useful if you move a site and want another site instead with redirection on others pages.
There’s a pyramid_rewrite extension (https://pypi.python.org/pypi/pyramid_rewrite/) that looks unmaintained, but seems to work. I had a use case it didn’t handle, though: using Configure.include() with the route_prefix parameter.
It occurred to me that the usual approach is to do URL rewrites in the server, and I was using a WSGI server from the Python standard library. How hard could it be?
Make a custom request handler class:
from wsgiref.simple_server import make_server, WSGIRequestHandler
class MyReqHandler(WSGIRequestHandler):
def get_environ(self):
env = WSGIRequestHandler.get_environ(self)
if env['PATH_INFO'].startswith('/foo'):
env['PATH_INFO'] = env['PATH_INFO'].replace('foo', 'bar', 1)
return env
Pass it to make_server() when creating your server:
srvr = make_server('0.0.0.0', 6543, app, handler_class=MyReqHandler)
It works!
Straight-up substitution is all I needed for the problem at hand. Extending it to use regular expressions and exposing it via a nice API would be pretty straightforward.
I have another solution, that is straight-up pyramid, so it will work with some other wsgi server:
from pyramid.events import NewRequest, subscriber
@subscriber(NewRequest)
def mysubscriber(event):
req = event.request
if req.path_info.startswith('/~cfuller'):
req.path_info = req.path_info.replace('foo', 'bar', 1)
That’s the declarative way, and it requires a config.scan(). Imperitively, you’d do something like
config.add_subscriber(mysubscriber, NewRequest)
See http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/events.html for the skinny on events.
I want to create a webapp that dynamically redirects to a URL, based on address that user typed. When a user visit my site by a address like this:
http://mydomain1.com/a1b2c3d4
I want redirect this user to URL:
http://mydomain2.com/register.php?id=a1b2c3d4&from=mydomain1.com
Yay, I love a good fight!
from pyramid.config import Configurator
from pyramid.httpexceptions import HTTPFound
from paste.httpserver import serve
config = Configurator()
config.add_route('redirect', '/{arg}')
def redirect_view(request):
dst = 'http://mydomain2.com/register.php?id={id}&from={host}'
args = {
'id': request.matchdict['arg'],
'host': request.host,
}
return HTTPFound(dst.format(**args))
config.add_view(redirect_view, route_name='redirect')
serve(config.make_wsgi_app(), host='0.0.0.0', port=80)
Here goes my attempt, I’m almost newbie in flask, so it should have room to improve
from flask import Flask, redirect, request
app = Flask(__name__)
host = 'domain2.org'
@app.route('/<path>')
def redirection(path):
return redirect('http://'+host+'/register.php?id='+path+'&from='+request.host)
if __name__ == '__main__':
app.run()
Edited to add the host to the from parameter
My solution was to use a Werkzeug rule using the path type :
host = 'domain2.org'
@app.route('/<path:path>')
def redirection(path):
return redirect('http://%s/%s' % (host, path), code=301)
This can be useful if you move a site and want another site instead with redirection on others pages.
There’s a pyramid_rewrite extension (https://pypi.python.org/pypi/pyramid_rewrite/) that looks unmaintained, but seems to work. I had a use case it didn’t handle, though: using Configure.include() with the route_prefix parameter.
It occurred to me that the usual approach is to do URL rewrites in the server, and I was using a WSGI server from the Python standard library. How hard could it be?
Make a custom request handler class:
from wsgiref.simple_server import make_server, WSGIRequestHandler
class MyReqHandler(WSGIRequestHandler):
def get_environ(self):
env = WSGIRequestHandler.get_environ(self)
if env['PATH_INFO'].startswith('/foo'):
env['PATH_INFO'] = env['PATH_INFO'].replace('foo', 'bar', 1)
return env
Pass it to make_server() when creating your server:
srvr = make_server('0.0.0.0', 6543, app, handler_class=MyReqHandler)
It works!
Straight-up substitution is all I needed for the problem at hand. Extending it to use regular expressions and exposing it via a nice API would be pretty straightforward.
I have another solution, that is straight-up pyramid, so it will work with some other wsgi server:
from pyramid.events import NewRequest, subscriber
@subscriber(NewRequest)
def mysubscriber(event):
req = event.request
if req.path_info.startswith('/~cfuller'):
req.path_info = req.path_info.replace('foo', 'bar', 1)
That’s the declarative way, and it requires a config.scan(). Imperitively, you’d do something like
config.add_subscriber(mysubscriber, NewRequest)
See http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/events.html for the skinny on events.