Login

Tag "redirect"

25 snippets

Snippet List

When you can't return a response object, throw it

There are cases when rendering had already started, but you have to return Your response nevertheless. A good example is when you have a django-cms plugin and a form in it. You want to redirect after the form was processed, but normally you can't do it. More information here: https://github.com/divio/django-cms/issues/79 http://groups.google.com/group/django-cms/browse_thread/thread/79ab6080c80bbcb5?pli=1

  • middleware
  • redirect
  • django-cms
Read More

Effective content caching for mass-load site using redirect feature

Hi All, I would like to share my idea and experience in using http redirect feature to organize effective content caching and avoid site blocking on mass requests to not yet cached content. First of all, I should explain that I don't mean usual template-based pages, whose caching in django is enough in almost all cases. My speech is concerning to content such as dynamically created images, external files and other content which may require almost unpredictable long time period to be ready, up to about 10 seconds. Anyway, the content which is already in cache, can be returned immediately. The question is - what *should* happen if the requested content is *not yet present* in the cache? The HTML content is not a problem in this case - we can return intermediate page with meta information to ask a client to retry the content after some period of time. But non-HTML content, such as image, or json, is a problem. The usual *blocking* behavior of the django caching subsystem is not appropriate in a case when the content preparation process takes *more than several fractions* of a second. The whole period while the content is preparing (painting, getting from the external resource and so on) *hundreds* of users will *ask not yet cached* content until all available application server connections will be *occupied* by waiting requests and new user will wait for the content even if the content requested by him is actually ready to be returned. The celery package resolves this problem *partially*, allowing to schedule cache update before cache expiration in asynchronous manner (I am using threadpool package for this purpose instead), and avoiding blocking on content preparation procedure, but the problem with not yet available content remains unresolved. We might schedule periodic cache update to avoid such a situation, but this way leads to unnecessary resource load and may be inappropriate at all in some cases, f.e. for the service like CloudMade or Google "staticmap" painting map content basing on the request parameters. My solution is *using HTTP Redirect feature* . Ideal solution would be available if most of HTTP clients supported Retry-After header in the HTTP Redirect response. Unfortunately, no one of most popular clients (neither Mozilla, nor IE, nor Chrome) does it. Really they ask redirected URL immediately after receiving the redirection response, and ignore Retry-After header at all. Anyway, I hope that they *will* support this feature, but this is not enough right now. So, instead of delegating waiting job to the client side, we need to organize waiting on the server. For this purpose I have created small separate application server with it's *own connection pool*, and delegated waiting task to him (see the snippet). This server needs one URL (/retry_after in the example) looking to the view above, installed in the url.py, and additional DEFAULT_RETRY_TIMEOUT parameter in the settings.py. The view uses request GET parameters, so Django will not try to cache it's results. The only task for this server is to *suspend* redirected requests until requested time is *really arrived*, and then redirect the request to the original URL. To make possible to process many requests simultaneously, it breaks waiting and redirects too long time requests to the self basing on the default timeout. Using this server is simple. We will instantiate the 'retry' server on the separate URL as a *separate application server* and will redirect all requests required to be delayed to this server, passing original URL and the time moment when the requested content should be ready, as parameters. The main server which prepares and returns the content, is *never waiting*. It returns prepared content from the cache, if it is found there, or *starts* content preparation process in *asynchronous* manner using threads, celery package, or any other appropriate technique, and *immediately redirects* the request to the 'retry' server The following is a fragment of the code using 'retry' server: ... # Create your views here. def jams(request,z,x,y): jams_timeout = settings.JAMS_TIMEOUT retry_after_server = settings.RETRY_AFTER_SERVER try: jams_ts,jams_png = request_jams(z,x,y) except Http404,ex: return HttpResponseNotFound() if not jams_png: if settings.DEBUG: logger.debug("JAMS NOT YET READY FOR: %s" % str((z,x,y))) # Tell a client to retrieve jams later time_after = time.time() + settings.DEFAULT_RETRY_TIMEOUT if settings.DEBUG: logger.debug("SEND RETRY AFTER FOR: %s" % str((z,x,y))) loc = reverse(jams,args=(z,x,y)) if request.get_host(): loc = request.build_absolute_uri(loc) r = HttpResponseRedirect( retry_after_server + '?' + urlencode({'redirect': loc,'retry_after':int(time_after)}) ) r['Retry-After'] = settings.DEFAULT_RETRY_TIMEOUT return r # return a png got from the cache if settings.DEBUG: logger.debug("RETURNING JAMS FOR: %s" % str((z,x,y,http_date(jams_ts),http_date(time.time())))) r = HttpResponse(jams_png) r['Content-Type'] = "image/png" r['Content-Length'] = len(jams_png) r['Content-Location'] = request.path # extra data for cache negotiation # Common and ConditionalGet Django Middleware will do the rest r['ETag'] = '"%s"' % md5_constructor(jams_png).hexdigest() r['Last-Modified'] = http_date(jams_ts) r['Expires'] = http_date(jams_ts + jams_timeout) return r ... At the application level, the request_jams() call tries to get content from the cache, and starts content update process asynchronously if required. It returns content got from the cache, and timestamp when the content has been created last time, or pair of None,None values, if the requested content is not available immediately. The line starting from 'r = HttpResponseRedirect' redirects the request to the 'retry' server, if the content is not available immediately. I am using nginx as a 'front-end' proxy server which passes requests to two separate fastcgi daemons - 'retry' and main django application servers separating requests by prefix. The following is a fragment of the nginx.conf configuration file for the nginx server: server { ... location /jams { fastcgi_pass unix:/var/tmp/jams.sock; ... } location /retry_after { fastcgi_pass unix:/var/tmp/retry.sock; ... } ... } As you can see, two locations are passed to *different* application server instances in the production environment, so they *don't block each other*. Really they both are implemented inside one django project, and started from the same directory as fastcgi daemon instances with different starting parameters (sockets to listen, log files etc.). I've used such structure to configure and debug my server easy, either just starting one developer server for both locations, or to have a possibility to start production server in described 'split' mode on the other hand. You can see that the both servers (jams and retry) use the same DEFAULT_RETRY_TIMEOUT setting from the settings.py file. The DEFAULT_RETRY_TIMEOUT plays role of load balancing parameter for requests which wait finishing asynchronous job. After the retry timeout is passed, the control returns to the client by the redirection response (or, for smart clients, the client itself waits the retry timeout before requesting the resource again), so the server may cleanup resources temporary acquired by these requests. Additional bonus of using such technique is stability of server processor load. Even in prime time, the server load is stable and controlled: number of the application instances and number of threads in the thread pool (evaluating asynchronous jobs) for each instance is fixed by configuration, nginx load per request is minimal, and concurrent requests are balanced (between server, network, and clients) by the retry timeout and redirect responses. You can see the result of the work on the our site, f.e. [on this page](http://www.doroga.tv/nnov/apps/map/), where all (transparent version) jam tiles are painting such a manner. The only difference for the production server environment is that some top zooms of most popular regions are refreshed by the special daemon (also written using django as a 'management command') which forces tiles to be refreshed in the cache even no one client requests it right now — to decrease response time for the jams map after long 'sleep' period.

  • cache
  • load
  • redirect
  • nginx
  • content
  • mass
