title | description | i18nReady |
---|---|---|
エンドポイント |
どんな種類のデータでも提供できるエンドポイントの作成方法について学びます。 |
true |
import RecipeLinks from "~/components/RecipeLinks.astro";
Astroでは、どんな種類のデータでも提供できるカスタムエンドポイントを作成できます。これを利用して、画像を生成したり、RSSを公開したり、またはAPIルーティングとして使用してサイトの完全なAPIを構築したりできます。
静的に生成されたサイトでは、カスタムエンドポイントは静的ファイルを生成するため、ビルド時に呼び出されます。SSRモードを選択した場合、カスタムエンドポイントはリクエストに応じて呼び出される動的なサーバーエンドポイントに変わります。静的エンドポイントとSSRエンドポイントは同じ様に定義されますが、SSRエンドポイントは追加機能をサポートします。
カスタムエンドポイントを作成するには、.js
または.ts
ファイルを/pages
ディレクトリに追加してください。.js
または.ts
の拡張子はビルドプロセス中に削除されるので、ファイル名には作成したいデータの拡張子を含める必要があります。たとえば、src/pages/data.json.ts
は、ビルドすると/data.json
エンドポイントとなります。
エンドポイントは、Astro
グローバルと同様のプロパティを持つコンテキストオブジェクトを受け取るGET
関数(async
も可)をエクスポートします。以下のエンドポイントはname
とurl
を持つレスポンスオブジェクトを返しており、Astroはビルド時にこれを呼び出し、bodyの内容を使ってファイルを生成します。
// 例: src/pages/builtwith.json.ts
// 出力: /builtwith.json
export async function GET({params, request}) {
return new Response(
JSON.stringify({
name: 'Astro',
url: 'https://astro.build/'
})
)
}
Astro v3.0以降、返り値のResponse
オブジェクトがencoding
プロパティを含む必要はなくなりました。たとえば、バイナリのpng画像を生成する場合は次のようになります。
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
return new Response(await response.arrayBuffer());
}
また、APIRoute
型を使用してエンドポイント関数に型付けもできます。
import type { APIRoute } from 'astro';
export const GET: APIRoute = async ({ params, request }) => {...}
エンドポイントは、ページと同じ動的ルーティング機能をサポートしています。ファイル名を角括弧付きのパラメーター名とし、getStaticPaths()
関数をエクスポートしてください。そして、エンドポイント関数に渡されたparams
プロパティを使用して、パラメーターにアクセスします。
import type { APIRoute } from 'astro';
const usernames = ["Sarah", "Chris", "Yan", "Elian"]
export const GET: APIRoute = ({ params, request }) => {
const id = params.id;
return new Response(
JSON.stringify({
name: usernames[id]
})
)
}
export function getStaticPaths() {
return [
{ params: { id: "0"} },
{ params: { id: "1"} },
{ params: { id: "2"} },
{ params: { id: "3"} }
]
}
これにより、ビルド時に/api/0.json
、/api/1.json
、/api/2.json
、/api/3.json
という4つのJSONエンドポイントが生成されます。エンドポイントによる動的ルーティングはページと同じように動作しますが、エンドポイントはコンポーネントではなく関数であるため、propsはサポートされていません。
すべてのエンドポイントはrequest
プロパティを受け取りますが、静的モードではrequest.url
にのみアクセスが可能です。これは、現在のエンドポイントの完全なURLを返し、Astro.request.urlがページに対して行うのと同じように動作します。
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
path: new URL(request.url).pathname
})
)
}
静的ファイルエンドポイントのセクションで説明したものはすべて、SSRモードでも使用できます。ファイルは、Astro
グローバルと同様のプロパティを持つコンテキストオブジェクトを受け取るGET
関数をエクスポートできます。
しかし、static
モードとは異なり、server
モードを設定すると、エンドポイントはリクエストされた時点でビルドされます。これにより、ビルド時には利用できない新しい機能が利用可能となり、リクエストをリッスンするAPIルートを構築したり、実行時にサーバー上で安全にコードを実行できるようになります。
<RecipeLinks slugs={["ja/recipes/call-endpoints" ]}/>
:::note これらの例を試す前に、必ずSSRを有効にしてください。 :::
サーバーエンドポイントは、getStaticPaths
のエクスポートなしでparams
にアクセスできます。また、Response
オブジェクトを返せるので、ステータスコードやヘッダーを設定できます。
import { getProduct } from '../db';
export async function GET({ params }) {
const id = params.id;
const product = await getProduct(id);
if (!product) {
return new Response(null, {
status: 404,
statusText: 'Not found'
});
}
return new Response(
JSON.stringify(product), {
status: 200,
headers: {
"Content-Type": "application/json"
}
}
);
}
これは、動的ルーティングにマッチするすべてのリクエストに応答します。たとえば、/helmet.json
に移動した場合、params.id
はhelmet
に設定されます。モックの商品データベースにhelmet
が存在すれば、エンドポイントはResponse
オブジェクトを作成してJSONで応答し、成功を意味するHTTPステータスコードを返します。存在しない場合は、Response
オブジェクトを使用して404
で応答します。
特定のプロバイダーは、SSRモードで画像を返すためにContent-Type
ヘッダーを要求します。この場合、Response
オブジェクトを使用してheaders
プロパティを指定します。以下はバイナリの.png
画像を返却する例です。
export async function GET({ params, request }) {
const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
const buffer = Buffer.from(await response.arrayBuffer());
return new Response(buffer, {
headers: { "Content-Type": "image/png" },
});
}
GET
関数に加えて、任意のHTTPメソッドの名前をもつ関数をエクスポートできます。リクエストが来た時、Astroはメソッドをチェックし、対応する関数を呼び出します。
対応するエクスポートされた関数がないHTTPメソッドにマッチするALL
関数をエクスポートすることもできます。対応するメソッドがないリクエストが来た場合、サイトの404ページにリダイレクトされます。
export const GET: APIRoute = ({ params, request }) => {
return new Response(JSON.stringify({
message: "This was a GET!"
})
)
}
export const POST: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a POST!"
})
)
}
export const DELETE: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: "This was a DELETE!"
})
)
}
export const ALL: APIRoute = ({ request }) => {
return new Response(JSON.stringify({
message: `This was a ${request.method}!`
})
)
}
<RecipeLinks slugs={["ja/recipes/captcha", "ja/recipes/build-forms-api" ]}/>
SSRモードでは、request
プロパティは、現在のリクエストを参照する完全に使用可能なRequest
オブジェクトを返します。これにより、データの取得やヘッダーのチェックができます。
export const POST: APIRoute = async ({ request }) => {
if (request.headers.get("Content-Type") === "application/json") {
const body = await request.json();
const name = body.name;
return new Response(JSON.stringify({
message: "名前: " + name
}), {
status: 200
})
}
return new Response(null, { status: 400 });
}
エンドポイントのコンテキストは、Astro.redirect
に似たredirect()
ユーティリティをエクスポートします。
import { getLinkUrl } from '../db';
export async function GET({ params, redirect }) {
const { id } = params;
const link = await getLinkUrl(id);
if (!link) {
return new Response(null, {
status: 404,
statusText: 'Not found'
});
}
return redirect(link, 307);
}