We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
gcloud.storage.iterator.KeyDataIterator chunking is off-by-one
'get_headers' computes the "Range:" header as '_bytes_written' - '_bytes_written + CHUNK_SIZE':

https://github.com/GoogleCloudPlatform/gcloud-python/blob/1f2aaf3606802f4f02eeb30e22e1082ef7f4594e/gcloud/storage/iterator.py#L215

and the '_bytes_written' gets updated to bump by the size of the chunk the server returns.  Consider the initial read, assuming a CHUNK_SIZE of 100:

   Range: bytes=0-100

Note that, per RFC2616. this will return up to 101 bytes (both bytes-position values are inclusive):

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gcloud/storage/iterator.py`
Content:
```
1 """Iterators for paging through API responses.
2 
3 These iterators
4 simplify the process
5 of paging through API responses
6 where the response
7 is a list of results
8 with a ``nextPageToken``.
9 
10 To make an iterator work,
11 just override the ``get_items_from_response`` method
12 so that given a response
13 (containing a page of results)
14 it parses those results
15 into an iterable
16 of the actual objects you want::
17 
18   class MyIterator(Iterator):
19     def get_items_from_response(self, response):
20       items = response.get('items', [])
21       for item in items:
22         yield MyItemClass.from_dict(item, other_arg=True)
23 
24 You then can use this
25 to get **all** the results
26 from a resource::
27 
28   >>> iterator = MyIterator(...)
29   >>> list(iterator)  # Convert to a list (consumes all values).
30 
31 Or you can walk your way through items
32 and call off the search early
33 if you find what you're looking for
34 (resulting in possibly fewer requests)::
35 
36   >>> for item in MyIterator(...):
37   >>>   print item.name
38   >>>   if not item.is_valid:
39   >>>     break
40 """
41 
42 
43 class Iterator(object):
44   """A generic class for iterating through Cloud Storage list responses.
45 
46   :type connection: :class:`gcloud.storage.connection.Connection`
47   :param connection: The connection to use to make requests.
48 
49   :type path: string
50   :param path: The path to query for the list of items.
51   """
52 
53   def __init__(self, connection, path):
54     self.connection = connection
55     self.path = path
56     self.page_number = 0
57     self.next_page_token = None
58 
59   def __iter__(self):
60     """Iterate through the list of items."""
61 
62     while self.has_next_page():
63       response = self.get_next_page_response()
64       for item in self.get_items_from_response(response):
65         yield item
66 
67   def has_next_page(self):
68     """Determines whether or not this iterator has more pages.
69 
70     :rtype: bool
71     :returns: Whether the iterator has more pages or not.
72     """
73 
74     if self.page_number == 0:
75       return True
76 
77     return self.next_page_token is not None
78 
79   def get_query_params(self):
80     """Getter for query parameters for the next request.
81 
82     :rtype: dict or None
83     :returns: A dictionary of query parameters or None if there are none.
84     """
85 
86     if self.next_page_token:
87       return {'pageToken': self.next_page_token}
88 
89   def get_next_page_response(self):
90     """Requests the next page from the path provided.
91 
92     :rtype: dict
93     :returns: The parsed JSON response of the next page's contents.
94     """
95 
96     if not self.has_next_page():
97       raise RuntimeError('No more pages. Try resetting the iterator.')
98 
99     response = self.connection.api_request(
100         method='GET', path=self.path, query_params=self.get_query_params())
101 
102     self.page_number += 1
103     self.next_page_token = response.get('nextPageToken')
104 
105     return response
106 
107   def reset(self):
108     """Resets the iterator to the beginning."""
109     self.page_number = 0
110     self.next_page_token = None
111 
112   def get_items_from_response(self, response): #pragma NO COVER
113     """Factory method called while iterating. This should be overriden.
114 
115     This method should be overridden by a subclass.
116     It should accept the API response
117     of a request for the next page of items,
118     and return a list (or other iterable)
119     of items.
120 
121     Typically this method will construct
122     a Bucket or a Key
123     from the page of results in the response.
124 
125     :type response: dict
126     :param response: The response of asking for the next page of items.
127 
128     :rtype: iterable
129     :returns: Items that the iterator should yield.
130     """
131     raise NotImplementedError
132 
133 
134 class BucketIterator(Iterator):
135   """An iterator listing all buckets.
136 
137   You shouldn't have to use this directly,
138   but instead should use the helper methods
139   on :class:`gcloud.storage.connection.Connection` objects.
140 
141   :type connection: :class:`gcloud.storage.connection.Connection`
142   :param connection: The connection to use for querying the list of buckets.
143   """
144 
145   def __init__(self, connection):
146     super(BucketIterator, self).__init__(connection=connection, path='/b')
147 
148   def get_items_from_response(self, response):
149     """Factory method which yields :class:`gcloud.storage.bucket.Bucket` items from a response.
150 
151     :type response: dict
152     :param response: The JSON API response for a page of buckets.
153     """
154 
155     from gcloud.storage.bucket import Bucket
156     for item in response.get('items', []):
157       yield Bucket.from_dict(item, connection=self.connection)
158 
159 
160 class KeyIterator(Iterator):
161   """An iterator listing keys.
162 
163   You shouldn't have to use this directly,
164   but instead should use the helper methods
165   on :class:`gcloud.storage.key.Key` objects.
166 
167   :type bucket: :class:`gcloud.storage.bucket.Bucket`
168   :param bucket: The bucket from which to list keys.
169   """
170 
171   def __init__(self, bucket):
172     self.bucket = bucket
173     super(KeyIterator, self).__init__(
174         connection=bucket.connection, path=bucket.path + '/o')
175 
176   def get_items_from_response(self, response):
177     """Factory method which yields :class:`gcloud.storage.key.Key` items from a response.
178 
179     :type response: dict
180     :param response: The JSON API response for a page of keys.
181     """
182 
183     from gcloud.storage.key import Key
184     for item in response.get('items', []):
185       yield Key.from_dict(item, bucket=self.bucket)
186 
187 
188 class KeyDataIterator(object):
189 
190   def __init__(self, key):
191     self.key = key
192     self.reset()
193 
194   def __iter__(self):
195     while self.has_more_data():
196       yield self.get_next_chunk()
197 
198   def reset(self):
199     self._bytes_written = 0
200     self._total_bytes = None
201 
202   def has_more_data(self):
203     if self._bytes_written == 0:
204       return True
205     elif not self._total_bytes:
206       # self._total_bytes **should** be set by this point.
207       # If it isn't, something is wrong.
208       raise ValueError('Size of object is unknown... This is bad.')
209     else:
210       return (self._bytes_written < self._total_bytes)
211 
212   def get_headers(self):
213     start = self._bytes_written
214     end = self._bytes_written + self.key.CHUNK_SIZE
215 
216     if self._total_bytes and end > self._total_bytes:
217       end = ''
218 
219     return {'Range': 'bytes=%s-%s' % (start, end)}
220 
221   def get_url(self):
222     return self.key.connection.build_api_url(
223         path=self.key.path, query_params={'alt': 'media'})
224 
225   def get_next_chunk(self):
226     if not self.has_more_data():
227       raise RuntimeError('No more data in this iterator. Try resetting.')
228 
229     response, content = self.key.connection.make_request(
230         method='GET', url=self.get_url(), headers=self.get_headers())
231 
232     if response.status in (200, 206):
233       self._bytes_written += len(content)
234 
235       if 'content-range' in response:
236         content_range = response['content-range']
237         self._total_bytes = int(content_range.rsplit('/', 1)[1])
238 
239       return content
240 
241     # Expected a 200 or a 206... Got something else, which is bad.
242     raise Exception(response)
243
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gcloud/storage/iterator.py b/gcloud/storage/iterator.py
--- a/gcloud/storage/iterator.py
+++ b/gcloud/storage/iterator.py
@@ -211,7 +211,7 @@
 
   def get_headers(self):
     start = self._bytes_written