Read More

FirstRun Middleware

Simple piece of middleware that redirects all requests to **settings.FIRSTRUN_APP_PATH**, until a lockfile is created. Tested on 1.3 only, but I do not believe it requires any special functionality beyond that provided in 1.1 This is useful if you need to force a user to run an installer, or do some configuration before your project can function fully. At first glance, such a thing would generate a lot of hits on the disk. However, once the lockfile has been created, the middleware unloads itself, so when a project is in a production environment, the lockfile is only checked once per process invocation (with passenger or mod_wsgi, that's not very often at all). Once your user has completed your FirstRun app, simply create the lockfile and the project will function as normal. For it to function, the following settings must be configured: * **settings.PROJECT_PATH** - absolute path to project on disk (e.g. */var/www/project/*) * **settings.FIRSTRUN_LOCKFILE** - relative path of the lockfile (e.g. */.lockfile*) * **settings.FIRSTRUN_APP_ROOT** - relative URL of the App you want to FirstRun (eg.*/firstrun/*)

  • middleware
  • django
  • redirect
Read More

Workaround Firefox bug 553888

Firefox transparently follows redirects when AJAX calls return 3xx code. And it drops additional headers, X-Requested-With among them. Server treats redirected HTTP requested as non-AJAX. JS libraries has nothing to do here. At 16.03.11 bug https://bugzilla.mozilla.org/show_bug.cgi?id=553888 has status "NEW" being reported at 21.03.10. Workaround is following: - in process_response(): if request.is_ajax() and response has status_code 3xx then put response["Location"] to session, otherwise unset session stored value (if it is there). - in process_request(): if not request.is_ajax() and request.path equals to stored session value then monkeypatch request.is_ajax() return True (before any views come into play). This results in smooth transparent redirects in Firefox, all treated as AJAX calls.

  • ajax
  • redirect
  • headers
Read More

login_required decorator that doesn't redirect

A login_required decorator that wraps the login view instead of redirecting to it. This prevents your site from leaking login information with HTTP status codes as explained [here](https://grepular.com/Abusing_HTTP_Status_Codes_to_Expose_Private_Information). This is the way Django's admin is protected, the difference being that it checks for is_active and is_staff instead of is_authenticated. With this decorators, users directly see a login form (no redirect), post it to LOGIN_URL and are redirected to the page they first tried to see.

  • redirect
  • login_required
Read More

Doing redirect without request

When you neeed to do redirect and request object is not available, you can do it with exception. Put exception handler somewhere request is available, for example to middleware or ModelAdmin. Raise exception, where request is not available.

  • http
  • request
  • redirect
  • reverse
  • httpresponse
Read More

Return to a filtered changelist on change form save

You've filtered your changelist in your admin site and you want to edit a few entries here; you click on an object, edit it and press save, and you end up back at the default unfiltered changelist view. This ModelAdmin override is so that if you press "save" (not "save and add another", or "save and continue editing") you end up back at your filtered changelist. There are other ways out there and other snippets to do similar; however I hadn't seen one to only redirect if you pressed save so this is what I came up with. Hopefully it's useful.

  • admin
  • redirect
Read More

RedirectedURLField

This field is similar to the standard URLField, except it checks the given URL for a HTTP 301 response (permanent redirect) and updates its value accordingly. For example: >>> url = RedirectedURLField() >>> url.clean('http://www.twitter.com/') >>> 'http://twitter.com/' In models: class TestModel(models.Model): url1 = RedirectedURLField('Redirected URL') url2 = models.URLField('Standard URL')

  • url
  • redirect
  • field
Read More

Redirect view based on GEO

Wanted a neat way to redirect views based on GeoIP determined criteria, from HTTP_REFERER. Decorator approach seemed the best way to make it straightforward to redirect views. To use, installed the Max Mind Python GeoIP API : http://www.maxmind.com/app/python

  • view
  • redirect
  • geoip
Read More

simple DomainsAliasMiddleware

Permit to redirect desired domain name to the 'domain' of Site app. Useful if you have different domains name for the same website. #1. Add to your settings DOMAINS_ALIAS like this: DOMAINS_ALIAS = ( 'my-second-domain.com', 'www.my-second-domain.com', 'third-domain.com', 'www.third-domain.com', ) notice: all these domains are redirected to the **domain** db entry of Site ID. #2. add all these domains to ServerAlias directive in your vhost apache configuration. #3. enable the middleware by adding to your MIDDLEWARE_CLASSES: MIDDLEWARE_CLASSES = ( ... 'utils.middleware.domainsalias.DomainsAliasMiddleware', ... )

  • middleware
  • redirect
  • domain
Read More

Custom Admin Redirects

This little bit of code will let you reference parts of the admin but lets you control where it returns to. For instance, I have a list of objects in the admin and i want to have a delete link for each object. I don't want them to return to the changelist after a delete however, i want them to return to my list. cheers

  • admin
  • redirect
Read More

iPhone Redirect Middleware

I didn't really like the current state of iPhone/Mobile redirect middleware mainly because I wanted something that was closer to twitters use case. So I came up with this. I don't think it a great snippet and I will probably fix it in the near future. But it works.

  • middleware
  • session
  • redirect
  • iphone
Read More

Create short URL redirects for site urls.

This allows you to host your own URL shortening service for your site's internal urls. By adding this class as a Mixin to your models, any model with a get_absolute_url method will have a get_short_url method also, which either returns an existing redirect or creates a new one and returns that. **Usage:** Import the class above, add the mixin to your model declaration, and ensure you have declared a get_absolute_url method. `class MyModel = (models.Model, ShortURL):` **Pre-requisites:** You must have the django.contrib.redirects app installed, and you must be using the RedirectFallbackMiddleware as a middleware class. **Settings:** Change the settings in the code above or set them in your settings.py file SHORTURL_CHARS: the characters to use when creating a shorturl SHORTURL_CHAR_NO = the number of characters to use in a shorturl SHORTURL_APPEND_SLASH = whether to append a slash to the end of the shorturl redirect **Notes:** The default settings will give you about 17 million different unique short URLs, reducing the number of characters used to 4 will give you 600,000 or so. That's enough that collisions will be quite rare for sites of a few thousand pages (collisions just result in a urls being generated until an unused combination is found) but if you've got a big site you'll probably want to explore a more robust solution with a proper hash function. [http://matt.geek.nz/blog/text/generating-short-urls-django-site-urls/](http://matt.geek.nz/blog/text/generating-short-urls-django-site-urls/)

  • url
  • redirect
  • tinyurl
  • short
Read More

Decorator to ease dynamic redirections in Django

I often use it so I hope it helps! Usage: urlpatterns = patterns('', url(r'^nav/$', redirect('/navigation/')), url(r'^search/(?P<category_name>\w+)/$', redirect('/documents/%(category_name)s/')), and so on... ) It keeps GET arguments too.

  • dynamic
  • decorator
  • redirect
Read More