[Zope3-Users] Re: Is this a bug of HTTP response's head handling? (publisherhttpserver.py)

Simon Hang hangzhiyun at gmail.com
Wed Sep 20 19:03:53 EDT 2006


How about below changes?

in httptask.py

    def prepareResponseHeaders(self):
        version = self.version
        # Figure out whether the connection should be closed.
        connection = self.request_data.headers.get('CONNECTION', '').lower()
        close_it = 0
        response_headers = self.response_headers

        if version == '1.0':
            if connection == 'keep-alive':
                if not ('Content-Length' in response_headers):
                    close_it = 1
                else:
                    response_headers['Connection'] = 'Keep-Alive'
            else:
                close_it = 1
        elif version == '1.1':
            #insert by Simon
            thisflag = False
            for each in self.accumulated_headers:
                if each.lower() == 'connection: keep-alive':
                    thisflag = True
                    break
            if thisflag == False:
                close_it = 1
            #end of insert
            if connection == 'close':
                close_it = 1
            elif 'Transfer-Encoding' in response_headers:
                if not response_headers['Transfer-Encoding'] == 'chunked':
                    close_it = 1
            elif self.status == '304':
                # Replying with headers only.
                pass
            #insert by simon
            elif not ('Content-Length' in response_headers):
                thisflag = False
                for each in self.accumulated_headers:
                    if each[:14].upper() == 'CONTENT-LENGTH':
                        thisflag = True
                        break
                if thisflag == False: #only CONTENT_LENGTH not exist in
accumulated headers too

              #end of insert
                    close_it = 1
        else:
            # Close if unrecognized HTTP version.
            close_it = 1

        self.close_on_finish = close_it
        if close_it:
            self.response_headers['Connection'] = 'close'



On 9/19/06, Simon Hang <hangzhiyun at gmail.com> wrote:
>
>  Dear all,
>
> While I was exploring my options to implement NTLM authentication, I found
> some strange behavior of Zope HTTP server.
>
> in zope.server.http.wsgihttpserver.WSGIHTTPServer,
> It use below function to handle response's head:
>
>         def start_response(status, headers):
>             # Prepare the headers for output
>             status, reason = re.match('([0-9]*) (.*)', status).groups()
>             task.setResponseStatus(status, reason)
>             task.appendResponseHeaders(['%s: %s' % i for i in headers])
>
>             # Return the write method used to write the response data.
>             return fakeWrite
>
> The result is all response's head from the content part of program will be
> stored in task.accumulated_headers. See below function from
> zope.server.http.httptask.HTTPTask.
>
>     def appendResponseHeaders(self, lst):
>         """See zope.publisher.interfaces.http.IHeaderOutput"""
>         accum = self.accumulated_headers
>         if accum is None:
>             self.accumulated_headers = accum = []
>         accum.extend(lst)
>
> But, the problem is while httptask to determin whether to close the
> connection or not, it use below code. The code is only checking
> self.response_headers which has nothing to do with the response our
> application generated. So zope ends up to disconnect connection for each
> single request.
>
>    def prepareResponseHeaders(self):
>         version = self.version
>         # Figure out whether the connection should be closed.
>         connection = self.request_data.headers.get('CONNECTION',
> '').lower()
>         close_it = 0
>         response_headers = self.response_headers
>
>         if version == '1.0':
>             if connection == 'keep-alive':
>                 if not ('Content-Length' in response_headers):
>                     close_it = 1
>                 else:
>                     response_headers['Connection'] = 'Keep-Alive'
>             else:
>                 close_it = 1
>         elif version == '1.1':
>             thisflag = False
>
>             if connection == 'close':
>                 close_it = 1
>             elif 'Transfer-Encoding' in response_headers:
>                 if not response_headers['Transfer-Encoding'] == 'chunked':
>                     close_it = 1
>             elif self.status == '304':
>                 # Replying with headers only.
>                 pass
>             elif not ('Content-Length' in response_headers):
>                 close_it = 1
>         else:
>             # Close if unrecognized HTTP version.
>             close_it = 1
>
>         self.close_on_finish = close_it
>         if close_it:
>             self.response_headers['Connection'] = 'close'
>
>
> Can somebody tell me why the thing is implement like this, is there
> special reason to do this? Or can we change it a little bit to let zope
> support persistence connection?
>
> Thanks,
> Simon
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.zope.org/pipermail/zope3-users/attachments/20060921/c4c34631/attachment-0001.htm


More information about the Zope3-users mailing list