示例#1
0
 def test_getline_exact(self):
     inp = StringIO.StringIO("abcd\r\nef")
     reader = http_app._FencedReader(inp, 6, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abcd\r\n", line)
     self.assertIs(None, reader._kept)
示例#2
0
 def test_read_chunk_remaining(self):
     inp = StringIO.StringIO("abcdef")
     reader = http_app._FencedReader(inp, 4, 10)
     data = reader.read_chunk(9999)
     self.assertEqual("abcd", data)
     self.assertEqual(4, inp.tell())
     self.assertEqual(0, reader.remaining)
示例#3
0
 def test_getline(self):
     inp = StringIO.StringIO("abc\r\nde")
     reader = http_app._FencedReader(inp, 6, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abc\r\n", line)
     self.assertEqual("d", reader._kept)
示例#4
0
 def test_read_chunk(self):
     inp = StringIO.StringIO("abcdef")
     reader = http_app._FencedReader(inp, 5, 10)
     data = reader.read_chunk(2)
     self.assertEqual("ab", data)
     self.assertEqual(2, inp.tell())
     self.assertEqual(3, reader.remaining)
示例#5
0
 def test_read_chunk_remaining(self):
     inp = StringIO.StringIO("abcdef")
     reader = http_app._FencedReader(inp, 4, 10)
     data = reader.read_chunk(9999)
     self.assertEqual("abcd", data)
     self.assertEqual(4, inp.tell())
     self.assertEqual(0, reader.remaining)
示例#6
0
 def test_read_chunk(self):
     inp = StringIO.StringIO("abcdef")
     reader = http_app._FencedReader(inp, 5, 10)
     data = reader.read_chunk(2)
     self.assertEqual("ab", data)
     self.assertEqual(2, inp.tell())
     self.assertEqual(3, reader.remaining)
示例#7
0
 def test_getline(self):
     inp = StringIO.StringIO("abc\r\nde")
     reader = http_app._FencedReader(inp, 6, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abc\r\n", line)
     self.assertEqual("d", reader._kept)
示例#8
0
 def test_getline_exact(self):
     inp = StringIO.StringIO("abcd\r\nef")
     reader = http_app._FencedReader(inp, 6, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abcd\r\n", line)
     self.assertIs(None, reader._kept)
示例#9
0
 def test_getline_just_newline(self):
     inp = StringIO.StringIO("\r\n")
     reader = http_app._FencedReader(inp, 2, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("\r\n", line)
     line = reader.getline()
     self.assertEqual("", line)
示例#10
0
 def test_getline_just_newline(self):
     inp = StringIO.StringIO("\r\n")
     reader = http_app._FencedReader(inp, 2, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("\r\n", line)
     line = reader.getline()
     self.assertEqual("", line)
示例#11
0
 def test_getline_empty(self):
     inp = StringIO.StringIO("")
     reader = http_app._FencedReader(inp, 0, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("", line)
     line = reader.getline()
     self.assertEqual("", line)
示例#12
0
 def test_getline_empty(self):
     inp = StringIO.StringIO("")
     reader = http_app._FencedReader(inp, 0, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("", line)
     line = reader.getline()
     self.assertEqual("", line)
示例#13
0
 def test_getline_many_chunks(self):
     inp = StringIO.StringIO("abcde\r\nf")
     reader = http_app._FencedReader(inp, 8, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("abcde\r\n", line)
     self.assertEqual("f", reader._kept)
     line = reader.getline()
     self.assertEqual("f", line)
示例#14
0
 def test_read_chunk_kept(self):
     inp = StringIO.StringIO("abcde")
     reader = http_app._FencedReader(inp, 4, 10)
     reader._kept = "xyz"
     data = reader.read_chunk(2)  # atmost ignored
     self.assertEqual("xyz", data)
     self.assertEqual(0, inp.tell())
     self.assertEqual(4, reader.remaining)
     self.assertIsNone(reader._kept)
示例#15
0
 def test_getline_many_chunks(self):
     inp = StringIO.StringIO("abcde\r\nf")
     reader = http_app._FencedReader(inp, 8, 10)
     reader.MAXCHUNK = 4
     line = reader.getline()
     self.assertEqual("abcde\r\n", line)
     self.assertEqual("f", reader._kept)
     line = reader.getline()
     self.assertEqual("f", line)
示例#16
0
 def test_read_chunk_kept(self):
     inp = StringIO.StringIO("abcde")
     reader = http_app._FencedReader(inp, 4, 10)
     reader._kept = "xyz"
     data = reader.read_chunk(2)  # atmost ignored
     self.assertEqual("xyz", data)
     self.assertEqual(0, inp.tell())
     self.assertEqual(4, reader.remaining)
     self.assertIsNone(reader._kept)
示例#17
0
 def test_read_chunk_nothing_left(self):
     inp = StringIO.StringIO("abc")
     reader = http_app._FencedReader(inp, 2, 10)
     reader.read_chunk(2)
     self.assertEqual(2, inp.tell())
     self.assertEqual(0, reader.remaining)
     data = reader.read_chunk(2)
     self.assertEqual("", data)
     self.assertEqual(2, inp.tell())
     self.assertEqual(0, reader.remaining)
示例#18
0
 def test_read_chunk_nothing_left(self):
     inp = StringIO.StringIO("abc")
     reader = http_app._FencedReader(inp, 2, 10)
     reader.read_chunk(2)
     self.assertEqual(2, inp.tell())
     self.assertEqual(0, reader.remaining)
     data = reader.read_chunk(2)
     self.assertEqual("", data)
     self.assertEqual(2, inp.tell())
     self.assertEqual(0, reader.remaining)
示例#19
0
 def test_getline_no_newline(self):
     inp = StringIO.StringIO("abcd")
     reader = http_app._FencedReader(inp, 4, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abcd", line)
示例#20
0
 def test_getline_too_large_complete(self):
     inp = StringIO.StringIO("x" * 25 + "\r\n")
     reader = http_app._FencedReader(inp, 50, 25)
     reader.MAXCHUNK = 4
     self.assertRaises(http_app.BadRequest, reader.getline)
示例#21
0
 def test_init(self):
     reader = http_app._FencedReader(StringIO.StringIO(""), 25, 100)
     self.assertEqual(25, reader.remaining)
示例#22
0
 def test_init(self):
     reader = http_app._FencedReader(StringIO.StringIO(""), 25, 100)
     self.assertEqual(25, reader.remaining)
示例#23
0
 def test_getline_too_large_complete(self):
     inp = StringIO.StringIO("x" * 25 + "\r\n")
     reader = http_app._FencedReader(inp, 50, 25)
     reader.MAXCHUNK = 4
     self.assertRaises(http_app.BadRequest, reader.getline)
示例#24
0
 def test_getline_no_newline(self):
     inp = StringIO.StringIO("abcd")
     reader = http_app._FencedReader(inp, 4, 10)
     reader.MAXCHUNK = 6
     line = reader.getline()
     self.assertEqual("abcd", line)
示例#25
0
    def __call__(self):
        """
        Call an HTTP method of a resource.

        This method was rewritten to allow for a sync flow which uses one POST
        request for each transferred document (back and forth).

        Usual U1DB sync process transfers all documents from client to server
        and back in only one POST request. This is inconvenient for some
        reasons, as lack of possibility of gracefully interrupting the sync
        process, and possible timeouts for when dealing with large documents
        that have to be retrieved and encrypted/decrypted. Because of those,
        we split the sync process into many POST requests.
        """
        args = urlparse.parse_qsl(self.environ['QUERY_STRING'],
                                  strict_parsing=False)
        try:
            args = dict(
                (k.decode('utf-8'), v.decode('utf-8')) for k, v in args)
        except ValueError:
            raise http_app.BadRequest()
        method = self.environ['REQUEST_METHOD'].lower()
        if method in ('get', 'delete'):
            meth = self._lookup(method)
            return meth(args, None)
        else:
            # we expect content-length > 0, reconsider if we move
            # to support chunked enconding
            try:
                content_length = int(self.environ['CONTENT_LENGTH'])
            except (ValueError, KeyError):
                raise http_app.BadRequest
            if content_length <= 0:
                raise http_app.BadRequest
            if content_length > self.max_request_size:
                raise http_app.BadRequest
            reader = http_app._FencedReader(
                self.environ['wsgi.input'], content_length,
                self.max_entry_size)
            content_type = self.environ.get('CONTENT_TYPE')
            if content_type == 'application/json':
                meth = self._lookup(method)
                body = reader.read_chunk(sys.maxint)
                return meth(args, body)
            elif content_type.startswith('application/x-soledad-sync'):
                # read one line and validate it
                body_getline = reader.getline
                if body_getline().strip() != '[':
                    raise http_app.BadRequest()
                line = body_getline()
                line, comma = utils.check_and_strip_comma(line.strip())
                meth_args = self._lookup('%s_args' % method)
                meth_args(args, line)
                # handle incoming documents
                if content_type == 'application/x-soledad-sync-put':
                    meth_put = self._lookup('%s_put' % method)
                    meth_end = self._lookup('%s_end' % method)
                    entries = []
                    while True:
                        line = body_getline()
                        entry = line.strip()
                        if entry == ']':  # end of incoming document stream
                            break
                        if not entry or not comma:  # empty or no prec comma
                            raise http_app.BadRequest
                        entry, comma = utils.check_and_strip_comma(entry)
                        entries.append(entry)
                    if comma or body_getline():  # extra comma or data
                        raise http_app.BadRequest
                    for entry in entries:
                        meth_put({}, entry)
                    return meth_end()
                # handle outgoing documents
                elif content_type == 'application/x-soledad-sync-get':
                    line = body_getline()
                    entry = line.strip()
                    meth_get = self._lookup('%s_get' % method)
                    return meth_get({}, line)
                else:
                    raise http_app.BadRequest()
            else:
                raise http_app.BadRequest()
示例#26
0
    def __call__(self):
        """
        Call an HTTP method of a resource.

        This method was rewritten to allow for a sync flow which uses one POST
        request for each transferred document (back and forth).

        Usual U1DB sync process transfers all documents from client to server
        and back in only one POST request. This is inconvenient for some
        reasons, as lack of possibility of gracefully interrupting the sync
        process, and possible timeouts for when dealing with large documents
        that have to be retrieved and encrypted/decrypted. Because of those,
        we split the sync process into many POST requests.
        """
        args = urlparse.parse_qsl(self.environ['QUERY_STRING'],
                                  strict_parsing=False)
        try:
            args = dict(
                (k.decode('utf-8'), v.decode('utf-8')) for k, v in args)
        except ValueError:
            raise http_app.BadRequest()
        method = self.environ['REQUEST_METHOD'].lower()
        if method in ('get', 'delete'):
            meth = self._lookup(method)
            return meth(args, None)
        else:
            # we expect content-length > 0, reconsider if we move
            # to support chunked enconding
            try:
                content_length = int(self.environ['CONTENT_LENGTH'])
            except (ValueError, KeyError):
                raise http_app.BadRequest
            if content_length <= 0:
                raise http_app.BadRequest
            if content_length > self.max_request_size:
                raise http_app.BadRequest
            reader = http_app._FencedReader(self.environ['wsgi.input'],
                                            content_length,
                                            self.max_entry_size)
            content_type = self.environ.get('CONTENT_TYPE')
            if content_type == 'application/json':
                meth = self._lookup(method)
                body = reader.read_chunk(sys.maxint)
                return meth(args, body)
            elif content_type.startswith('application/x-soledad-sync'):
                # read one line and validate it
                body_getline = reader.getline
                if body_getline().strip() != '[':
                    raise http_app.BadRequest()
                line = body_getline()
                line, comma = utils.check_and_strip_comma(line.strip())
                meth_args = self._lookup('%s_args' % method)
                meth_args(args, line)
                # handle incoming documents
                if content_type == 'application/x-soledad-sync-put':
                    meth_put = self._lookup('%s_put' % method)
                    meth_end = self._lookup('%s_end' % method)
                    while True:
                        line = body_getline()
                        entry = line.strip()
                        if entry == ']':  # end of incoming document stream
                            break
                        if not entry or not comma:  # empty or no prec comma
                            raise http_app.BadRequest
                        entry, comma = utils.check_and_strip_comma(entry)
                        meth_put({}, entry)
                    if comma or body_getline():  # extra comma or data
                        raise http_app.BadRequest
                    return meth_end()
                # handle outgoing documents
                elif content_type == 'application/x-soledad-sync-get':
                    line = body_getline()
                    entry = line.strip()
                    meth_get = self._lookup('%s_get' % method)
                    return meth_get({}, line)
                else:
                    raise http_app.BadRequest()
            else:
                raise http_app.BadRequest()