Incorrect PUT request on push (HTTP 400 error)

Bug #955445 reported by Andreas Sommer
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Bazaar WebDAV plugin
Incomplete
High
Vincent Ladeuil

Bug Description

Empty PUT requests may be sent, resulting in invalid headers as follows:

Content-Range: bytes 4222347-4222346/*
Content-Length: 0

The server then returns HTTP 400 (Bad Request).

Will add a fixed branch in a minute.

Andreas Sommer (andidog)
description: updated
Revision history for this message
Andreas Sommer (andidog) wrote :

Maybe it's also a good idea to keep investigating why empty requests were sent. As I wrote on the mailing list (https://lists.ubuntu.com/archives/bazaar/2012q1/074515.html), this started happening everytime since I updated from bzr 2.5b1 to 2.5b6.

I also tried it with pushing to a new repository: The first push worked (I committed only a small file, first pack file), while the second push again causes the problem (added a 4 MB file, resulting in upload of second pack file when pushing).

Revision history for this message
Vincent Ladeuil (vila) wrote :

Can you attach the relevant part of your .bzr.log file (taking care at removing any sensitive data regarding auth as you did in your mail) ?

An empty push request is indeed really weird. Your work-around is obviously correct but I'd like to get to the root cause of it as it seems to indicate an issue in bzr-core itself.

Changed in bzr-webdav:
status: New → Incomplete
importance: Undecided → High
assignee: nobody → Vincent Ladeuil (vila)
Revision history for this message
Andreas Sommer (andidog) wrote :

I found out what the problem is:

(in bzrlib\vf_repository.py:2139)
new_pack._write_data('', flush=True)

(which in turn calls _write_data in bzrlib\repofmt\groupcompress_repo.py:153)
        def _write_data(bytes, flush=False, _buffer=self._buffer,
            _write=self.write_stream.write, _update=self._hash.update):
            _buffer[0].append(bytes)
            _buffer[1] += len(bytes)
            # buffer cap
            if _buffer[1] > self._cache_limit or flush:
                bytes = ''.join(_buffer[0])
                _write(bytes) # <------- THERE IT IS
                _update(bytes)
                _buffer[:] = [[], 0]

(this calls AppendBasedFileStream.write in bzrlib\transport\__init__.py:286)
    def write(self, bytes):
        self.transport.append_bytes(self.relpath, bytes)

Obviously, AppendBasedFileStream.write doesn't care if bytes is actually empty. And the flush causes a write call with an empty buffer.

So in the end, the problem boils down to how I fixed it already. But I changed the commit to check for an empty buffer in append_bytes, that will cover all possible append cases.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.