"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

Django REST Framework でheadersやparamsを使う「Web-APIプロキシ」を作る

既存のWeb-APIを内部で呼び出して結果をそのまま返す「WebAPI」プロキシという手法があります。

CORS対策やインタフェースを統一して利用する側が使いやすくしたり、保守性をあげるような目的に有効な手段です。

今回は、それをDjangoを使って作ってみます。

f:id:arakan_no_boku:20190909212423j:plain
 

はじめに

 

JavaScriptから直接WebAPを利用すると、ネットワークエラーになるものがあります。

セキュリティ上の理由から、ブラウザーが、スクリプトによって開始される異なるオリジン(ドメイン)間 のHTTP リクエストを制限しているからです。

属に言う「Access-Control-Allow-Origin」エラーです。

それを回避する方法として、一旦、自分が管理できるドメイン内でWEB-APIインタフェースを作り、その中で問題になるWeb-APIを処理することでCORS(Cross-Origin Resource Sharing:オリジン間リソース共有)対策をする方法があります。

自分の管理できるドメイン内であれば特定のURLからのアクセスのみリソース共有を許す「ホワイトリスト」を設定して、JavaScriptが動くドメインからのアクセスを許可することができるというわけです。

これは「CORS_ORIGIN_ALLOW_ALL」などで何でもOKにするCORS対策よりも、セキュリティ的にも強固なので、個人的には良い方法だと思っています。

今回は、そんな「Web-APIプロキシ」の作成のうち、API-KEYの受け渡しが必要なWeb-APIDjango REST Framework (以後、DRF)で作る方法の確認をテーマにします。

具体的には。

  • ヘダーにAPI-KEYの受け渡しが必要なWEB-APIを使う。
  • URLパラメータが必要なWEB-APIを使う

ということになります。

なお。

DRFで、Web-APIプロキシ的Web-APIを作る方法は以下の記事に一度書いています。

arakan-pgm-ai.hatenablog.com

上記の記事の中でとりあげた「郵便番号API」ユーザ登録も、API-KEYも何も必要ない気軽に使えるAPIでしたから、今回はその応用版って感じです。

ipcloud.ibsnet.co.jp

 

使うAPIは「地域経済分析システムAPI

 

利用には「登録(無料)が必要」です。

登録には、メールアドレスと名前と市区町村レベルの所在地が必要です。

登録すると、API-KEYが送られてくるので、このAPIキーをリクエストヘッダー「X-API-KEY」にセットして、利用しないといけないことになってます。

以下の概要で一覧が見れますが、このAPIからとれる情報はものすごく多いです。

https://opendata.resas-portal.go.jp/docs/api/v1/index.html

f:id:arakan_no_boku:20190902203127p:plain

共通として「都道府県・市区町村」とか「産業分類」「職業分類」などが取得できて、

それらの組合せをキーにして「人口」とか「従業員数」とかみたいな個別情報が取得できるみたいな構造になってます。

今回は、「都道府県一覧 api/v1/prefectures」と「市区町村一覧 api/v1/cities」の取得と、それをキーにして人口情報を取得するという例・・というか、自分がテストとかに使うためにやってみたものを紹介してみます。

 

都道府県コード一覧取得のWEB-APIプロキシ

 

都道府県コードの一覧を取得するソースコードです。

prefectures_api.py

import requests
from rest_framework.views import APIView
from rest_framework.response import Response


class Prefectures(APIView):

    def get(self, request):
        headers = {'X-API-KEY': 'noxxxxxxxxxjK'}
        resp = requests.get(
            'https://opendata.resas-portal.go.jp/api/v1/prefectures',
            headers=headers)
        return Response(resp.json(), status=resp.status_code)

補足します。

ポイントはAPIキーの渡し方です。

headersに渡す必要があるので、上記のようなやり方をします。

 

市区町村コード一覧取得のWEB-APIプロキシ

 

都道府県コードをキーに、市区町村一覧を取得する処理です。

ソースコードはこんな感じです。

municipalities_api.py

import requests
from rest_framework.views import APIView
from rest_framework.response import Response


class Municipalities(APIView):

    def get(self, request):
        pref_code = request.GET.get(key="prefCode", default="13")
        headers = {'X-API-KEY': 'nomgUp7A61gOWlvNTaGVjX1u7IvakZUf9MBcwOjK'}
        params = {'prefCode': pref_code}
        resp = requests.get(
            'https://opendata.resas-portal.go.jp/api/v1/cities',
            headers=headers,
            params=params)
        return Response(resp.json(), status=resp.status_code)

ポイントはパラメータを受けるところと、パラメータを渡すところです。 

デフォルトは「13」(つまり東京)にしています。

基本、本物のAPIパラメータと同じ名前にしています。

 

URLSの構成

 

上記のようにクラスベースで実装したAPIは、urls.pyに以下のように登録して使います。

urls.py

from django.contrib import admin
from django.urls import path
from . import views
from . import adress_from_zip as zip
from . import prefectures_api as pref
from . import municipalities_api as city

urlpatterns = [
    path(
        'admin/',
        admin.site.urls),
    path(
        'api/v1/addresses/zip/get',
        zip.AddressFromZip.as_view(),
        name='cls-v'),
    path(
        'api/v1/prefectures',
        pref.Prefectures.as_view(),
        name='pref-v'),
    path(
        'api/v1/cities',
        city.Municipalities.as_view(),
        name='city-v'),
]

例えば、市区町村コード取得の場合だと。 

http://localhost:8000/api/v1/cities?prefcode=10

 のように使います。

実際のRESASのAPIコールのURLは

https://opendata.resas-portal.go.jp/api/v1/cities?prefCode=10

 なので、ドメイン以外のURLやパラメータ名はあわせてやるようにしてます。

取得した結果はこんな感じ。

f:id:arakan_no_boku:20190902234709p:plain

APIを直接処理した場合と同じようなJSONが返せています。

よしよし。

今回はheadersやparamsを使う「Web-APIプロキシ」を試しにやってみました。

今回はこんなところで。

ではでは。