3

すべてが 1 つのホストで実行されている場合は本番環境で正常に動作し、Web アプリが別のホストで実行されている場合はほとんど動作する Google App Engine アプリがあります。GETサーバー ( 、POSTPUT、 ) との間のすべてのクエリはDELETE、期待どおりに動作しています。これは、システム全体ですべての CORS が正しく構成されていることを示しています (数週間前にその戦いを戦い、すべて解決しました)。

私が作業できないのは、ファイルのアップロードだけです。djangodjangoappenginedjango-cors-headers、およびを使用してfiletransfersいます。すべての最終的な結果として、リモート サーバーから実行しているときにファイルをアップロードできませんが、他のすべては正しく機能しています。Chrome の JavaScript コンソールに次のエラーが表示されます。

XMLHttpRequest cannot load http://localhost:8080/_ah/upload/ahl...<truncated>.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:9000' is therefore not allowed
access. The response had HTTP status code 405.

これは明らかに CORS エラーであるため、何が起こる必要があるかはおおよそわかっています。これを克服するために構成に必要な変更を加える方法がわかりません。

これが私の全体的なセットアップです:

  • dev_appserver.pyポート 8080 で API を提供する
  • grunt serveポート 9000 でクライアント アプリを提供する
  • CORS 設定:
    • 発達:CORS_ORIGIN_ALLOW_ALL = True
    • 製造:CORS_ORIGIN_WHITELIST = [ '(app.domain.com for my app)' ]

本番環境では、バケットに CORSを設定することで修正されると思いますが、私は確信が持てません。ただし、展開する前にデータの全体的なフローをテストできるように、ローカル開発サーバーを構成する方法がわかりません。

最終的に失敗する JavaScript は次のとおりです (アプリは を使用していますAngularJS)。

var form = angular.element('#media-form');
var data = new FormData(form);

// have the API return a URL using prepare_upload in
// filetransfers module to upload to:
var uploadActionUrl = https://api.domain.com/upload_url/';
$http.get(uploadActionUrl)
  .then(function(response) {
    // I get here with no problem
    $http.post(response.data.action, formData)
      .then(function(response) {
        console.log('got:', response);
      }, function(error) {
        console.log('upload error:', error); // <- this is where I end up
      });
  }, function(error) {
    console.log('get upload URL error:', error);
  });

繰り返しになりますが、このようなコードは同じホストから実行すると正しく機能し (API 自体が正しく機能します)、(重要なことに) すべての HTTP メソッドがファイルのアップロード以外のすべてのエンドポイントで機能するため、CORS 自体が正しくセットアップされます。 App Engine とのやり取り。機能していないのは、ファイルのアップロード部分だけです。

おそらく修正には、フォームの代わりに JSON を使用してアップロード用にフォームを組み立てることが含まれFormDataていると思いますが、過去にこれを行う方法を見つけたことがありません。

--- 追加するために更新 ---

明確にするために、このエラーの原因となっているエンドポイントはアプリ内に直接存在するのではなく、別の Google サービスによって処理される URL にあります。URL を提供するコードは次のとおりです。

from google.appengine.ext.blobstore import create_upload_url

def prepare_upload(request, url, **kwargs):
    return create_upload_url(
        url,
        gs_bucket_name = settings.GOOGLE_CLOUD_STORAGE_BUCKET
    ), {}

返される URL は の形式/_ah/upload/<one-time key>であり、その URL で発生するすべてのことは、ヘッダーの追加を含め、私の制御の範囲外にあるようです。

4

2 に答える 2