Beispiel #1
0
 def save_test(self):
     """Save a previously run test_id."""
     try:
         # touch the save file so it isn't deleted.
         os.utime(
             os.path.join(save_dir, self.test_id), 
             (
                 nbhttp.now(), 
                 nbhttp.now() + (save_days * 24 * 60 * 60)
             )
         )
         location = "?id=%s" % self.test_id
         if self.descend:
             location = "%s&descend=True" % location
         self.output_hdrs(
             "303 See Other", [
             ("Location", location)
         ])
         self.output_body("Redirecting to the saved test page...")
     except (OSError, IOError):
         self.output_hdrs(
             "500 Internal Server Error", [
             ("Content-Type", "text/html; charset=%s" % charset), 
         ])
         # TODO: better error message (through formatter?)
         self.output_body(
             error_template % "Sorry, I couldn't save that."
         )
     self.body_done()
Beispiel #2
0
 def run(self, done_cb=None):
     """
     Make an asynchronous HTTP request to uri, calling status_cb as it's
     updated and done_cb when it's done. Reason is used to explain what the
     request is in the status callback.
     """
     self.outstanding_tasks += 1
     self.done_cb = done_cb
     state = self.state
     if not self.preflight() or state.uri == None:
         # generally a good sign that we're not going much further.
         self.finish_task()
         return
     if 'user-agent' not in [i[0].lower() for i in state.req_hdrs]:
         state.req_hdrs.append(
             ("User-Agent", "RED/%s (http://redbot.org/)" % __version__))    
     self.client = RedHttpClient(self._response_start)
     if self.status_cb and state.type:
         self.status_cb("fetching %s (%s)" % (state.uri, state.type))
     req_body, req_done = self.client.req_start(
         state.method, state.uri, state.req_hdrs, nbhttp.dummy)
     state.req_ts = nbhttp.now()
     if state.req_body != None:
         req_body(state.req_body)
     req_done(None)
Beispiel #3
0
    def status(self, message):
        "Update the status bar of the browser"
        self.output(u"""
<script>
<!-- %3.3f
window.status="%s";
-->
</script>
        """ % (nbhttp.now() - self.start, e(message)))
Beispiel #4
0
    def load_saved_test(self):
        """Load a saved test by test_id."""
        try:
            fd = gzip.open(os.path.join(
                save_dir, os.path.basename(self.test_id)
            ))
            mtime = os.fstat(fd.fileno()).st_mtime
        except (OSError, IOError, zlib.error):
            self.output_hdrs(
                "404 Not Found", [
                ("Content-Type", "text/html; charset=%s" % charset), 
                ("Cache-Control", "max-age=600, must-revalidate")
            ])
            # TODO: better error page (through formatter?)
            self.output_body(error_template % 
                "I'm sorry, I can't find that saved response."
            )
            self.body_done()
            return
        is_saved = mtime > nbhttp.now()
        try:
            ired = pickle.load(fd)
        except (pickle.PickleError, EOFError):
            self.output_hdrs(
                "500 Internal Server Error", [
                ("Content-Type", "text/html; charset=%s" % charset), 
                ("Cache-Control", "max-age=600, must-revalidate")
            ])
            # TODO: better error page (through formatter?)
            self.output_body(error_template % 
                "I'm sorry, I had a problem reading that response."
            )
            self.body_done()
            return
        finally:
            fd.close()
            
        formatter = find_formatter(self.format, 'html', self.descend)(
            self.base_uri, ired.uri, ired.orig_req_hdrs, lang,
            self.output, allow_save=(not is_saved), is_saved=True,
            test_id=self.test_id
        )
        self.output_hdrs(
            "200 OK", [
            ("Content-Type", "%s; charset=%s" % (
                formatter.media_type, charset)), 
            ("Cache-Control", "max-age=3600, must-revalidate")
        ])

        formatter.start_output()
        formatter.set_red(ired)
        formatter.finish_output()
        self.body_done()
