Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Content-length error in google cloud endpoints testing

I get the following error whenever I want to test a 404 HTTP error path in my code:

AssertionError: Content-Length is different from actual app_iter length (512!=60)

I have created a minimal sample that triggers this behavior:

import unittest
import endpoints
from protorpc import remote
from protorpc.message_types import VoidMessage
import webtest

@endpoints.api(name='test', version='v1')
class HelloWorld(remote.Service):
    @endpoints.method(VoidMessage, VoidMessage,
                      path='test_path', http_method='POST',
                      name='test_name')
    def test(self, request):
        raise endpoints.NotFoundException("Not found")

class AppTest(unittest.TestCase):
    def setUp(self):
        app = endpoints.api_server([HelloWorld])
        self.testapp = webtest.TestApp(app)

    # Test the handler.
    def testHelloWorldHandler(self):
        response = self.testapp.post('/_ah/spi/HelloWorld.test', extra_environ={
            'SERVER_SOFTWARE': 'Development/X', 'CONTENT_TYPE': 'application/json'})

So what am I doing wrong?

like image 494
peak Avatar asked Jun 14 '14 11:06

peak


1 Answers

This is a known error with App Engine.

Endpoints does not set the correct Content-Length header when you raise an exception:

https://code.google.com/p/googleappengine/issues/detail?id=10544

To fix it there is a diff file included in the link above, or follow my instructions to temporarily patch it by yourself.

1. Open apiserving.py

On a mac you can find the file at:

/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/endpoints-1.0/endpoints

2. Locate the following section (line 467):

It should look like this:

headers_dict = dict([(k.lower(), v) for k, v in headers])
if self.__is_json_error(status, headers_dict):
  status, body = self.protorpc_to_endpoints_error(status, body)

3. Change it to this:

headers_dict = dict([(k.lower(), v) for k, v in headers])
if self.__is_json_error(status, headers_dict):
  pre_body_length = len(body)
  status, body = self.protorpc_to_endpoints_error(status, body)
  post_body_length = len(body)
  if pre_body_length != post_body_length:
    for index, header in enumerate(headers):
      header_key, _header_value = header
      if header_key == 'content-length':
        headers[index] = (header_key, str(post_body_length))
        break

4. All done!

Endpoints will return the correct Content-Length, WebOb will be happy and your API tests will be working :)

like image 155
Robert Dodd Avatar answered Oct 05 '22 09:10

Robert Dodd