-    end = self._bytes_written + self.key.CHUNK_SIZE
+    end = self._bytes_written + self.key.CHUNK_SIZE - 1
 
     if self._total_bytes and end > self._total_bytes:
       end = ''

{"golden_diff": "diff --git a/gcloud/storage/iterator.py b/gcloud/storage/iterator.py\n--- a/gcloud/storage/iterator.py\n+++ b/gcloud/storage/iterator.py\n@@ -211,7 +211,7 @@\n \n   def get_headers(self):\n     start = self._bytes_written\n-    end = self._bytes_written + self.key.CHUNK_SIZE\n+    end = self._bytes_written + self.key.CHUNK_SIZE - 1\n \n     if self._total_bytes and end > self._total_bytes:\n       end = ''\n", "issue": "gcloud.storage.iterator.KeyDataIterator chunking is off-by-one\n'get_headers' computes the \"Range:\" header as '_bytes_written' - '_bytes_written + CHUNK_SIZE':\n\nhttps://github.com/GoogleCloudPlatform/gcloud-python/blob/1f2aaf3606802f4f02eeb30e22e1082ef7f4594e/gcloud/storage/iterator.py#L215\n\nand the '_bytes_written' gets updated to bump by the size of the chunk the server returns.  Consider the initial read, assuming a CHUNK_SIZE of 100:\n\n   Range: bytes=0-100\n\nNote that, per RFC2616. this will return up to 101 bytes (both bytes-position values are inclusive):\n\nhttp://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1\n\n", "before_files": [{"content": "\"\"\"Iterators for paging through API responses.\n\nThese iterators\nsimplify the process\nof paging through API responses\nwhere the response\nis a list of results\nwith a ``nextPageToken``.\n\nTo make an iterator work,\njust override the ``get_items_from_response`` method\nso that given a response\n(containing a page of results)\nit parses those results\ninto an iterable\nof the actual objects you want::\n\n  class MyIterator(Iterator):\n    def get_items_from_response(self, response):\n      items = response.get('items', [])\n      for item in items:\n        yield MyItemClass.from_dict(item, other_arg=True)\n\nYou then can use this\nto get **all** the results\nfrom a resource::\n\n  >>> iterator = MyIterator(...)\n  >>> list(iterator)  # Convert to a list (consumes all values).\n\nOr you can walk your way through items\nand call off the search early\nif you find what you're looking for\n(resulting in possibly fewer requests)::\n\n  >>> for item in MyIterator(...):\n  >>>   print item.name\n  >>>   if not item.is_valid:\n  >>>     break\n\"\"\"\n\n\nclass Iterator(object):\n  \"\"\"A generic class for iterating through Cloud Storage list responses.\n\n  :type connection: :class:`gcloud.storage.connection.Connection`\n  :param connection: The connection to use to make requests.\n\n  :type path: string\n  :param path: The path to query for the list of items.\n  \"\"\"\n\n  def __init__(self, connection, path):\n    self.connection = connection\n    self.path = path\n    self.page_number = 0\n    self.next_page_token = None\n\n  def __iter__(self):\n    \"\"\"Iterate through the list of items.\"\"\"\n\n    while self.has_next_page():\n      response = self.get_next_page_response()\n      for item in self.get_items_from_response(response):\n        yield item\n\n  def has_next_page(self):\n    \"\"\"Determines whether or not this iterator has more pages.\n\n    :rtype: bool\n    :returns: Whether the iterator has more pages or not.\n    \"\"\"\n\n    if self.page_number == 0:\n      return True\n\n    return self.next_page_token is not None\n\n  def get_query_params(self):\n    \"\"\"Getter for query parameters for the next request.\n\n    :rtype: dict or None\n    :returns: A dictionary of query parameters or None if there are none.\n    \"\"\"\n\n    if self.next_page_token:\n      return {'pageToken': self.next_page_token}\n\n  def get_next_page_response(self):\n    \"\"\"Requests the next page from the path provided.\n\n    :rtype: dict\n    :returns: The parsed JSON response of the next page's contents.\n    \"\"\"\n\n    if not self.has_next_page():\n      raise RuntimeError('No more pages. Try resetting the iterator.')\n\n    response = self.connection.api_request(\n        method='GET', path=self.path, query_params=self.get_query_params())\n\n    self.page_number += 1\n    self.next_page_token = response.get('nextPageToken')\n\n    return response\n\n  def reset(self):\n    \"\"\"Resets the iterator to the beginning.\"\"\"\n    self.page_number = 0\n    self.next_page_token = None\n\n  def get_items_from_response(self, response): #pragma NO COVER\n    \"\"\"Factory method called while iterating. This should be overriden.\n\n    This method should be overridden by a subclass.\n    It should accept the API response\n    of a request for the next page of items,\n    and return a list (or other iterable)\n    of items.\n\n    Typically this method will construct\n    a Bucket or a Key\n    from the page of results in the response.\n\n    :type response: dict\n    :param response: The response of asking for the next page of items.\n\n    :rtype: iterable\n    :returns: Items that the iterator should yield.\n    \"\"\"\n    raise NotImplementedError\n\n\nclass BucketIterator(Iterator):\n  \"\"\"An iterator listing all buckets.\n\n  You shouldn't have to use this directly,\n  but instead should use the helper methods\n  on :class:`gcloud.storage.connection.Connection` objects.\n\n  :type connection: :class:`gcloud.storage.connection.Connection`\n  :param connection: The connection to use for querying the list of buckets.\n  \"\"\"\n\n  def __init__(self, connection):\n    super(BucketIterator, self).__init__(connection=connection, path='/b')\n\n  def get_items_from_response(self, response):\n    \"\"\"Factory method which yields :class:`gcloud.storage.bucket.Bucket` items from a response.\n\n    :type response: dict\n    :param response: The JSON API response for a page of buckets.\n    \"\"\"\n\n    from gcloud.storage.bucket import Bucket\n    for item in response.get('items', []):\n      yield Bucket.from_dict(item, connection=self.connection)\n\n\nclass KeyIterator(Iterator):\n  \"\"\"An iterator listing keys.\n\n  You shouldn't have to use this directly,\n  but instead should use the helper methods\n  on :class:`gcloud.storage.key.Key` objects.\n\n  :type bucket: :class:`gcloud.storage.bucket.Bucket`\n  :param bucket: The bucket from which to list keys.\n  \"\"\"\n\n  def __init__(self, bucket):\n    self.bucket = bucket\n    super(KeyIterator, self).__init__(\n        connection=bucket.connection, path=bucket.path + '/o')\n\n  def get_items_from_response(self, response):\n    \"\"\"Factory method which yields :class:`gcloud.storage.key.Key` items from a response.\n\n    :type response: dict\n    :param response: The JSON API response for a page of keys.\n    \"\"\"\n\n    from gcloud.storage.key import Key\n    for item in response.get('items', []):\n      yield Key.from_dict(item, bucket=self.bucket)\n\n\nclass KeyDataIterator(object):\n\n  def __init__(self, key):\n    self.key = key\n    self.reset()\n\n  def __iter__(self):\n    while self.has_more_data():\n      yield self.get_next_chunk()\n\n  def reset(self):\n    self._bytes_written = 0\n    self._total_bytes = None\n\n  def has_more_data(self):\n    if self._bytes_written == 0:\n      return True\n    elif not self._total_bytes:\n      # self._total_bytes **should** be set by this point.\n      # If it isn't, something is wrong.\n      raise ValueError('Size of object is unknown... This is bad.')\n    else:\n      return (self._bytes_written < self._total_bytes)\n\n  def get_headers(self):\n    start = self._bytes_written\n    end = self._bytes_written + self.key.CHUNK_SIZE\n\n    if self._total_bytes and end > self._total_bytes:\n      end = ''\n\n    return {'Range': 'bytes=%s-%s' % (start, end)}\n\n  def get_url(self):\n    return self.key.connection.build_api_url(\n        path=self.key.path, query_params={'alt': 'media'})\n\n  def get_next_chunk(self):\n    if not self.has_more_data():\n      raise RuntimeError('No more data in this iterator. Try resetting.')\n\n    response, content = self.key.connection.make_request(\n        method='GET', url=self.get_url(), headers=self.get_headers())\n\n    if response.status in (200, 206):\n      self._bytes_written += len(content)\n\n      if 'content-range' in response:\n        content_range = response['content-range']\n        self._total_bytes = int(content_range.rsplit('/', 1)[1])\n\n      return content\n\n    # Expected a 200 or a 206... Got something else, which is bad.\n    raise Exception(response)\n", "path": "gcloud/storage/iterator.py"}], "after_files": [{"content": "\"\"\"Iterators for paging through API responses.\n\nThese iterators\nsimplify the process\nof paging through API responses\nwhere the response\nis a list of results\nwith a ``nextPageToken``.\n\nTo make an iterator work,\njust override the ``get_items_from_response`` method\nso that given a response\n(containing a page of results)\nit parses those results\ninto an iterable\nof the actual objects you want::\n\n  class MyIterator(Iterator):\n    def get_items_from_response(self, response):\n      items = response.get('items', [])\n      for item in items:\n        yield MyItemClass.from_dict(item, other_arg=True)\n\nYou then can use this\nto get **all** the results\nfrom a resource::\n\n  >>> iterator = MyIterator(...)\n  >>> list(iterator)  # Convert to a list (consumes all values).\n\nOr you can walk your way through items\nand call off the search early\nif you find what you're looking for\n(resulting in possibly fewer requests)::\n\n  >>> for item in MyIterator(...):\n  >>>   print item.name\n  >>>   if not item.is_valid:\n  >>>     break\n\"\"\"\n\n\nclass Iterator(object):\n  \"\"\"A generic class for iterating through Cloud Storage list responses.\n\n  :type connection: :class:`gcloud.storage.connection.Connection`\n  :param connection: The connection to use to make requests.\n\n  :type path: string\n  :param path: The path to query for the list of items.\n  \"\"\"\n\n  def __init__(self, connection, path):\n    self.connection = connection\n    self.path = path\n    self.page_number = 0\n    self.next_page_token = None\n\n  def __iter__(self):\n    \"\"\"Iterate through the list of items.\"\"\"\n\n    while self.has_next_page():\n      response = self.get_next_page_response()\n      for item in self.get_items_from_response(response):\n        yield item\n\n  def has_next_page(self):\n    \"\"\"Determines whether or not this iterator has more pages.\n\n    :rtype: bool\n    :returns: Whether the iterator has more pages or not.\n    \"\"\"\n\n    if self.page_number == 0:\n      return True\n\n    return self.next_page_token is not None\n\n  def get_query_params(self):\n    \"\"\"Getter for query parameters for the next request.\n\n    :rtype: dict or None\n    :returns: A dictionary of query parameters or None if there are none.\n    \"\"\"\n\n    if self.next_page_token:\n      return {'pageToken': self.next_page_token}\n\n  def get_next_page_response(self):\n    \"\"\"Requests the next page from the path provided.\n\n    :rtype: dict\n    :returns: The parsed JSON response of the next page's contents.\n    \"\"\"\n\n    if not self.has_next_page():\n      raise RuntimeError('No more pages. Try resetting the iterator.')\n\n    response = self.connection.api_request(\n        method='GET', path=self.path, query_params=self.get_query_params())\n\n    self.page_number += 1\n    self.next_page_token = response.get('nextPageToken')\n\n    return response\n\n  def reset(self):\n    \"\"\"Resets the iterator to the beginning.\"\"\"\n    self.page_number = 0\n    self.next_page_token = None\n\n  def get_items_from_response(self, response): #pragma NO COVER\n    \"\"\"Factory method called while iterating. This should be overriden.\n\n    This method should be overridden by a subclass.\n    It should accept the API response\n    of a request for the next page of items,\n    and return a list (or other iterable)\n    of items.\n\n    Typically this method will construct\n    a Bucket or a Key\n    from the page of results in the response.\n\n    :type response: dict\n    :param response: The response of asking for the next page of items.\n\n    :rtype: iterable\n    :returns: Items that the iterator should yield.\n    \"\"\"\n    raise NotImplementedError\n\n\nclass BucketIterator(Iterator):\n  \"\"\"An iterator listing all buckets.\n\n  You shouldn't have to use this directly,\n  but instead should use the helper methods\n  on :class:`gcloud.storage.connection.Connection` objects.\n\n  :type connection: :class:`gcloud.storage.connection.Connection`\n  :param connection: The connection to use for querying the list of buckets.\n  \"\"\"\n\n  def __init__(self, connection):\n    super(BucketIterator, self).__init__(connection=connection, path='/b')\n\n  def get_items_from_response(self, response):\n    \"\"\"Factory method which yields :class:`gcloud.storage.bucket.Bucket` items from a response.\n\n    :type response: dict\n    :param response: The JSON API response for a page of buckets.\n    \"\"\"\n\n    from gcloud.storage.bucket import Bucket\n    for item in response.get('items', []):\n      yield Bucket.from_dict(item, connection=self.connection)\n\n\nclass KeyIterator(Iterator):\n  \"\"\"An iterator listing keys.\n\n  You shouldn't have to use this directly,\n  but instead should use the helper methods\n  on :class:`gcloud.storage.key.Key` objects.\n\n  :type bucket: :class:`gcloud.storage.bucket.Bucket`\n  :param bucket: The bucket from which to list keys.\n  \"\"\"\n\n  def __init__(self, bucket):\n    self.bucket = bucket\n    super(KeyIterator, self).__init__(\n        connection=bucket.connection, path=bucket.path + '/o')\n\n  def get_items_from_response(self, response):\n    \"\"\"Factory method which yields :class:`gcloud.storage.key.Key` items from a response.\n\n    :type response: dict\n    :param response: The JSON API response for a page of keys.\n    \"\"\"\n\n    from gcloud.storage.key import Key\n    for item in response.get('items', []):\n      yield Key.from_dict(item, bucket=self.bucket)\n\n\nclass KeyDataIterator(object):\n\n  def __init__(self, key):\n    self.key = key\n    self.reset()\n\n  def __iter__(self):\n    while self.has_more_data():\n      yield self.get_next_chunk()\n\n  def reset(self):\n    self._bytes_written = 0\n    self._total_bytes = None\n\n  def has_more_data(self):\n    if self._bytes_written == 0:\n      return True\n    elif not self._total_bytes:\n      # self._total_bytes **should** be set by this point.\n      # If it isn't, something is wrong.\n      raise ValueError('Size of object is unknown... This is bad.')\n    else:\n      return (self._bytes_written < self._total_bytes)\n\n  def get_headers(self):\n    start = self._bytes_written\n    end = self._bytes_written + self.key.CHUNK_SIZE - 1\n\n    if self._total_bytes and end > self._total_bytes:\n      end = ''\n\n    return {'Range': 'bytes=%s-%s' % (start, end)}\n\n  def get_url(self):\n    return self.key.connection.build_api_url(\n        path=self.key.path, query_params={'alt': 'media'})\n\n  def get_next_chunk(self):\n    if not self.has_more_data():\n      raise RuntimeError('No more data in this iterator. Try resetting.')\n\n    response, content = self.key.connection.make_request(\n        method='GET', url=self.get_url(), headers=self.get_headers())\n\n    if response.status in (200, 206):\n      self._bytes_written += len(content)\n\n      if 'content-range' in response:\n        content_range = response['content-range']\n        self._total_bytes = int(content_range.rsplit('/', 1)[1])\n\n      return content\n\n    # Expected a 200 or a 206... Got something else, which is bad.\n    raise Exception(response)\n", "path": "gcloud/storage/iterator.py"}]}