Beispiel #5
0
 def _response_start(self, version, status, phrase, 
     res_headers, res_pause
 ):
     "Process the response start-line and headers."
     state = self.state
     state.res_ts = nbhttp.now()
     state.res_version = version
     state.res_status = status.decode('iso-8859-1', 'replace')
     state.res_phrase = phrase.decode('iso-8859-1', 'replace')
     state.res_hdrs = res_headers
     ra.ResponseHeaderParser(state)
     ra.ResponseStatusChecker(state)
     state.res_body_enc = state.parsed_hdrs.get(
         'content-type', [None, {}]
     )[1].get('charset', 'utf-8') # default isn't really UTF-8, but oh well
     return self._response_body, self._response_done
Beispiel #6
0
 def __init__(self, *args, **kw):
     Formatter.__init__(self, *args, **kw)
     self.hidden_text = []
     self.start = nbhttp.now()
Beispiel #7
0
 def final_status(self):
     self.status("RED made %(reqs)s requests in %(elapse)2.3f seconds." % {
        'reqs': fetch.total_requests,
        'elapse': nbhttp.now() - self.start
     })
Beispiel #8
0
    def _response_done(self, err):
        "Finish anaylsing the response, handling any parse errors."
        state = self.state
        state.res_complete = True
        state.res_done_ts = nbhttp.now()
        state.transfer_length = self.client.input_transfer_length
        state.header_length = self.client.input_header_length
        self.client = None
        state.res_error = err
        if self.status_cb and state.type:
            self.status_cb("fetched %s (%s)" % (state.uri, state.type))
        state.res_body_md5 = self._md5_processor.digest()
        state.res_body_post_md5 = self._md5_post_processor.digest()
        if err == None:
            pass
        elif err['desc'] == nbhttp.error.ERR_BODY_FORBIDDEN['desc']:
            state.setMessage('header-none', rs.BODY_NOT_ALLOWED)
        elif err['desc'] == nbhttp.error.ERR_EXTRA_DATA['desc']:
            state.res_body_len += len(err.get('detail', ''))
        elif err['desc'] == nbhttp.error.ERR_CHUNK['desc']:
            state.setMessage('header-transfer-encoding', rs.BAD_CHUNK,
                chunk_sample=e(
                    err.get('detail', '')[:20].encode('string_escape')
                )
            )
        elif err['desc'] == nbhttp.error.ERR_CONNECT['desc']:
            state.res_complete = False
        elif err['desc'] == nbhttp.error.ERR_LEN_REQ['desc']:
            pass # TODO: length required
        elif err['desc'] == nbhttp.error.ERR_URL['desc']:
            state.res_complete = False
        elif err['desc'] == nbhttp.error.ERR_READ_TIMEOUT['desc']:
            state.res_complete = False
        elif err['desc'] == nbhttp.error.ERR_HTTP_VERSION['desc']:
            state.res_complete = False
        else:
            raise AssertionError, "Unknown response error: %s" % err

        if state.res_complete:
            checkCaching(state)

        if state.res_complete \
          and state.method not in ['HEAD'] \
          and state.res_status not in ['304']:
            # check payload basics
            if state.parsed_hdrs.has_key('content-length'):
                if state.res_body_len == state.parsed_hdrs['content-length']:
                    state.setMessage('header-content-length', rs.CL_CORRECT)
                else:
                    state.setMessage('header-content-length', 
                                    rs.CL_INCORRECT,
                                    body_length=f_num(state.res_body_len)
                    )
            if state.parsed_hdrs.has_key('content-md5'):
                c_md5_calc = base64.encodestring(state.res_body_md5)[:-1]
                if state.parsed_hdrs['content-md5'] == c_md5_calc:
                    state.setMessage('header-content-md5', rs.CMD5_CORRECT)
                else:
                    state.setMessage('header-content-md5', rs.CMD5_INCORRECT,
                                     calc_md5=c_md5_calc)
        self.done()
        self.finish_task()
