質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.93%

AngularからLaravelのAPIをたたく

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 505

dev3310

score 24

AngularアプリケーションからLaravelで作ったAPIに接続してDBのデータを取得したいのですが、うまくいきません。

●表示されるエラー
Chromeで試していますが、開発者ツールには下記のようなエラーが表示されます。

HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "http://172.21.0.5:80/api/customers", ok: false, …}
message: "Http failure response for http://172.21.0.5:80/api/customers: 0 Unknown Error"

●前提条件
・AngularアプリもLaravelアプリもdocker環境で動いています。
・ローカルPCのブラウザのURL入力欄でAPIのURLを入力すると、ちゃんとほしい情報が返ってきます。
・Angularアプリが動いているnode.jsコンテナからcurlコマンドでAPIをたたくと、ちゃんとほしい情報が返ってきます。
・クロスドメインの対応はしてあります。

●各種ソースコード

<!-- customer-list.component.html -->
<button (click)="get()">get</button>
<table >
  <tr><th>Id</th><th>Name</th>
  <tr *ngFor="let customer of customers">
    <td>{{customer.customer_number}}</td>
    <td>{{customer.name}}</td>
  </tr>
</table>
// customer-list.component.ts

import { Component, OnInit } from "@angular/core";
import { CustomerService } from "../service/customer.service";
import { Customer } from "../shared/models/customer.model";
@Component({
  selector: "app-customer-list",
  templateUrl: "./customer-list.component.html",
  styleUrls: ["./customer-list.component.scss"]
})
export class CustomerListComponent implements OnInit {
  customers: Customer[];
  constructor(private cs: CustomerService) {}

  ngOnInit(): void {}

  get() {
    this.cs.getCustomerList().subscribe(res => {
      this.customers = res;
    });
  }
}
// customer.service.ts
import { Injectable } from "@angular/core";
import { Customer } from "../shared/models/customer.model";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";
import { of } from "rxjs";
import { catchError } from "rxjs/operators";
@Injectable({
  providedIn: "root"
})
export class CustomerService {
  customers: Customer[];
  private url = "http://172.21.0.5:80/api/customers";

  constructor(private http: HttpClient) {}

  getCustomerList(): Observable<Customer[]> {
    return this.http
      .get<Customer[]>(`${this.url}`)
      .pipe(catchError(this.handleError("getCustomerList", [])));
  }

  private handleError<T>(operation = "operation", result?: T) {
    return (error: any): Observable<T> => {
      console.error(error);
      console.log(`${operation} failed: ${error.message}`);
      return of(result as T);
    };
  }
}
//customer.model.ts
export class Customer {
  customer_number: string;
  tel: string;
  name: string;
  name_kana: string;
  address: string;
  address_kana: string;
  birthday: string;
  sex: string;
  debt: number;
  point: number;
}
//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CustomerListComponent } from './customer-list/customer-list.component';

import { HttpClientModule} from '@angular/common/http'

@NgModule({
  declarations: [
    AppComponent,
    CustomerListComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

クロスオリジンの対応は以下のようにしています。

<?php

namespace App\Http\Middleware;
use Illuminate\Support\Facades\Log;
use Closure;

class Cors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $http_origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : "";

        if ($http_origin == "http://localhost:4200") {
            $response
                ->header("Access-Control-Allow-Origin" , $http_origin)
                ->header("Access-Control-Allow-Headers" , 'content-type');
        }

        return $response;
    }
}
//省略
protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \App\Http\Middleware\Cors::class, //追加
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\Cors::class, //追加
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

//省略
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyabi_takatsuk

    2020/03/10 16:33

    まず、
    export class Customerは、クラス的な使い方をしていないので、
    interfaceにした方がいいかと。
    export interface Customer
    とするということです。
    (初期化してないし、静的に使っているわけでもないため)
    もう一点、メソッド名に"get"を使うのはやめましょう。
    ゲッター定義のgetキーワードと被るので。
    (もしかしたら、それで直ったり?)

    ふむ・・・。特に問題なさそうですが、動きませんか・・・。

    キャンセル

  • keisukeh

    2020/03/29 23:19

    両方Dockerで立ち上げてるのであればDocker内のネットワークの設定がうまくいってないのではないでしょうか?

    キャンセル

回答 1

check解決した方法

0

APIのURLを
172.21.0.5⇒localhost
へ変更したら通りました。
docker-composeのymlファイルにネットワーク設定もしたし、curlではIPアドレスでちゃんと通信できていたので大丈夫かと思ったのですが、localhostのブラウザから叩いているからなのかなと考えています。
もう少し調査をしますが、一旦問題は解決しましたのでクローズさせていただきます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る