Fragments of Code

September 10, 2009

Disable WordPress Flash Uploader with Apache

Filed under: Apache — Tags: , — David Chandek-Stark @ 10:13 am

OK, this doesn’t really disable it, but it does make the “browser uploader” the default …

<Directory /path/to/wp/wp-admin>
  <Files media-new.php>
    # Force browser uploader instead of Flash
    RewriteCond %{QUERY_STRING} !=flash=0
    RewriteRule ^/(.*) /$1?flash=0
  </Files>
</Directory>

(WordPress 2.8.4)

February 24, 2009

Get a fully-qualified URL for the current Django site

Filed under: Apache, Django, code — Tags: , , — David Chandek-Stark @ 1:02 pm

You need to generate a fully-qualified URL to a Django page, in particular outside of a web request context (in which you would have access to server variables), such as an automated process that generates e-mail with links.  You may be able to generate a root-relative URL from a reverse lookup; there’s also get_absolute_url() of course, but it’s provided on a per-model basis, and in any case shouldn’t be coupled with URL elements such as protocol and host name.  You can get the domain part of the host name from the current site object, but Django currently (as of version 1.0.2) provides no means for reliably generating a fully-qualified URL (including protocol and port) outside of a web request context.  In the function current_site_url(), below, I have used two custom settings, MY_SITE_PROTOCOL and MY_SITE_PORT.  (My current practice is to prefix custom settings with MY_,  place them in a parallel module in the project called my_settings.py, and import the custom settings into the project settings module.)

def current_site_url():
    """Returns fully qualified URL (no trailing slash) for the current site."""
    from django.contrib.sites.models import Site
    current_site = Site.objects.get_current()
    protocol = getattr(settings, 'MY_SITE_PROTOCOL', 'http')
    port     = getattr(settings, 'MY_SITE_PORT', '')
    url = '%s://%s' % (protocol, current_site.domain)
    if port:
        url += ':%s' % port
    return url

Now, I still don’t really have enough information to construct a fully-qualified URL for the most general case, because in taking advantage of the django.root setting, my code no longer “knows” what Django’s root path is.  That was good for decoupling the URLconf from the web server conf, but again, I need to generate fully-qualified URLs outside of a web request context, so I don’t have access the django.root setting.  My solution has been to add another custom setting, MY_DJANGO_URL_PATH, which corresponds to the django.root setting (a comment Django’s mod_python handler module indicates that the handler must be called before importing any settings in order for os.environ to be set up correctly with respect to settings).  With that, I can get my Django root URL with this function:

def django_root_url(fq=False):
    """Returns base URL (no trailing slash) for the current project.

    Setting fq parameter to a true value will prepend the base URL
    of the current site to create a fully qualified URL.

    The name django_root_url is used in favor of alternatives
    (such as project_url) because it corresponds to the mod_python
    PythonOption django.root setting used in Apache.
    """
    url = getattr(settings, 'MY_DJANGO_URL_PATH', '')
    if fq:
        url = current_site_url() + url
    return url

With these functions and Django’s reverse URL lookup, I can construct fully-qualified URLs.

February 4, 2009

Python script for Apache RewriteMap

Filed under: Apache, Python — Tags: , , , — David Chandek-Stark @ 3:00 pm

It turned out that I didn’t need this after all, but thought I’d post it here anyway …

The use case was to base64-encode a URL so that it could be passed as a query parameter to a login page.  The login routes through a third page and returns to the logn page, which redirects the client back to the original URL which was base64-encoded.  Without the encoding, the third page could mangle the original URL.

#!/usr/bin/python

import binascii
import sys

while sys.stdin:
    print binascii.b2a_base64(sys.stdin.readline().rstrip()) ,
    sys.stdout.flush()

January 7, 2009

Managing static files for Django applications

Filed under: Apache, Django — Tags: , , — David Chandek-Stark @ 3:30 pm

Two principles of Django development lead to a dilemma:

  1. Application code should be self-contained — i.e., not coupled with a project.
  2. Django should not serve static media files (for security and efficiency).

So, how does one manage static files (images, css, js, etc.) that are bundled with an application?  I make a couple of assumptions:

  1. You don’t want to hard-code full URL paths in templates, so you need some way to inject a base URL dynamically into your template context.
  2. You want to keep the media files in the application package — that is, not to copy or move them to a filesystem location outside the application directory.

Django’s builtin settings provide for two non-admin media settings, MEDIA_ROOT and MEDIA_URL.  One option for resolving the issue is to use MEDIA_URL and create symlinks from the MEDIA_ROOT directory to the application’s media directory (or directories).  Personally, I don’t like that, partly because I prefer not to use symlinks, but mostly because the MEDIA_ROOT space is used for uploads for model file fields, and it feels like this other static, presentation-related, content should be in its own space.  OTOH the symlink approach is probably the most flexible.