Beispiel #9
0
 def __init__(self, test_id, test_uri, req_hdrs, base_uri, 
     format, output_hdrs, output_body, descend=False, save=False):
     self.output_body = output_body
     self.start = time.time()
     timeout = nbhttp.schedule(max_runtime, self.timeoutError)
     if save and save_dir and test_id:
         try:
             os.utime(
                 os.path.join(save_dir, test_id), 
                 (
                     nbhttp.now(), 
                     nbhttp.now() + (save_days * 24 * 60 * 60)
                 )
             )
             location = "?id=%s" % test_id
             if descend:
                 location = "%s&descend=True" % location
             output_hdrs("303 See Other", [
                 ("Location", location)
             ])
             output_body("Redirecting...")
         except (OSError, IOError):
             output_hdrs("500 Internal Server Error", [
                 ("Content-Type", "text/html; charset=%s" % charset), 
             ])
             # TODO: better error message (through formatter?)
             output_body(error_template % "Sorry, I couldn't save that.")
     elif test_id:
         try:
             test_id = os.path.basename(test_id)
             fd = gzip.open(os.path.join(save_dir, test_id))
             mtime = os.fstat(fd.fileno()).st_mtime
         except (OSError, IOError, zlib.error):
             output_hdrs("404 Not Found", [
                 ("Content-Type", "text/html; charset=%s" % charset), 
                 ("Cache-Control", "max-age=600, must-revalidate")
             ])
             # TODO: better error page (through formatter?)
             self.output_body(error_template % 
                 "I'm sorry, I can't find that saved response."
             )
             timeout.delete()
             return
         is_saved = mtime > nbhttp.now()
         try:
             ired = pickle.load(fd)
         except (pickle.PickleError, EOFError):
             output_hdrs("500 Internal Server Error", [
                 ("Content-Type", "text/html; charset=%s" % charset), 
                 ("Cache-Control", "max-age=600, must-revalidate")
             ])
             # TODO: better error page (through formatter?)
             self.output_body(error_template % 
                 "I'm sorry, I had a problem reading that response."
             )
             timeout.delete()
             return
         finally:
             fd.close()
         formatter = find_formatter(format, 'html', descend)(
             base_uri, ired.uri, ired.orig_req_hdrs, lang, self.output,
             allow_save=(not is_saved), is_saved=True, test_id=test_id
         )
         output_hdrs("200 OK", [
             ("Content-Type", "%s; charset=%s" % (
                 formatter.media_type, charset)), 
             ("Cache-Control", "max-age=3600, must-revalidate")
         ])
         formatter.start_output()
         formatter.finish_output(ired)
     elif test_uri:
         if save_dir and os.path.exists(save_dir):
             try:
                 fd, path = tempfile.mkstemp(prefix='', dir=save_dir)
                 test_id = os.path.split(path)[1]
             except (OSError, IOError):
                 # Don't try to store it. 
                 test_id = None
         else:
             test_id = None
         formatter = find_formatter(format, 'html', descend)(
             base_uri, test_uri, req_hdrs, lang, self.output,
             allow_save=test_id, is_saved=False, test_id=test_id,
             descend=descend
         )
         output_hdrs("200 OK", [
             ("Content-Type", "%s; charset=%s" % (
                 formatter.media_type, charset)), 
             ("Cache-Control", "max-age=60, must-revalidate")
         ])
         formatter.start_output()
         ired = droid.InspectingResourceExpertDroid(
             test_uri,
             req_hdrs=req_hdrs,
             status_cb=formatter.status,
             body_procs=[formatter.feed],
             descend=descend
         )
         formatter.finish_output(ired)
         if test_id:
             try:
                 tmp_file = gzip.open(path, 'w')
                 pickle.dump(ired, tmp_file)
                 tmp_file.close()
             except (IOError, zlib.error, pickle.PickleError):
                 pass # we don't cry if we can't store it.
     else:  # no test_uri
         formatter = html.BaseHtmlFormatter(
             base_uri, test_uri, req_hdrs, lang, self.output)
         output_hdrs("200 OK", [
             ("Content-Type", "%s; charset=%s" % (
                 formatter.media_type, charset)
             ), 
             ("Cache-Control", "max-age=300")
         ])
         formatter.start_output()
         formatter.finish_output(None)
     timeout.delete()