2016-03-29 14 views
2

私はangular2の "ヒーローのツアー"のチュートリアルを成功裏に終えました。それから、バックエンドとしてsymfony3、FosRestBundle、BazingaHateoasBundleに基づくAPIをビルドします。 ほとんどすべての機能が動作しますが、新しいアイテムの作成時には、新しく作成されたアイテムを読み込むためのレスポンスから「Location」ヘッダーを取得できません。私はaddHeroメソッドを呼んでいるときangular2/httpは201の応答ヘッダを取得します

import {Injectable} from "angular2/core"; 
import {Hero} from "./hero"; 
import {Http, Headers, RequestOptions, Response} from "angular2/http"; 
import {Observable} from "rxjs/Observable"; 
import "rxjs/Rx"; 

@Injectable() 
export class HeroService { 

    constructor(private _http:Http) { 
    } 

    private _apiUrl = 'http://tour-of-heros.loc/app_dev.php/api'; // Base URL 
    private _heroesUrl = this._apiUrl + '/heroes'; // URL to the hero api 


    getHeroes() { 
     return this._http.get(this._heroesUrl) 
      .map(res => <Hero[]> res.json()._embedded.items) 
      .do(data => console.log(data)) // eyeball results in the console 
      .catch(this.handleError); 
    } 

    addHero(name:string):Observable<Hero> { 

     let body = JSON.stringify({name}); 

     let headers = new Headers({'Content-Type': 'application/json'}); 
     let options = new RequestOptions({headers: headers}); 

     return this._http.post(this._heroesUrl, body, options) 
      // Hero is created, but unable to get URL from the Location header! 
      .map((res:Response) => this._http.get(res.headers.get('Location')).map((res:Response) => res.json())) 
      .catch(this.handleError) 

    } 

    private handleError(error:Response) { 
     // in a real world app, we may send the error to some remote logging infrastructure 
     // instead of just logging it to the console 
     console.error(error); 
     return Observable.throw(error.json().error || 'Server error'); 
    } 

    getHero(id:number) { 
     return this._http.get(this._heroesUrl + '/' + id) 
      .map(res => { 
       return res.json(); 
      }) 
      .do(data => console.log(data)) // eyeball results in the console 
      .catch(this.handleError); 
    } 
} 

ので、新しいヒーローが作成され、201応答は体のない、しかし、Locationヘッダセットで返されます:

ここ

は私のヒーロー・サービスであります

Cache-Control: no-cache 
Connection: Keep-Alive 
Content-Length: 0 
Content-Type: application/json 
Date: Tue, 29 Mar 2016 09:24:42 GMT 
Keep-Alive: timeout=5, max=100 
Location: http://tour-of-heros.loc/app_dev.php/api/heroes/3 
Server: Apache/2.4.10 (Debian) 
X-Debug-Token: 06323e 
X-Debug-Token-Link: /app_dev.php/_profiler/06323e 
access-control-allow-credentials: true 
access-control-allow-origin: http://172.18.0.10:3000 

問題は、res.headers.get('Location')が応答からロケーションヘッダーを取得しなかったことです。 デバッグ後、res.headersは2つのヘッダーCache-ControlとContent-Typeを提供しているようです。しかし、場所はありません。

新しく作成されたデータをレスポンス本体に追加することで問題を解決することも可能であることはわかっていましたが、実際にこれを解決する方法ではありません。

ありがとうございます!

+0

'場所を貢献すべての人へ

感謝します。それはあなたの '応答オブジェクト'によって含まれていますか?そうであれば、何が問題なのですか? – micronyks

+0

いいえ、私はレスポンスオブジェクトでそれを見つけられませんでした。私はこれが問題だと確信しています;)。しかし、私はどこでそれを探し求めなければならないのか分かりません。 – skroczek

+0

この最後のスニペットはどのようにして得ましたか? – micronyks

答えて

5

あなたはmap 1の代わりにflatMap演算子を使用する必要があります。

return this._http.post(this._heroesUrl, body, options) 
     .flatMap((res:Response) => { 
      var location = res.headers.get('Location'); 
      return this._http.get(location); 
     }).map((res:Response) => res.json())) 
     .catch(this.handleError) 

編集

あなたのヘッダーの問題について。

あなたの問題はCORSに関連していると思います。私は、プレフライトされたリクエストは、その応答のAccess-Control-Allow-Headersで承認するためのヘッダを返さなければならないと思います。そのような何か:

Access-Control-Allow-Headers:location 

あなたは、コールのサーバー側で手を持っている場合、あなたは、クライアント側(in your case Location`)上で使用するヘッダと、このヘッダを更新することができます。

リクエストを実際に実行したXhrBackendクラス内でリクエストをデバッグし、XHRオブジェクトからの応答を取得しました。ヘッダーはコード_xhr.getAllResponseHeaders()によって返されません。私の場合、私はContent-Typeのものしか持っていません。

このリンクを参照してください:https://github.com/angular/angular/blob/master/modules/angular2/src/http/backends/xhr_backend.ts#L42

次の質問から

クロスオリジンリソース共有の仕様では、非同一生成元の要求に対してgetResponseHeader()で公開されているヘッダをフィルタリングします。この仕様では、単純なレスポンスヘッダフィールド以外のレスポンスヘッダフィールドへのアクセスを禁止しています。Cache-Control、コンテンツ言語、コンテンツの種類、有効期限、最終修飾、およびプラグマ):

詳細については、この質問を参照してください:私のせい

+0

あなたの答えをありがとう。しかし、同じ問題、 'res.headers.get( 'Location')'は 'null'を返します。 – skroczek

+0

私の答え@skroczekを更新しました。私はあなたが問題はCORSに関連していると思う... –

+0

あなたの権利! CORSが問題です。私自身の答えを見てください。どうもありがとう! – skroczek

4

を!

https://github.com/angular/angular/issues/5237http://www.aaron-powell.com/posts/2013-11-28-accessing-location-header-in-cors-response.htmlを読んだ後、私はNelmioCorsBundle(https://github.com/nelmio/NelmioCorsBundle/issues/9)の私のCORSの設定に何か問題がなければならないことを認識しています。迅速な&汚い修正として 私はsymfonyの設定にexpose_headers: ['Origin','Accept','Content-Type', 'Location']を追加しました:後

nelmio_cors: 
    paths: 
     '^/api/': 
      allow_credentials: true 
      origin_regex: true 
      allow_origin: ['*'] 
      allow_headers: ['Origin','Accept','Content-Type', 'Location'] 
      allow_methods: ['POST','GET','DELETE','PUT','OPTIONS'] 
      max_age: 3600 

::前

nelmio_cors: 
    paths: 
     '^/api/': 
      allow_credentials: true 
      origin_regex: true 
      allow_origin: ['*'] 
      allow_headers: ['Origin','Accept','Content-Type', 'Location'] 
      allow_methods: ['POST','GET','DELETE','PUT','OPTIONS'] 
      expose_headers: ['Origin','Accept','Content-Type', 'Location'] 
      max_age: 3600 

そして今、それは魔法のように動作します。

これは角の問題ではなく、決して解決できませんでした。ごめんなさい!同様のCORS問題を偶然見つけたすべての人にこれを守ります。ます。http://ツアー・オブ・heros.loc/app_dev.php/API /ヒーロー/ 3`

関連する問題