中安拓也のブログ

プログラミングについて書くブログ

仮想通貨取引所のAPIを使ってみる #1 - CORS問題を克服する

今回は、仮想通貨取引所であるbitFlyerのAPIを呼び出して、結果を画面に表示するところまでやります。

bitFlyerのAPIについて

bitFlyerのAPIには、認証が不要なHTTP Public APIと、認証が必要なHTTP Private APIがあるのですが、今回は認証のいらないHTTP Public APIを呼び出してみます。

bitFlyerのAPIについて、詳しくは👇を参照してください。

ビットコイン取引所【bitFlyer Lightning】

バージョン情報

APIを呼び出すアプリケーションですが、Angularを使って作成していきます。

  • Angular: 5.2.8

  • OS: Windows10(64bit)だったりMacのHigh Sierraだったり

  • typescript: 2.5.3

  • webpack: 3.11.0

  • angular/cli: 1.7.3

実装

前準備: AppModuleにHttpClientModuleを設定

APIの呼び出しにHttpClientModuleを使うため、imports: []に追加しておきます。

src/app/app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { BitFlyerService } from './services/bit-flyer.service';

import 'rxjs/add/operator/map';

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

ComponentにAPIを呼び出すServiceをDI

bitflyer APIを呼び出すBitFlyerServiceをDIしていて、ngOnInit()内ではAPIのレスポンス結果を取得しています。

src/app/app.component.ts:

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { BitFlyerService } from './services/bit-flyer.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  response: Observable<String>;

  constructor(
    private bitFlyerService: BitFlyerService,
  )  {}

  ngOnInit() {
    this.response = this.bitFlyerService.getBoard();
  }
}

HTMLの方では、取得したレスポンス結果(Observable<string>)をasyncパイプでただ表示します。

src/app/app.component.html:

<div>{{ response | async }}</div>

APIを呼び出すServiceを作成

板情報のAPIを呼び出してみます(/v1/getboard)。Angularのgetの戻り値はObservable<Object>なのでそのまま表示するには不便です。RxJSオペレーターのmapを使用して、Observable<Object>からObservable<string>に変換しています。

ちなみに板情報とは、買い・売り注文がどれくらい入っているかを示すものらしいです。こーいうの👇

src/app/services/bit-flyer.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class BitFlyerService {

  bitFlyerUrl = 'https://api.bitflyer.jp';
  bitFlyerPath = '/v1/getboard';

  constructor(
    private http: HttpClient,
  ) { }

  getBoard = (): Observable<String> => {
    return this.http
    .get(`${this.bitFlyerUrl}${this.bitFlyerPath}`)
    .map(response => JSON.stringify(response));
  }
}

動作確認1: CORSが出て失敗する

ここまで書いた段階で一回動作確認をしてみましょう。

f:id:l08084:20180316164415p:plain

Failed to load https://api.bitflyer.jp/v1/getboard: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

おなじみのCORSエラーで、レスポンスの取得に失敗してしまいます。

CORSを回避する

ブラウザ(Chrome)の起動オプションでCORSを回避しましょう。

本当はWebpackの設定(devserverproxyの設定でいけるらしい)をいじることによって回避したかったのですが、やり方がわからずに断念しました。わかる人は教えてください。

Chromeブラウザを全部閉じた状態で下記コマンドを実行すると、CORSに関するセキュリティ設定をOFFにした状態でブラウザが立ち上がります。

Windowsの場合
chrome.exe --disable-web-security --user-data-dir
Macの場合
open /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir

npm scripts を使う

毎回ターミナルに上記のコマンドを張り付けて実行するのも芸がないので、npm scriptsを使うようにします。

package.json:

  "scripts": {
    "cors:mac": "open /Applications/Google\\ Chrome.app/ --args --disable-web-security --user-data-dir",
    "cors:win": "cd C:\\\"Program Files (x86)\"\\Google\\Chrome\\Application && chrome.exe --disable-web-security --user-data-dir"
  },

package.jsoncors:maccors:winコマンドを追加しました。これらのコマンドを使うことによって、CORSに関するセキュリティをOFFにした状態でChromeを立ち上げることができます。

# Windowsの場合
$ npm run cors:win

# Macの場合
$ npm run cors:mac

動作確認2: 成功

Chromeを全部閉じてから、ターミナル上でnpm run cors:winを実行します(Macだったらnpm run cors:mac)。

f:id:l08084:20180316171358p:plain

👆🏻のような表示が出ている場合は、成功です。CORS設定がOFFになった状態でブラウザが立ち上がっています。

上記の状態で、もう一度動作確認をすると、画面上に板情報/v1/getboardのレスポンス結果が表示されるので、APIのアクセスに成功していることがわかります。

f:id:l08084:20180316172016p:plain

参考サイト

【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法 - Qiita


次回の記事はこちら