Perhaps your web server is providing the correct SCRIPT_NAME, and the problem is introduced in Publisher.process(), which attempts to work around a common, similar SCRIPT_NAME/PATH_INFO problem in a way that would make matters worse for your setup. Here's the code I am talking about: def process(self, stdin, env): """ Return a Hit with a complete response. Subclasses that want to customize the Hit class may do so by overriding this method. """ if env.get('SCRIPT_NAME') and env.get('PATH_INFO') == '': # The "script" here is your QP application, so the SCRIPT_NAME # should be the part of the url, after the host name, that # causes requests to be handled by your QP application. # The PATH_INFO part of the path after the SCRIPT_NAME. # We expect applications running at the top of the URL space # to get requests where the SCRIPT_NAME is the empty string # and the PATH_INFO starts with a '/'. # Your HTTP server is not providing the expected CGI environment. # The full path part of the URL is being put in the SCRIPT_NAME. # We'll try to make it work anyway, but we are assuming here # that your application is running at the top of your URL space. # If you want your application to run somewhere else in your URL # space, you must change your server so that it provides the # correct environment variables. Alternatively, your publisher # class can override this method and hack the environment as # needed to fit QP's expectations. env['PATH_INFO'] = env['SCRIPT_NAME'] env['SCRIPT_NAME'] = "" hit = Hit(stdin, env) self.process_hit(hit) return hit In your case, I think you could try overriding this method and changing any empty PATH_INFO to "/" and removing the "if" statement that appears above. Even easier, perhaps, would be to put a redirect in your web server config so that '/app.cgi' always redirects to '/app.cgi/' before qp sees it.