What I’ve been doing to this point is based on the assumption that my application packages all live in the same base directory. I added a custom setting APP_MEDIA_PREFIX (inspired by ADMIN_MEDIA_PREFIX) and set it to the URL path which I alias in in Apache.

Django setting:

APP_MEDIA_PREFIX = '/django/apps/'

Apache conf:

# Application media
AliasMatch ^/django/apps/([^/]+)/media/(.+) /opt/django/apps/$1/media/$2
<DirectoryMatch "^/opt/django/apps/[^/]+/media">
    Allow from all
</DirectoryMatch>

My apps packages are in /opt/django/apps and by convention put their media files in a “media” subdirectory. Then I created a custom template tag for printing APP_MEDIA_PREFIX (inspired by {% admin_media_prefix %}) in my custom template tag module (custom.py):

from django import template
from django.conf import settings

register = template.Library()

@register.simple_tag
def app_media_prefix():
    """Prints value of APP_MEDIA_PREFIX setting.

    Usage: {% app_media_prefix %}
    """
    return getattr(settings, 'APP_MEDIA_PREFIX', '')

Then, in a template, for example:

{% load custom %}
<link rel="stylesheet" type="text/css" href="{% app_media_prefix %}locationguide/media/css/locationguide.css"/>

In this case, the application name/label is “locationguide” and is located in /opt/django/apps/locationguide.

If anyone has thought of a significantly better way to manage this scenario, I’d love to hear it.

December 17, 2008

django.root decouples URLconf from Apache conf

Filed under: Apache, Django — Tags: , , — David Chandek-Stark @ 5:26 pm

Maybe I didn’t read the detailed change log for Django 1.0 … in any case I missed this important new feature. If you are using Apache and mod_python to serve your Django site, you can add a directive to your Apache conf that will tell Django the root path of your Django URLs:

PythonOption django.root /apps

It seemed as though most Django examples assumed that your Django site was served from the root URL of the web server — even though that wasn’t a requirement in any way. The problem before this setting was available is that it coupled your Django project root URLconf to your web server configuration because Django always received the full URL path. Now with this setting, the root Django path from your Apache config is stripped off before matching url patterns in your Django URLconfs.

Thanks, Django!

December 15, 2008

Apache gotcha: RewriteOptions inherit

Filed under: Apache — Tags: , — David Chandek-Stark @ 11:17 am

The Apache 2.2 documentation on RewriteOptions inherit indicates only that “parent” rules, maps, and conditions are inherited, but not what inheritance means in this context. Since RewriteRule directives are processed in the order in which they appear in the configuration, it matters where the inherited directives are placed when the complete configuration is interpreted.

As it happens, “parent” rules are places after “child” rules — e.g., server-level rules are inherited by a virtual host after the rules defined in the virtual host container.  This behavior is consistent with how Apache scopes directives.  But you do have to be careful about conflicting rules, particularly rules that match any URL, for example:

RewriteRule ^/.* - [G]

If such a “catch-all” rule appears in your virtual host configuration, then no RewriteRule or RewriteCond directives from your server context will actually be effective in the virtual host context.  This misconfiguration has bitten me a few times, and can be confusing if you’ve never encountered it before.

December 11, 2008

AliasMatch gotcha

Filed under: Apache — Tags: — David Chandek-Stark @ 1:50 pm

I don’t use Apache’s AliasMatch directive often, and when I do, I tend to use it incorrectly on the first try for some strange reason.

Wrong – infinite loop!

AliasMatch ^/apps/([^/]+)/media/
            /opt/django/apps/$1/media/

Right

AliasMatch ^/apps/([^/]+)/media/(.+)
            /opt/django/apps/$1/media/$2

December 5, 2008

Authenticated access to directory indexes in Apache

Filed under: Apache, code — Tags: , — David Chandek-Stark @ 2:18 pm

You don’t want your media directories (images, css, javascript) to be anonymously browseable, right? But wouldn’t it be nice if you could browse them? Here’s how to do it:

<Directory /path/to/media>
    Options +Indexes
    Order Deny,Allow
    Allow from all
    Satisfy all
    <Files index.html>
        [authorization directives]
    </Files>
</Directory>

Depending on how your authentication mechanism works, you may also have to add a RewriteRule directive to deal with an explicit request for index.html:

RewriteRule ^/url/to/media/(.*/)?index.html$ /url/to/media/$1 [R,L]

In my case, using Shibboleth and mod_shib, authentication takes place on an external site and then redirects the client back. I’m guessing that because mod_dir is internally rewriting the URL from */ to */index.html, mod_shib is not handed the “original” URL (with just the trailing slash), but the DirectoryIndex URL.

Blog at WordPress.com.