金曜日, 8月 22, 2025
金曜日, 8月 22, 2025
- Advertisment -
ホームニューステックニュースじぇ、JSONPってなんやねーん!?🤯 #初心者 - Qiita

じぇ、JSONPってなんやねーん!?🤯 #初心者 – Qiita



じぇ、JSONPってなんやねーん!?🤯 #初心者 - Qiita

はじめに

開発チームで毎週徳丸本を読んで、内容を発表する取り組みをしています。
その際に、ちょこちょこJSONPというキーワードが出てきており、
お恥ずかしながら、JSONPってなんやねーんという状態だったので、
JSONPについて調べた内容や、実際にJSONPを作って実行してみたりした
知見などを共有できればと思い、本記事を書いてみました。

JSONPってなんやねーん!?

JSONP(JSON with Padding) とは、クロスドメイン通信を可能にするため、JSONデータをJavaScript関数でラップして scriptタグ経由で取得する手法です。クライアントはcallbackパラメータで関数名を指定し、サーバーはその関数を呼び出す形式でレスポンスを返します。これにより、同一オリジンポリシーの制約を回避してデータを受け取れます。ただし、今回解説はしませんが、セキュリティ的な観点から、XSSの対策としてコールバック関数名の検証や、JSONの安全なエンコードが必要となる点は押さえておきましょう。 また、近年ではより安全なCORSを用いた方法が主流となっています。

同一オリジンポリシーとは
Same-Origin Policyとか、同一生成元ポリシーとも呼ばれます。
Webブラウザのセキュリティポリシーで、同一オリジン(※1)ではない場合、基本的にはjavascriptから異なるオリジンへの通信はできません。

このため、上述のような同一オリジンポリシーの制約を回避するには、CORS(クロスオリジンリソース共有)という機能を利用して、異なるオリジンからのリソースアクセス制限を緩和させてあげるか、JSONPを使う必要があります。

※1: スキーム(httpsとかhttp)と、ホスト(example.com)と、ポート(80とか443)が同一

JSONPの具体的な実装方法

1. クライアント側で「javascriptの関数」が実行できるよう事前に定義を済ませる
2. scriptタグのsrc属性に、レスポンスとして関数名(JSONデータ);を受け取れるエンドポイントを指定しておき、ブラウザから当該エンドポイントへGETリクエストさせる(scriptタグのsrc属性に記述したエンドポイントへのGETリクエストは同一オリジンポリシーの制約を受けません)
3. サーバー側にて関数名(JSONデータ);といった呼び出し形式でレスポンスを返す
4. クライアント側で関数名(JSONデータ);を受け取ることで、事前定義しておいた「javascriptの関数」を実行させる

これにより、同一オリジンポリシーを回避しつつ、JSONデータをサーバーから受け取り、クライアント側のjavascriptで処理させることが可能です。

実際に作って実行してみよう!

説明だけだと中々イメージが掴みにくいと思いますので、実際に作って実行してみましょう。以下はLaravel(バージョンは11系です)で実際に作成したサンプルになります。

まずは、ルーティングを定義しておきます。

routes/web.php

Route::group([
    'prefix' => 'sample',
    'middleware' => 'guest:web'
], function () {
    Route::get('render', [JsonpController::class, 'render']);
    Route::get('jsonp', [JsonpController::class, 'jsonp']);
});

次にコントローラーの処理を書きます。

app/Http/Controllers/JsonpController.php



namespace App\Http\Controllers;
use Illuminate\Http\Request;

class JsonpController extends Controller
{
    public function render(Request $request) {
        return view('sample.render');
    }
    
    public function jsonp(Request $request)
    {
        $data = [
            'message' => 'This is a JSONP response',
            'status' => 'success',
        ];

        $callback = $request->query('callback');

        if ($callback && preg_match('/^[a-zA-Z0-9_.]+$/', $callback)) {
            $json = json_encode($data, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
            return response("$callback($json);", 200)
                ->header('Content-Type', 'application/javascript');
        } else {
            return response()->json($data);
        }
    }
}

最後にビュー側の処理を書いていきます。

resources/views/sample/render.blade.php

DOCTYPE html>
html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    head>
        meta charset="utf-8">
        meta name="viewport" content="width=device-width, initial-scale=1">
        title>JSONPを試して理解title>
    head>
    body style="background-color: #222; color: greenyellow">
        div id="result">レスポンス待ちdiv>
        script>
            // 1. クライアント側で「javascriptの関数」が実行できるよう事前に定義を済ませる
            function handleJsonpResponse(data) {
                const resultDiv = document.getElementById('result');
                resultDiv.innerHTML = `
                

Status: ${data.status}

Message: ${data.message}

`
; console.log('JSONP Data:', data); } script> script src="http://localhost:8320/sample/jsonp/?callback=handleJsonpResponse">script> body> html>

ビューファイルのfunction handleJsonpResponse(data)の部分で、以下を行っています。

1. クライアント側で「javascriptの関数」が実行できるよう事前に定義を済ませる

そして、ビューファイルの



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -