| 1 | # Copyright: 2004-2005 Brian Harring |
|---|
| 2 | # Author(s): Brian Harring (ferringb@gentoo.org) |
|---|
| 3 | # License: GPL2 |
|---|
| 4 | # $Header: /home/cvsrep/pchecker/httpchecker.py,v 1.21 2005/09/25 23:38:03 bharring Exp $ |
|---|
| 5 | |
|---|
| 6 | """http and https checkers.""" |
|---|
| 7 | |
|---|
| 8 | from twisted.web import http, error |
|---|
| 9 | from twisted.python import log, failure |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | class HTTPCheckerClient(http.HTTPClient): |
|---|
| 13 | |
|---|
| 14 | def connectionMade(self): |
|---|
| 15 | """Initialize some vars and start the first check.""" |
|---|
| 16 | http.HTTPClient.connectionMade(self) |
|---|
| 17 | self.count = 0 |
|---|
| 18 | # determine pipelining possibility after first check. |
|---|
| 19 | self.max_piped = 1 |
|---|
| 20 | self.debug = False |
|---|
| 21 | self._startCheck() |
|---|
| 22 | |
|---|
| 23 | def _startCheck(self): |
|---|
| 24 | """Run a single check.""" |
|---|
| 25 | uri = self.factory.getUri() |
|---|
| 26 | if uri is None: |
|---|
| 27 | # all done |
|---|
| 28 | self.transport.loseConnection() |
|---|
| 29 | return |
|---|
| 30 | self.status = [] |
|---|
| 31 | self.sendCommand('HEAD', uri) |
|---|
| 32 | self.sendHeader('Connection', 'Keep-Alive') |
|---|
| 33 | self.sendHeader('Host', '%s:%d' % ( |
|---|
| 34 | self.factory.host, self.factory.port)) |
|---|
| 35 | self.sendHeader('User-Agent', 'exp. SRC_URI checker') |
|---|
| 36 | self.endHeaders() |
|---|
| 37 | self.count += 1 |
|---|
| 38 | |
|---|
| 39 | def lineReceived(self, line): |
|---|
| 40 | """Extra error handling for HTTPClient's lineReceived.""" |
|---|
| 41 | if self.firstLine and len(line.split(None, 1)) < 2: |
|---|
| 42 | log.msg('ignoring a bogus firstLine (I hope) line %r' % line) |
|---|
| 43 | elif not self.firstLine and line and ':' not in line: |
|---|
| 44 | log.msg('ignoring a bogus header (I hope) line %r' % line) |
|---|
| 45 | else: |
|---|
| 46 | http.HTTPClient.lineReceived(self, line) |
|---|
| 47 | |
|---|
| 48 | def setRawMode(self): |
|---|
| 49 | """Override and no-op. |
|---|
| 50 | |
|---|
| 51 | Normally HTTPClient switches to raw mode after receiving the |
|---|
| 52 | header. Since we want to do some more requests we force it to |
|---|
| 53 | stay in line mode. |
|---|
| 54 | """ |
|---|
| 55 | |
|---|
| 56 | def handleStatus(self, version, status, message): |
|---|
| 57 | """Remember our status.""" |
|---|
| 58 | try: |
|---|
| 59 | status = int(status) |
|---|
| 60 | except ValueError: |
|---|
| 61 | pass |
|---|
| 62 | self.version, self.status, self.message = version, status, message |
|---|
| 63 | |
|---|
| 64 | def handleHeader(self, key, val): |
|---|
| 65 | """Check if we can do keepalive if we do not know yet.""" |
|---|
| 66 | if self.count == 1: |
|---|
| 67 | # we don't know yet. |
|---|
| 68 | k = key.lower() |
|---|
| 69 | if k == "keep-alive": |
|---|
| 70 | # yay! let's figure out how many requests... |
|---|
| 71 | for t in val.strip(",").split(): |
|---|
| 72 | try: |
|---|
| 73 | t = t.split("=") |
|---|
| 74 | if t[0].lower() == "max": |
|---|
| 75 | self.max_piped = int(t[1]) |
|---|
| 76 | break |
|---|
| 77 | except (ValueError, IndexError): |
|---|
| 78 | # if something is odd, disable pipelining. |
|---|
| 79 | break |
|---|
| 80 | elif k == "connection" and val.lower() == "close": |
|---|
| 81 | self.max_piped = 0 |
|---|
| 82 | |
|---|
| 83 | def handleEndHeaders(self, *arg): |
|---|
| 84 | """Handle the received headers and do another request if possible.""" |
|---|
| 85 | if self.status == 200: |
|---|
| 86 | self.factory.uriSucceeded() |
|---|
| 87 | else: |
|---|
| 88 | self.factory.uriFailed(failure.Failure( |
|---|
| 89 | error.Error(self.status, self.message))) |
|---|
| 90 | if self.max_piped > self.count: |
|---|
| 91 | # reset us for a new check and run it. |
|---|
| 92 | self.firstLine = 1 |
|---|
| 93 | self.status = [] |
|---|
| 94 | self._startCheck() |
|---|
| 95 | else: |
|---|
| 96 | # request limit reached, drop the connection. |
|---|
| 97 | self.transport.loseConnection() |
|---|
| 98 | |
|---|
| 99 | def handleResponse(self, response): |
|---|
| 100 | """Ignore the response.""" |
|---|