Apache2 + RewriteMap + Python - when returning "NULL" apache hangs

[SOLVED: see solution below.]

I am having a problem writing a program RewriteMap

(using Python). I have a directive RewriteMap

pointing to a Python script that determines if the required URL needs to be redirected to a different location.

When the script outputs a line terminated by a line break, Apache redirects accordingly. However, when the script outputs NULL

(no line breaks), Apache hangs and subsequent HTTP requests are effectively ignored.

There are no errors in the error log. The rewrite log shows only pass through

followed by redirect

then only pass through

when the NULL

script returns. Subsequent requests also show only pass through

.

Also, replacing stdout

with os.fdopen(sys.stdout.fileno(), 'w', 0)

to set the buffer length to zero didn't help.

Any help would be greatly appreciated. Thank you in advance.

/etc/apache2/httpd.conf

[...]
RewriteLock /tmp/apache_rewrite.lock

      

/ etc / apache2 / sites-available / default

<VirtualHost *:80>
  [...]
  RewriteEngine on
  RewriteLogLevel 1
  RewriteLog /var/www/logs/rewrite.log
  RewriteMap remap prg:/var/www/remap.py
  [...]
</VirtualHost>

      

/var/www/webroot/.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*_.*) /${remap:$1} [R=301]

      

/var/www/remap.py

#!/usr/bin/python

import sys

def getRedirect(str):
  new_url = None
  # if url needs to be redirected, put this value in new_url
  # otherwise new_url remains None
  return new_url

while True:
  request = sys.stdin.readline().strip()
  response = getRedirect(request)
  if response:
    sys.stdout.write(response + '\n')
  else:
    sys.stdout.write('NULL')
  sys.stdout.flush()

      

+2


source to share


2 answers


You should return one new line, not "NULL".

Apache waits for a new line to know when the URL has been rewritten to the end. If your script doesn't post a newline, Apache waits forever.

So, just change return ('NULL')

to return ('NULL\n')

, then redirect to /. If you don't want this to happen, ask the program to return the desired URL if there is no match on the map.



If you don't want to redirect if there is no match I would:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond (${remap:$1}) !NULL
RewriteRule (.*_.*) /%1 [R=301]

      

Use match in RewriteCond (this will work with NULL of course). But given your problem, this looks like the right solution.

+5


source


The best solution I've come to is to return the RewriteMap script to the new url or '__NULL__\n'

if no redirect is required and store that value in the ENV variable. Then check the ENV variable for !__NULL__

and redirect. See below .htaccess

file.

Also, if anyone is planning to do something like this, inside a Python script I have wrapped it quite a bit in a try / except block to prevent the script from dying (in my case due to a file / database read failed) and subsequent requests are ignored.

/var/www/webroot/.htaccess

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ - [E=REMAP_RESULT:${remap:$1},NS]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{ENV:REMAP_RESULT} !^__NULL__$
RewriteRule ^(.+)$ /%{ENV:REMAP_RESULT} [R=301,L]

      

/var/www/remap.py



#!/usr/bin/python

import sys

def getRedirect(str):
  try:  # to prevent the script from dying on any errors
    new_url = str
    # if url needs to be redirected, put this value in new_url
    # otherwise new_url remains None
    if new_url == str: new_url = '__NULL__'
    return new_url
  except:
    return '__NULL__'

while True:
  request = sys.stdin.readline().strip()
  response = getRedirect(request)
  sys.stdout.write(response + '\n')
  sys.stdout.flush()

      

Vinko, you definitely helped me figure this out. If I had more experience with stackoverflow

, you would get ^

from me. Thank.

I hope this post helps someone who is facing a similar issue in the future.

Cheers, Andrew

+2


source







All Articles