AppEngine dev_appserver - проблема urllib2.urlopen с адресом localhost

UPDATE

App Engine SDK 1.9.24 был выпущен 20 июля 2015 года, поэтому, если вы все еще испытываете это, вы должны иметь возможность исправить это просто путем обновления. См. + Jpatokal ответ ниже для объяснения точной проблемы и решения.

Оригинальный вопрос

У меня есть приложение, с которым я работаю и сталкиваюсь с проблемами при разработке локально.

У нас есть общий код, который проверяет сервер auth для наших приложений с помощью urllib2.urlopen. Когда я разрабатываю локально, меня отклоняют с помощью 404 в моем приложении, которое делает запрос из AppEngine, но запрос успешно завершен с терминала.

У меня appengine работает на порту localhost:8000, а сервер auth на localhost:8001

import urllib2

url = "http://localhost:8001/api/CheckAuthentication/?__client_id=dev&token=c7jl2y3smhzzqabhxnzrlyq5r5sdyjr8&username=amadison&__signature=6IXnj08bAnKoIBvJQUuBG8O1kBuBCWS8655s3DpBQIE="

try:
  r = urllib2.urlopen(url)
  print(r.geturl())
  print(r.read())
except urllib2.HTTPError as e:
  print("got error: {} - {}".format(e.code, e.reason))

что приводит к got error: 404 - Not Found из AppEngine

Похоже, что AppEngine добавляет схему, хост и порт в часть PATH URL-адреса, которую я пытаюсь нажать, так как это то, что я вижу на сервере auth:

[02/Jul/2015 16:54:16] "GET http://localhost:8001/api/CheckAuthentication/?__client_id=dev&token=c7jl2y3smhzzqabhxnzrlyq5r5sdyjr8&username=amadison&__signature=6IXnj08bAnKoIBvJQUuBG8O1kBuBCWS8655s3DpBQIE= HTTP/1.1" 404 10146

и из заголовка запроса мы видим всю схему, а хост и порт передаются вместе с частью пути (заголовки ниже):

 'HTTP_HOST': 'localhost:8001',
 'PATH_INFO': u'http://localhost:8001/api/CheckAuthentication/',
 'SERVER_PORT': '8001',
 'SERVER_PROTOCOL': 'HTTP/1.1',

Есть ли способ, чтобы сервер AppEngine Dev не захватил этот запрос на localhost на другом порту? Или я не понимаю, что происходит? Все работает отлично в производстве, где наши домены разные.

Заранее благодарим за помощь, помогающую указать мне в правильном направлении.

Ответ 1

App Engine SDK 1.9.24 был выпущен 20 июля 2015 года, поэтому, если вы все еще испытываете это, вы должны иметь возможность Исправьте это, просто обновив.

Вот краткое объяснение того, что произошло. До 1.9.21 SDK форматировал запросы выборки URL с относительными путями, например:

GET /test/ HTTP/1.1
Host: 127.0.0.1:5000

В 1.9.22, чтобы лучше поддерживать прокси, это изменилось на абсолютные пути:

GET http://127.0.0.1:5000/test/ HTTP/1.1
Host: 127.0.0.1:5000

Оба формата совершенно легальны по спецификации HTTP/1.1, см. RFC 2616, раздел 5.1.2. Однако, хотя эта спецификация датируется 1999 годом, существует, по-видимому, довольно много обработчиков запросов HTTP, которые не анализируют абсолютную форму правильно, а просто наивно объединяют путь и хост вместе.

Таким образом, в интересах совместимости предыдущее поведение было восстановлено. (Если вы не используете прокси, в этом случае RFC требует абсолютных путей.)

Ответ 2

Это раздражающая проблема, связанная с реализацией urlfetch_stub. Я не уверен, что версия gcloud sdk представила его.

Я исправил это, установив gcloud SDK - пока Google не сделает.

что означает, что этот ответ, надеюсь, будет неактуальным в ближайшее время

  • Найдите и откройте urlfetch_stub.py, который часто можно найти в ~/google-cloud-sdk/platform/google_appengine/google/appengine/api/urlfetch_stub.py

  • Вокруг строки 380 (зависит от версии), найдите:

full_path = urlparse.urlunsplit((protocol, host, path, query, ''))

и замените его на:

full_path = urlparse.urlunsplit(('', '', path, query, ''))

больше информации

Вы были уверены, что проблема связана с сломанным заголовком PATH_INFO. full_path здесь передается после того, как соединение выполнено.

отказ от ответственности

Я могу очень легко сломать прокси-запросы с этим патчем. Поскольку я ожидаю, что Google исправит это, я не собираюсь сходить с ума.

Чтобы быть предельно ясным , эта ошибка ТОЛЬКО относится к разработке локальных приложений - вы не увидите этого при создании.