Some docstring updates
[ganeti-local] / lib / http / __init__.py
1 #
2 #
3
4 # Copyright (C) 2007, 2008 Google Inc.
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20
21 """HTTP module.
22
23 """
24
25 import logging
26 import mimetools
27 import OpenSSL
28 import select
29 import socket
30 import errno
31
32 from cStringIO import StringIO
33
34 from ganeti import constants
35 from ganeti import serializer
36 from ganeti import utils
37
38
39 HTTP_GANETI_VERSION = "Ganeti %s" % constants.RELEASE_VERSION
40
41 HTTP_OK = 200
42 HTTP_NO_CONTENT = 204
43 HTTP_NOT_MODIFIED = 304
44
45 HTTP_0_9 = "HTTP/0.9"
46 HTTP_1_0 = "HTTP/1.0"
47 HTTP_1_1 = "HTTP/1.1"
48
49 HTTP_GET = "GET"
50 HTTP_HEAD = "HEAD"
51 HTTP_POST = "POST"
52 HTTP_PUT = "PUT"
53 HTTP_DELETE = "DELETE"
54
55 HTTP_ETAG = "ETag"
56 HTTP_HOST = "Host"
57 HTTP_SERVER = "Server"
58 HTTP_DATE = "Date"
59 HTTP_USER_AGENT = "User-Agent"
60 HTTP_CONTENT_TYPE = "Content-Type"
61 HTTP_CONTENT_LENGTH = "Content-Length"
62 HTTP_CONNECTION = "Connection"
63 HTTP_KEEP_ALIVE = "Keep-Alive"
64 HTTP_WWW_AUTHENTICATE = "WWW-Authenticate"
65 HTTP_AUTHORIZATION = "Authorization"
66 HTTP_AUTHENTICATION_INFO = "Authentication-Info"
67 HTTP_ALLOW = "Allow"
68
69 _SSL_UNEXPECTED_EOF = "Unexpected EOF"
70
71 # Socket operations
72 (SOCKOP_SEND,
73  SOCKOP_RECV,
74  SOCKOP_SHUTDOWN,
75  SOCKOP_HANDSHAKE) = range(4)
76
77 # send/receive quantum
78 SOCK_BUF_SIZE = 32768
79
80
81 class HttpError(Exception):
82   """Internal exception for HTTP errors.
83
84   This should only be used for internal error reporting.
85
86   """
87
88
89 class HttpConnectionClosed(Exception):
90   """Internal exception for a closed connection.
91
92   This should only be used for internal error reporting. Only use
93   it if there's no other way to report this condition.
94
95   """
96
97
98 class HttpSessionHandshakeUnexpectedEOF(HttpError):
99   """Internal exception for errors during SSL handshake.
100
101   This should only be used for internal error reporting.
102
103   """
104
105
106 class HttpSocketTimeout(Exception):
107   """Internal exception for socket timeouts.
108
109   This should only be used for internal error reporting.
110
111   """
112
113
114 class HttpException(Exception):
115   code = None
116   message = None
117
118   def __init__(self, message=None, headers=None):
119     Exception.__init__(self)
120     self.message = message
121     self.headers = headers
122
123
124 class HttpBadRequest(HttpException):
125   """400 Bad Request
126
127   RFC2616, 10.4.1: The request could not be understood by the server
128   due to malformed syntax. The client SHOULD NOT repeat the request
129   without modifications.
130
131   """
132   code = 400
133
134
135 class HttpUnauthorized(HttpException):
136   """401 Unauthorized
137
138   RFC2616, section 10.4.2: The request requires user
139   authentication. The response MUST include a WWW-Authenticate header
140   field (section 14.47) containing a challenge applicable to the
141   requested resource.
142
143   """
144   code = 401
145
146
147 class HttpForbidden(HttpException):
148   """403 Forbidden
149
150   RFC2616, 10.4.4: The server understood the request, but is refusing
151   to fulfill it.  Authorization will not help and the request SHOULD
152   NOT be repeated.
153
154   """
155   code = 403
156
157
158 class HttpNotFound(HttpException):
159   """404 Not Found
160
161   RFC2616, 10.4.5: The server has not found anything matching the
162   Request-URI.  No indication is given of whether the condition is
163   temporary or permanent.
164
165   """
166   code = 404
167
168
169 class HttpMethodNotAllowed(HttpException):
170   """405 Method Not Allowed
171
172   RFC2616, 10.4.6: The method specified in the Request-Line is not
173   allowed for the resource identified by the Request-URI. The response
174   MUST include an Allow header containing a list of valid methods for
175   the requested resource.
176
177   """
178   code = 405
179
180
181 class HttpRequestTimeout(HttpException):
182   """408 Request Timeout
183
184   RFC2616, 10.4.9: The client did not produce a request within the
185   time that the server was prepared to wait. The client MAY repeat the
186   request without modifications at any later time.
187
188   """
189   code = 408
190
191
192 class HttpConflict(HttpException):
193   """409 Conflict
194
195   RFC2616, 10.4.10: The request could not be completed due to a
196   conflict with the current state of the resource. This code is only
197   allowed in situations where it is expected that the user might be
198   able to resolve the conflict and resubmit the request.
199
200   """
201   code = 409
202
203
204 class HttpGone(HttpException):
205   """410 Gone
206
207   RFC2616, 10.4.11: The requested resource is no longer available at
208   the server and no forwarding address is known. This condition is
209   expected to be considered permanent.
210
211   """
212   code = 410
213
214
215 class HttpLengthRequired(HttpException):
216   """411 Length Required
217
218   RFC2616, 10.4.12: The server refuses to accept the request without a
219   defined Content-Length. The client MAY repeat the request if it adds
220   a valid Content-Length header field containing the length of the
221   message-body in the request message.
222
223   """
224   code = 411
225
226
227 class HttpPreconditionFailed(HttpException):
228   """412 Precondition Failed
229
230   RFC2616, 10.4.13: The precondition given in one or more of the
231   request-header fields evaluated to false when it was tested on the
232   server.
233
234   """
235   code = 412
236
237
238 class HttpInternalServerError(HttpException):
239   """500 Internal Server Error
240
241   RFC2616, 10.5.1: The server encountered an unexpected condition
242   which prevented it from fulfilling the request.
243
244   """
245   code = 500
246
247
248 class HttpNotImplemented(HttpException):
249   """501 Not Implemented
250
251   RFC2616, 10.5.2: The server does not support the functionality
252   required to fulfill the request.
253
254   """
255   code = 501
256
257
258 class HttpServiceUnavailable(HttpException):
259   """503 Service Unavailable
260
261   RFC2616, 10.5.4: The server is currently unable to handle the
262   request due to a temporary overloading or maintenance of the server.
263
264   """
265   code = 503
266
267
268 class HttpVersionNotSupported(HttpException):
269   """505 HTTP Version Not Supported
270
271   RFC2616, 10.5.6: The server does not support, or refuses to support,
272   the HTTP protocol version that was used in the request message.
273
274   """
275   code = 505
276
277
278 class HttpJsonConverter:
279   CONTENT_TYPE = "application/json"
280
281   def Encode(self, data):
282     return serializer.DumpJson(data)
283
284   def Decode(self, data):
285     return serializer.LoadJson(data)
286
287
288 def WaitForSocketCondition(sock, event, timeout):
289   """Waits for a condition to occur on the socket.
290
291   @type sock: socket
292   @param sock: Wait for events on this socket
293   @type event: int
294   @param event: ORed condition (see select module)
295   @type timeout: float or None
296   @param timeout: Timeout in seconds
297   @rtype: int or None
298   @return: None for timeout, otherwise occured conditions
299
300   """
301   check = (event | select.POLLPRI |
302            select.POLLNVAL | select.POLLHUP | select.POLLERR)
303
304   if timeout is not None:
305     # Poller object expects milliseconds
306     timeout *= 1000
307
308   poller = select.poll()
309   poller.register(sock, event)
310   try:
311     while True:
312       # TODO: If the main thread receives a signal and we have no timeout, we
313       # could wait forever. This should check a global "quit" flag or
314       # something every so often.
315       io_events = poller.poll(timeout)
316       if not io_events:
317         # Timeout
318         return None
319       for (evfd, evcond) in io_events:
320         if evcond & check:
321           return evcond
322   finally:
323     poller.unregister(sock)
324
325
326 def SocketOperation(sock, op, arg1, timeout):
327   """Wrapper around socket functions.
328
329   This function abstracts error handling for socket operations, especially
330   for the complicated interaction with OpenSSL.
331
332   @type sock: socket
333   @param sock: Socket for the operation
334   @type op: int
335   @param op: Operation to execute (SOCKOP_* constants)
336   @type arg1: any
337   @param arg1: Parameter for function (if needed)
338   @type timeout: None or float
339   @param timeout: Timeout in seconds or None
340   @return: Return value of socket function
341
342   """
343   # TODO: event_poll/event_check/override
344   if op in (SOCKOP_SEND, SOCKOP_HANDSHAKE):
345     event_poll = select.POLLOUT
346     event_check = select.POLLOUT
347
348   elif op == SOCKOP_RECV:
349     event_poll = select.POLLIN
350     event_check = select.POLLIN | select.POLLPRI
351
352   elif op == SOCKOP_SHUTDOWN:
353     event_poll = None
354     event_check = None
355
356     # The timeout is only used when OpenSSL requests polling for a condition.
357     # It is not advisable to have no timeout for shutdown.
358     assert timeout
359
360   else:
361     raise AssertionError("Invalid socket operation")
362
363   # Handshake is only supported by SSL sockets
364   if (op == SOCKOP_HANDSHAKE and
365       not isinstance(sock, OpenSSL.SSL.ConnectionType)):
366     return
367
368   # No override by default
369   event_override = 0
370
371   while True:
372     # Poll only for certain operations and when asked for by an override
373     if event_override or op in (SOCKOP_SEND, SOCKOP_RECV, SOCKOP_HANDSHAKE):
374       if event_override:
375         wait_for_event = event_override
376       else:
377         wait_for_event = event_poll
378
379       event = WaitForSocketCondition(sock, wait_for_event, timeout)
380       if event is None:
381         raise HttpSocketTimeout()
382
383       if (op == SOCKOP_RECV and
384           event & (select.POLLNVAL | select.POLLHUP | select.POLLERR)):
385         return ""
386
387       if not event & wait_for_event:
388         continue
389
390     # Reset override
391     event_override = 0
392
393     try:
394       try:
395         if op == SOCKOP_SEND:
396           return sock.send(arg1)
397
398         elif op == SOCKOP_RECV:
399           return sock.recv(arg1)
400
401         elif op == SOCKOP_SHUTDOWN:
402           if isinstance(sock, OpenSSL.SSL.ConnectionType):
403             # PyOpenSSL's shutdown() doesn't take arguments
404             return sock.shutdown()
405           else:
406             return sock.shutdown(arg1)
407
408         elif op == SOCKOP_HANDSHAKE:
409           return sock.do_handshake()
410
411       except OpenSSL.SSL.WantWriteError:
412         # OpenSSL wants to write, poll for POLLOUT
413         event_override = select.POLLOUT
414         continue
415
416       except OpenSSL.SSL.WantReadError:
417         # OpenSSL wants to read, poll for POLLIN
418         event_override = select.POLLIN | select.POLLPRI
419         continue
420
421       except OpenSSL.SSL.WantX509LookupError:
422         continue
423
424       except OpenSSL.SSL.ZeroReturnError, err:
425         # SSL Connection has been closed. In SSL 3.0 and TLS 1.0, this only
426         # occurs if a closure alert has occurred in the protocol, i.e. the
427         # connection has been closed cleanly. Note that this does not
428         # necessarily mean that the transport layer (e.g. a socket) has been
429         # closed.
430         if op == SOCKOP_SEND:
431           # Can happen during a renegotiation
432           raise HttpConnectionClosed(err.args)
433         elif op == SOCKOP_RECV:
434           return ""
435
436         # SSL_shutdown shouldn't return SSL_ERROR_ZERO_RETURN
437         raise socket.error(err.args)
438
439       except OpenSSL.SSL.SysCallError, err:
440         if op == SOCKOP_SEND:
441           # arg1 is the data when writing
442           if err.args and err.args[0] == -1 and arg1 == "":
443             # errors when writing empty strings are expected
444             # and can be ignored
445             return 0
446
447         if err.args == (-1, _SSL_UNEXPECTED_EOF):
448           if op == SOCKOP_RECV:
449             return ""
450           elif op == SOCKOP_HANDSHAKE:
451             # Can happen if peer disconnects directly after the connection is
452             # opened.
453             raise HttpSessionHandshakeUnexpectedEOF(err.args)
454
455         raise socket.error(err.args)
456
457       except OpenSSL.SSL.Error, err:
458         raise socket.error(err.args)
459
460     except socket.error, err:
461       if err.args and err.args[0] == errno.EAGAIN:
462         # Ignore EAGAIN
463         continue
464
465       raise
466
467
468 def ShutdownConnection(sock, close_timeout, write_timeout, msgreader, force):
469   """Closes the connection.
470
471   @type sock: socket
472   @param sock: Socket to be shut down
473   @type close_timeout: float
474   @param close_timeout: How long to wait for the peer to close
475       the connection
476   @type write_timeout: float
477   @param write_timeout: Write timeout for shutdown
478   @type msgreader: http.HttpMessageReader
479   @param msgreader: Request message reader, used to determine whether
480       peer should close connection
481   @type force: bool
482   @param force: Whether to forcibly close the connection without
483       waiting for peer
484
485   """
486   #print msgreader.peer_will_close, force
487   if msgreader and msgreader.peer_will_close and not force:
488     # Wait for peer to close
489     try:
490       # Check whether it's actually closed
491       if not SocketOperation(sock, SOCKOP_RECV, 1, close_timeout):
492         return
493     except (socket.error, HttpError, HttpSocketTimeout):
494       # Ignore errors at this stage
495       pass
496
497   # Close the connection from our side
498   try:
499     # We don't care about the return value, see NOTES in SSL_shutdown(3).
500     SocketOperation(sock, SOCKOP_SHUTDOWN, socket.SHUT_RDWR,
501                     write_timeout)
502   except HttpSocketTimeout:
503     raise HttpError("Timeout while shutting down connection")
504   except socket.error, err:
505     # Ignore ENOTCONN
506     if not (err.args and err.args[0] == errno.ENOTCONN):
507       raise HttpError("Error while shutting down connection: %s" % err)
508
509
510 def Handshake(sock, write_timeout):
511   """Shakes peer's hands.
512
513   @type sock: socket
514   @param sock: Socket to be shut down
515   @type write_timeout: float
516   @param write_timeout: Write timeout for handshake
517
518   """
519   try:
520     return SocketOperation(sock, SOCKOP_HANDSHAKE, None, write_timeout)
521   except HttpSocketTimeout:
522     raise HttpError("Timeout during SSL handshake")
523   except socket.error, err:
524     raise HttpError("Error in SSL handshake: %s" % err)
525
526
527 class HttpSslParams(object):
528   """Data class for SSL key and certificate.
529
530   """
531   def __init__(self, ssl_key_path, ssl_cert_path):
532     """Initializes this class.
533
534     @type ssl_key_path: string
535     @param ssl_key_path: Path to file containing SSL key in PEM format
536     @type ssl_cert_path: string
537     @param ssl_cert_path: Path to file containing SSL certificate
538         in PEM format
539
540     """
541     self.ssl_key_pem = utils.ReadFile(ssl_key_path)
542     self.ssl_cert_pem = utils.ReadFile(ssl_cert_path)
543
544   def GetKey(self):
545     return OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
546                                           self.ssl_key_pem)
547
548   def GetCertificate(self):
549     return OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
550                                            self.ssl_cert_pem)
551
552
553 class HttpBase(object):
554   """Base class for HTTP server and client.
555
556   """
557   def __init__(self):
558     self.using_ssl = None
559     self._ssl_params = None
560     self._ssl_key = None
561     self._ssl_cert = None
562
563   def _CreateSocket(self, ssl_params, ssl_verify_peer):
564     """Creates a TCP socket and initializes SSL if needed.
565
566     @type ssl_params: HttpSslParams
567     @param ssl_params: SSL key and certificate
568     @type ssl_verify_peer: bool
569     @param ssl_verify_peer: Whether to require client certificate
570         and compare it with our certificate
571
572     """
573     self._ssl_params = ssl_params
574
575     sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
576
577     # Should we enable SSL?
578     self.using_ssl = ssl_params is not None
579
580     if not self.using_ssl:
581       return sock
582
583     self._ssl_key = ssl_params.GetKey()
584     self._ssl_cert = ssl_params.GetCertificate()
585
586     ctx = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
587     ctx.set_options(OpenSSL.SSL.OP_NO_SSLv2)
588
589     ctx.use_privatekey(self._ssl_key)
590     ctx.use_certificate(self._ssl_cert)
591     ctx.check_privatekey()
592
593     if ssl_verify_peer:
594       ctx.set_verify(OpenSSL.SSL.VERIFY_PEER |
595                      OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
596                      self._SSLVerifyCallback)
597
598     return OpenSSL.SSL.Connection(ctx, sock)
599
600   def _SSLVerifyCallback(self, conn, cert, errnum, errdepth, ok):
601     """Verify the certificate provided by the peer
602
603     We only compare fingerprints. The client must use the same certificate as
604     we do on our side.
605
606     """
607     assert self._ssl_params, "SSL not initialized"
608
609     return (self._ssl_cert.digest("sha1") == cert.digest("sha1") and
610             self._ssl_cert.digest("md5") == cert.digest("md5"))
611
612
613 class HttpMessage(object):
614   """Data structure for HTTP message.
615
616   """
617   def __init__(self):
618     self.start_line = None
619     self.headers = None
620     self.body = None
621     self.decoded_body = None
622
623
624 class HttpClientToServerStartLine(object):
625   """Data structure for HTTP request start line.
626
627   """
628   def __init__(self, method, path, version):
629     self.method = method
630     self.path = path
631     self.version = version
632
633   def __str__(self):
634     return "%s %s %s" % (self.method, self.path, self.version)
635
636
637 class HttpServerToClientStartLine(object):
638   """Data structure for HTTP response start line.
639
640   """
641   def __init__(self, version, code, reason):
642     self.version = version
643     self.code = code
644     self.reason = reason
645
646   def __str__(self):
647     return "%s %s %s" % (self.version, self.code, self.reason)
648
649
650 class HttpMessageWriter(object):
651   """Writes an HTTP message to a socket.
652
653   """
654   def __init__(self, sock, msg, write_timeout):
655     """Initializes this class and writes an HTTP message to a socket.
656
657     @type sock: socket
658     @param sock: Socket to be written to
659     @type msg: http.HttpMessage
660     @param msg: HTTP message to be written
661     @type write_timeout: float
662     @param write_timeout: Write timeout for socket
663
664     """
665     self._msg = msg
666
667     self._PrepareMessage()
668
669     buf = self._FormatMessage()
670
671     pos = 0
672     end = len(buf)
673     while pos < end:
674       # Send only SOCK_BUF_SIZE bytes at a time
675       data = buf[pos:(pos + SOCK_BUF_SIZE)]
676
677       sent = SocketOperation(sock, SOCKOP_SEND, data, write_timeout)
678
679       # Remove sent bytes
680       pos += sent
681
682     assert pos == end, "Message wasn't sent completely"
683
684   def _PrepareMessage(self):
685     """Prepares the HTTP message by setting mandatory headers.
686
687     """
688     # RFC2616, section 4.3: "The presence of a message-body in a request is
689     # signaled by the inclusion of a Content-Length or Transfer-Encoding header
690     # field in the request's message-headers."
691     if self._msg.body:
692       self._msg.headers[HTTP_CONTENT_LENGTH] = len(self._msg.body)
693
694   def _FormatMessage(self):
695     """Serializes the HTTP message into a string.
696
697     """
698     buf = StringIO()
699
700     # Add start line
701     buf.write(str(self._msg.start_line))
702     buf.write("\r\n")
703
704     # Add headers
705     if self._msg.start_line.version != HTTP_0_9:
706       for name, value in self._msg.headers.iteritems():
707         buf.write("%s: %s\r\n" % (name, value))
708
709     buf.write("\r\n")
710
711     # Add message body if needed
712     if self.HasMessageBody():
713       buf.write(self._msg.body)
714
715     elif self._msg.body:
716       logging.warning("Ignoring message body")
717
718     return buf.getvalue()
719
720   def HasMessageBody(self):
721     """Checks whether the HTTP message contains a body.
722
723     Can be overriden by subclasses.
724
725     """
726     return bool(self._msg.body)
727
728
729 class HttpMessageReader(object):
730   """Reads HTTP message from socket.
731
732   """
733   # Length limits
734   START_LINE_LENGTH_MAX = None
735   HEADER_LENGTH_MAX = None
736
737   # Parser state machine
738   PS_START_LINE = "start-line"
739   PS_HEADERS = "headers"
740   PS_BODY = "entity-body"
741   PS_COMPLETE = "complete"
742
743   def __init__(self, sock, msg, read_timeout):
744     """Reads an HTTP message from a socket.
745
746     @type sock: socket
747     @param sock: Socket to be read from
748     @type msg: http.HttpMessage
749     @param msg: Object for the read message
750     @type read_timeout: float
751     @param read_timeout: Read timeout for socket
752
753     """
754     self.sock = sock
755     self.msg = msg
756
757     self.start_line_buffer = None
758     self.header_buffer = StringIO()
759     self.body_buffer = StringIO()
760     self.parser_status = self.PS_START_LINE
761     self.content_length = None
762     self.peer_will_close = None
763
764     buf = ""
765     eof = False
766     while self.parser_status != self.PS_COMPLETE:
767       # TODO: Don't read more than necessary (Content-Length), otherwise
768       # data might be lost and/or an error could occur
769       data = SocketOperation(sock, SOCKOP_RECV, SOCK_BUF_SIZE, read_timeout)
770
771       if data:
772         buf += data
773       else:
774         eof = True
775
776       # Do some parsing and error checking while more data arrives
777       buf = self._ContinueParsing(buf, eof)
778
779       # Must be done only after the buffer has been evaluated
780       # TODO: Connection-length < len(data read) and connection closed
781       if (eof and
782           self.parser_status in (self.PS_START_LINE,
783                                  self.PS_HEADERS)):
784         raise HttpError("Connection closed prematurely")
785
786     # Parse rest
787     buf = self._ContinueParsing(buf, True)
788
789     assert self.parser_status == self.PS_COMPLETE
790     assert not buf, "Parser didn't read full response"
791
792     msg.body = self.body_buffer.getvalue()
793
794     # TODO: Content-type, error handling
795     if msg.body:
796       msg.decoded_body = HttpJsonConverter().Decode(msg.body)
797     else:
798       msg.decoded_body = None
799
800     if msg.decoded_body:
801       logging.debug("Message body: %s", msg.decoded_body)
802
803   def _ContinueParsing(self, buf, eof):
804     """Main function for HTTP message state machine.
805
806     @type buf: string
807     @param buf: Receive buffer
808     @type eof: bool
809     @param eof: Whether we've reached EOF on the socket
810     @rtype: string
811     @return: Updated receive buffer
812
813     """
814     # TODO: Use offset instead of slicing when possible
815     if self.parser_status == self.PS_START_LINE:
816       # Expect start line
817       while True:
818         idx = buf.find("\r\n")
819
820         # RFC2616, section 4.1: "In the interest of robustness, servers SHOULD
821         # ignore any empty line(s) received where a Request-Line is expected.
822         # In other words, if the server is reading the protocol stream at the
823         # beginning of a message and receives a CRLF first, it should ignore
824         # the CRLF."
825         if idx == 0:
826           # TODO: Limit number of CRLFs/empty lines for safety?
827           buf = buf[:2]
828           continue
829
830         if idx > 0:
831           self.start_line_buffer = buf[:idx]
832
833           self._CheckStartLineLength(len(self.start_line_buffer))
834
835           # Remove status line, including CRLF
836           buf = buf[idx + 2:]
837
838           self.msg.start_line = self.ParseStartLine(self.start_line_buffer)
839
840           self.parser_status = self.PS_HEADERS
841         else:
842           # Check whether incoming data is getting too large, otherwise we just
843           # fill our read buffer.
844           self._CheckStartLineLength(len(buf))
845
846         break
847
848     # TODO: Handle messages without headers
849     if self.parser_status == self.PS_HEADERS:
850       # Wait for header end
851       idx = buf.find("\r\n\r\n")
852       if idx >= 0:
853         self.header_buffer.write(buf[:idx + 2])
854
855         self._CheckHeaderLength(self.header_buffer.tell())
856
857         # Remove headers, including CRLF
858         buf = buf[idx + 4:]
859
860         self._ParseHeaders()
861
862         self.parser_status = self.PS_BODY
863       else:
864         # Check whether incoming data is getting too large, otherwise we just
865         # fill our read buffer.
866         self._CheckHeaderLength(len(buf))
867
868     if self.parser_status == self.PS_BODY:
869       # TODO: Implement max size for body_buffer
870       self.body_buffer.write(buf)
871       buf = ""
872
873       # Check whether we've read everything
874       #
875       # RFC2616, section 4.4: "When a message-body is included with a message,
876       # the transfer-length of that body is determined by one of the following
877       # [...] 5. By the server closing the connection. (Closing the connection
878       # cannot be used to indicate the end of a request body, since that would
879       # leave no possibility for the server to send back a response.)"
880       #
881       # TODO: Error when buffer length > Content-Length header
882       if (eof or
883           self.content_length is None or
884           (self.content_length is not None and
885            self.body_buffer.tell() >= self.content_length)):
886         self.parser_status = self.PS_COMPLETE
887
888     return buf
889
890   def _CheckStartLineLength(self, length):
891     """Limits the start line buffer size.
892
893     @type length: int
894     @param length: Buffer size
895
896     """
897     if (self.START_LINE_LENGTH_MAX is not None and
898         length > self.START_LINE_LENGTH_MAX):
899       raise HttpError("Start line longer than %d chars" %
900                        self.START_LINE_LENGTH_MAX)
901
902   def _CheckHeaderLength(self, length):
903     """Limits the header buffer size.
904
905     @type length: int
906     @param length: Buffer size
907
908     """
909     if (self.HEADER_LENGTH_MAX is not None and
910         length > self.HEADER_LENGTH_MAX):
911       raise HttpError("Headers longer than %d chars" % self.HEADER_LENGTH_MAX)
912
913   def ParseStartLine(self, start_line):
914     """Parses the start line of a message.
915
916     Must be overriden by subclass.
917
918     @type start_line: string
919     @param start_line: Start line string
920
921     """
922     raise NotImplementedError()
923
924   def _WillPeerCloseConnection(self):
925     """Evaluate whether peer will close the connection.
926
927     @rtype: bool
928     @return: Whether peer will close the connection
929
930     """
931     # RFC2616, section 14.10: "HTTP/1.1 defines the "close" connection option
932     # for the sender to signal that the connection will be closed after
933     # completion of the response. For example,
934     #
935     #        Connection: close
936     #
937     # in either the request or the response header fields indicates that the
938     # connection SHOULD NOT be considered `persistent' (section 8.1) after the
939     # current request/response is complete."
940
941     hdr_connection = self.msg.headers.get(HTTP_CONNECTION, None)
942     if hdr_connection:
943       hdr_connection = hdr_connection.lower()
944
945     # An HTTP/1.1 server is assumed to stay open unless explicitly closed.
946     if self.msg.start_line.version == HTTP_1_1:
947       return (hdr_connection and "close" in hdr_connection)
948
949     # Some HTTP/1.0 implementations have support for persistent connections,
950     # using rules different than HTTP/1.1.
951
952     # For older HTTP, Keep-Alive indicates persistent connection.
953     if self.msg.headers.get(HTTP_KEEP_ALIVE):
954       return False
955
956     # At least Akamai returns a "Connection: Keep-Alive" header, which was
957     # supposed to be sent by the client.
958     if hdr_connection and "keep-alive" in hdr_connection:
959       return False
960
961     return True
962
963   def _ParseHeaders(self):
964     """Parses the headers.
965
966     This function also adjusts internal variables based on header values.
967
968     RFC2616, section 4.3: The presence of a message-body in a request is
969     signaled by the inclusion of a Content-Length or Transfer-Encoding header
970     field in the request's message-headers.
971
972     """
973     # Parse headers
974     self.header_buffer.seek(0, 0)
975     self.msg.headers = mimetools.Message(self.header_buffer, 0)
976
977     self.peer_will_close = self._WillPeerCloseConnection()
978
979     # Do we have a Content-Length header?
980     hdr_content_length = self.msg.headers.get(HTTP_CONTENT_LENGTH, None)
981     if hdr_content_length:
982       try:
983         self.content_length = int(hdr_content_length)
984       except ValueError:
985         self.content_length = None
986       if self.content_length is not None and self.content_length < 0:
987         self.content_length = None
988
989     # if the connection remains open and a content-length was not provided,
990     # then assume that the connection WILL close.
991     if self.content_length is None:
992       self.peer_will_close = True