#6152 closed defect (fixed)
Error handler/helper in IIS is not output but returns CGI error due to missing headers
| Reported by: | Owned by: | Remy Blank | |
|---|---|---|---|
| Priority: | normal | Milestone: | 0.11.3 | 
| Component: | web frontend | Version: | 0.10-stable | 
| Severity: | normal | Keywords: | iis iis6 cgi error mime http header windows 2003 server review | 
| Cc: | Branch: | ||
| Release Notes: | |||
| API Changes: | |||
| Internal Changes: | |||
Description
To work with IIS 6 under Windows Server 2003 the trac.cgi file needs an additional two lines to set the content type headers otherwise IIS will report the following error;
CGI Error The specified CGI application misbehaved by not returning a complete set of HTTP headers.
The relevant portion of the trac.cgi file was changed from this;
    # PATCH IIS6 - start
    import os
    os.environ['TRAC_ENV'] = "mypath"
    # PATCH IIS6 - end
to this;
    # PATCH IIS6 - start
    import os
    print 'Content-type: text/html'
    print
    os.environ['TRAC_ENV'] = "mypath"
    # PATCH IIS6 - end
Doing this enables the script to work under IIS 6 on Windows Server 2003.
Not sure if this is by design as I am new to the trac system but thought it would help others.
Ryan
Attachments (1)
Change History (14)
comment:1 by , 18 years ago
| Summary: | Installation in IIS requires content type specifying → Error handler/helper in IIS is not output but returns CGI error due to missing headers | 
|---|
comment:2 by , 18 years ago
Looks like a regression. I think this has already been fixed some months (years?) ago, after I had a chat with cmlenz.
comment:4 by , 17 years ago
| Keywords: | needinfo removed | 
|---|---|
| Milestone: | → 0.11.3 | 
| Owner: | changed from to | 
I can still reproduce this issue in the case where TRAC_ENV is not set correctly, as it triggers an IOError exception in open_environment() that is not caught anywhere.
by , 17 years ago
| Attachment: | 6152-open-env-error-r7772.patch added | 
|---|
Patch against 0.11-stable catching all exceptions while opening the environment
comment:5 by , 17 years ago
| Keywords: | review added | 
|---|
The patch above catches all exceptions while opening the environment, not only TracError. This ensures that a correct error page is displayed even if the environment is not configured correctly, not only with CGI, but also e.g. with tracd.
Comments welcome.
comment:6 by , 17 years ago
| Component: | general → web frontend | 
|---|
The patch is fine.
A 'message': to_unicode(e.detail) would even be better than a simple 'message': e.detail, as that would call __unicode__ on TracErrors and force a safe conversion to unicode on other Exceptions.
comment:7 by , 17 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | new → closed | 
Thanks for the review. Patch and suggestion applied in [7778].
comment:8 by , 17 years ago
| Resolution: | fixed | 
|---|---|
| Status: | closed → reopened | 
Oops, review incomplete ;-) I've just seen that type was supposed to be either 'TracError' or 'internal', as you can see in the <py:choose test="type"> in trac/template/error.html. Can you check?
As for seeing the actual class name of the exception, to_unicode would take care of this (see patch attachment:t7935-log-exception-unicode-r7778.diff:ticket:7935).
An alternative would be to replace the <py:when test="'internal'"> condition with a <py:otherwise>.
follow-up: 10 comment:9 by , 17 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | reopened → closed | 
Right, good catch. I had erroneously assumed that data['type'] was intended to be the exception type, without checking the error template.
I'm not sure if having to_unicode() prepend the exception type is a good idea, as you most likely don't want that to happen for TracError and derived classes, for example. I tried it (with a check for TracError), and all permission errors started getting a PermissionError: prefix, as PermissionError derives from StandardError and not TracError (any idea why this is the case, BTW?).
IMO, to_unicode(e) should behave mostly like str(e), which doesn't prepend the exception name. I have fixed [7778] to leave type as 'TracError', and prepend the exception name to message if it is not a TracError. This is consistent with the processing of other exceptions in _dispatch_request(). Done in [7782].
comment:10 by , 17 years ago
Replying to rblank:
I'm not sure if having
to_unicode()prepend the exception type is a good idea, as you most likely don't want that to happen forTracErrorand derived classes, for example. I tried it (with a check forTracError), and all permission errors started getting aPermissionError:prefix,
Ok
as
PermissionErrorderives fromStandardErrorand notTracError(any idea why this is the case, BTW?).
No good reason I guess. Before changing it, we should verify the try/catch clauses. The one I had in mind (in source:trunk/trac/web/main.py) already catches PermissionError before TracError, so we would be safe there.
follow-up: 12 comment:11 by , 17 years ago
| Resolution: | fixed | 
|---|---|
| Status: | closed → reopened | 
Not yet there … just seen a regression on #5066 that can be traced to r7782.
Actually e.detail can't even be a TracError, see HTTPException constructor in source:trunk/trac/web/api.py.
Ok with the following fix?
- 
      
trac/web/main.py
42 42 arity 43 43 from trac.util.compat import partial, reversed 44 44 from trac.util.datefmt import format_datetime, http_date, localtz, timezone 45 from trac.util.text import shorten_line, to_unicode 45 from trac.util.text import shorten_line, to_unicode, exception_to_unicode 46 46 from trac.util.translation import _ 47 47 from trac.web.api import * 48 48 from trac.web.chrome import Chrome … … 443 443 title = e.reason 444 444 else: 445 445 title = 'Error: %s' % e.reason 446 message = to_unicode(e.detail)447 if isinstance(e.detail, Exception) and \448 not isinstance(e.detail, TracError):449 message = '%s: %s' % (e.detail.__class__.__name__, message)446 message = e.detail 447 if isinstance(e.detail, Exception): 448 # Note that e.detail can't be a TracError, see HTTPException 449 message = exception_to_unicode(e.detail) 450 450 data = {'title': title, 'type': 'TracError', 'message': message, 451 451 'frames': [], 'traceback': None} 452 452 if e.code == 403 and req.authname == 'anonymous':  - 
      
trac/util/text.py
63 63 except UnicodeError: 64 64 return unicode(text, locale.getpreferredencoding(), 'replace') 65 65 66 def exception_to_unicode(e): 67 return '%s: %s' % (e.__class__.__name__, to_unicode(e)) 68 66 69 def javascript_quote(text): 67 70 """Quote strings for inclusion in javascript""" 68 71 return text.replace('\\', '\\\\').replace('\r', '\\r') \  
(exception_to_unicode to be reused in various places where we forgot to convert exception to unicode, e.g. #7935)
follow-up: 13 comment:12 by , 17 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | reopened → closed | 
Replying to cboos:
Not yet there … just seen a regression on #5066 that can be traced to r7782.
Argh… All this because I wanted to see the type of the exception. Without that, fixing this ticket would have been a one-liner. Oh well…
Actually e.detail can't even be a TracError, see HTTPException constructor in source:trunk/trac/web/api.py.
I had actually noticed this in my logs, but failed to make the connection.
Ok with the following fix?
Looks good. Applied in [7794]. Thanks!
(One question, though. How on earth did you catch the regression on #5066?)



  
Apologies, the error actually occurred because the line;
was not pointing at a correct path. The error handler then tried to output helpful text which did not appear due to IIS not receiving the headers. Therefore the real fix is to move the lines;
print 'Content-type: text/html' printto the error handling code so that it is displayed to IIS users.