Adds a handler that produces a plain text response.

        Parameters
        ----------
        start : string
            The URL prefix that must be matched to perform this request.

        method_str : string
            The HTTP method for which to trigger the request.

        text_producer : function(esrh, args)
            A function returning a string. The function takes two arguments.
            esrh is the QuickServerRequestHandler object that called the
            function. args is a map containing the arguments to the request
            (i.e., the rest of the URL as path segment array 'paths', a map of
            all query fields / flags 'query', the fragment string 'fragment',
            and if the method was a POST the JSON form content 'post'). If the
            result is None a 404 error is sent.

def add_text_mask(self, start, method_str, text_producer):
        """Adds a handler that produces a plain text response.

        Parameters
        ----------
        start : string
            The URL prefix that must be matched to perform this request.

        method_str : string
            The HTTP method for which to trigger the request.

        text_producer : function(esrh, args)
            A function returning a string. The function takes two arguments.
            esrh is the QuickServerRequestHandler object that called the
            function. args is a map containing the arguments to the request
            (i.e., the rest of the URL as path segment array 'paths', a map of
            all query fields / flags 'query', the fragment string 'fragment',
            and if the method was a POST the JSON form content 'post'). If the
            result is None a 404 error is sent.
        """
        def send_text(drh, rem_path):
            text = text_producer(drh, rem_path)
            if not isinstance(text, Response):
                text = Response(text)
            ctype = text.get_ctype("text/plain")
            code = text.code
            text = text.response
            if text is None:
                drh.send_error(404, "File not found")
                return None
            f = BytesIO()
            if isinstance(text, (str, unicode)):
                try:
                    text = text.decode('utf8')
                except AttributeError:
                    pass
                text = text.encode('utf8')
            f.write(text)
            f.flush()
            size = f.tell()
            f.seek(0)
            # handle ETag caching
            if drh.request_version >= "HTTP/1.1":
                e_tag = "{0:x}".format(zlib.crc32(f.read()) & 0xFFFFFFFF)
                f.seek(0)
                match = _getheader(drh.headers, 'if-none-match')
                if match is not None:
                    if drh.check_cache(e_tag, match):
                        f.close()
                        return None
                drh.send_header("ETag", e_tag, end_header=True)
                drh.send_header("Cache-Control",
                                "max-age={0}".format(self.max_age),
                                end_header=True)
            drh.send_response(code)
            drh.send_header("Content-Type", ctype)
            drh.send_header("Content-Length", size)
            drh.end_headers()
            return f
        self._add_file_mask(start, method_str, send_text)