Пирамида в App Engine получает "InvalidResponseError: значения заголовка должны быть str, получены 'unicode' - PullRequest
4 голосов
/ 30 марта 2012

Я использую Pyramid 1.3 с AppEngine 1.6.4 SDK на OS X 10.7.3. Я использую Python 2.7, и в app.yaml есть true потокобезопасности.

@view_config(route_name='manager_swms', permission='manager', renderer='manager/swms.jinja2')
def manager_swms(request):
    """Generates blobstore url and passes users swms in swms table"""

    # generate url for any form upload that may occur
    upload_url = blobstore.create_upload_url('/upload_swm')

    user = get_current_user(request)
    swms = DBSession.query(SWMS).filter_by(owner_id=int(user.id)).all()

    return {
        "analytics_id": analytics_id,
        "user": get_current_user(request),
        "upload_url": upload_url,
        "swms": [(x.filename, x.blob_key) for x in swms]
    }

class BlobstoreUploadHandler(object):
    """Base class for creation blob upload handlers."""

    def __init__(self, *args, **kwargs):
        self.__uploads = None

    def get_uploads(self, field_name=None):
        """Get uploads sent to this handler.

        Args:
          field_name: Only select uploads that were sent as a specific field.

        Returns:
          A list of BlobInfo records corresponding to each upload.
          Empty list if there are no blob-info records for field_name.
        """
        if self.__uploads is None:
            self.__uploads = {}
            for key, value in self.request.params.items():
                if isinstance(value, cgi.FieldStorage):
                    if 'blob-key' in value.type_options:
                        self.__uploads.setdefault(key, []).append(
                            blobstore.parse_blob_info(value))

        if field_name:
            try:
                return list(self.__uploads[field_name])
            except KeyError:
                return []
        else:
            results = []
            for uploads in self.__uploads.itervalues():
                results += uploads
            return results

@view_config(route_name='upload_swm', permission='manager')
class UploadHandler(BlobstoreUploadHandler):
    ''' Handles redirects from Blobstore uploads. '''

    def __init__(self, request):
        self.request = request
        super(UploadHandler, self).__init__()

    def __call__(self):

        user = get_current_user(self.request)
        for blob_info in self.get_uploads('file'):

            new_swm = SWMS(
                owner_id = int(user.id),
                blob_key = str(blob_info.key()),
                filename = blob_info.filename,
                size = blob_info.size,
            )
            DBSession.add(new_swm)
        DBSession.flush()

        # redirect to swms page
        return HTTPFound(location='/manager/swms')

В приведенном выше коде manager_swms () создает страницу, которая включает форму для загрузки файла в Blobstore. Форма работает нормально, и я вижу, как блоб появляется в Blobstore, когда форма используется. Перенаправление из POST в Blobstore происходит в / upload_swm, где я успешно беру детали BlobInfo и помещаю их в таблицу SQL. Все это хорошо, и последнее, что я хочу сделать, - это перенаправить на первую страницу, чтобы при необходимости можно было загрузить другой файл и показать список загруженных файлов.

Согласно документации Pyramid, я использую HTTPFound (location = '/ manager / swms') [URL-адрес исходной страницы], чтобы попытаться перенаправить, однако я получаю:

ERROR    2012-03-29 22:56:38,170 wsgi.py:208] 
Traceback (most recent call last):
  File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 196, in Handle
    result = handler(self._environ, self._StartResponse)
  File "lib/dist/pyramid/router.py", line 195, in __call__
    foo = response(request.environ, start_response)
  File "lib/dist/pyramid/httpexceptions.py", line 291, in __call__
    foo = Response.__call__(self, environ, start_response)
  File "lib/dist/webob/response.py", line 922, in __call__
    start_response(self.status, headerlist)
  File "/Users/tim/work/OHSPro/var/parts/google_appengine/google/appengine/runtime/wsgi.py", line 150, in _StartResponse
    _GetTypeName(header[1]))
InvalidResponseError: header values must be str, got 'unicode'
INFO     2012-03-29 22:56:38,174 dev_appserver_blobstore.py:408] Upload handler returned 500
INFO     2012-03-29 22:56:38,193 dev_appserver.py:2884] "POST /_ah/upload/ahJkZXZ-cHJvdG8tc2NvaHNwcm9yGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgTDA HTTP/1.1" 500 -

AppEngine явно возражает против юникода в заголовке HTTP, но я не делаю ничего необычного AFAIK. Если я загляну в pdb и посмотрю на объект HTTPFound, заголовки будут:

ResponseHeaders([('Content-Type', 'text/html; charset=UTF-8'), ('Content-Length', '0'), ('Location', '/manager/swms')])

Зачем мне получать проблемы с юникодом от них?

Ответы [ 2 ]

2 голосов
/ 30 марта 2012

выглядит так, как будто вы переопределяете поддерживаемый appengine webob, который равен 1.1.1 в 2.7 времени выполнения. И пирамида 1.3 зависит от webob> = 1.2. Скорее всего, это проблема, потому что обработчик Blobstore удерживал sdk на уровне webob == 0.9 до выхода SDK 1.6.4.

FWIW, эта проблема, как ожидается, будет решена SDK 1.6.5 (конец апреля). Единственная причина, по которой я это знаю, заключается в том, что я пытался разрешить все это дерьмо, когда среда выполнения 2.7 считалась готовой для общего использования, но SDK не поддерживал ее. см. этот выпуск для более подробной информации.

Если возможно, я бы предложил запустить его с пирамидой 1.2, я знаю, что он отлично работает на appengine. И просто отложите переход на 1,3 в течение нескольких недель. :)

0 голосов
/ 09 апреля 2014

Еще один ответ ... добавление str () решает проблему, но не первопричину. Я потратил часы, пытаясь выяснить, почему один конкретный редирект вызвал эту ошибку, в то время как другие этого не сделали, прежде чем заметил, что в URL для неверного перенаправления отсутствует начальный "/".

Понятия не имею почему это так - возможно, неполный путь обрабатывается иначе, чем полный. Но если вы нажали эту ошибку, попробуйте изменить:

self.redirect('home.view')

до:

self.redirect('/home.view')
...