今回達成すること
前回実装したCORS設定の処理を、どこからでも呼び出せるように自作ライブラリに移動します。
そしてフォームのバリデーションを行うFunctionsプロジェクトを完成させます。
ライブライファイルを作成する
「netlify」ディレクトリ以下に、
- 自作ライブラリを置く「lib」ディレクトリと、
index.ts http-request-handler.ts
を作成しましょう。
% mkdir netlify/lib && touch $_/{index.ts,http-request-handler.ts}
「lib」ディレクトリ以下のファイルは以下の役目を持ちます。
index.ts ... 自作ライブラリを集約するファイルhttp-request-handler.ts ... HTTPリクエストの処理を行う自作ライブラリ
HTTPリクエストを処理するライブラリを作成する
HttpRequestHandler
クラスを作成します。
netlify/lib/http-request-handler.ts
export default class HttpRequestHandler {
// リクエストを許可するオリジン配列
readonly allowedOrigins: string[] = [
'http://localhost:3000'
/* 本番環境のカスタムドメインはここに追加 */
]
// 引数のオリジンが許可されている場合trueを返す
isAllowedOrigin (requestOrigin: string | undefined) {
return !!requestOrigin && this.allowedOrigins.includes(requestOrigin)
}
// CORS設定用のレスポンスヘッダを返す
corsHeaders (requestOrigin: string | undefined) {
if (!requestOrigin) {
return undefined
}
return {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Origin': requestOrigin
}
}
// CORSの許可されたオリジンか確認する
checkCors (requestOrigin: string | undefined) {
if (!this.isAllowedOrigin(requestOrigin)) {
return {
statusCode: 500
}
}
return {
statusCode: 200,
headers: this.corsHeaders(requestOrigin)
}
}
// 許可されたリクエストメソッドではない場合のレスポンス
notAllowedRequestMethod () {
return {
statusCode: 405,
body: 'Method Not Allowed'
}
}
}
readonly allowedOrigins
... 変更不可の配列を宣言。カスタムドメインと通信する場合はこの配列に追加する。
自作ライブラリをindex.tsに集約する
httpRequest
プロパティに登録します。
netlify/lib/index.ts
import HttpRequestHandler from './http-request-handler'
export default {
httpRequest: new HttpRequestHandler()
}
上記により、httpRequest.<メソッド名>
で自作ライブラリクラスのメソッドが呼び出せるようになります。
新たなライブラリを追加する場合は、プロパティを追加すればOKです。
netlify/lib/index.ts
export default {
httpRequest: new HttpRequestHandler(),
<呼び出し名>: new <クラスインスタンス生成>
}
バリデーションを行う関数を作成する
それでは
レスポンスmessage
には、バリデーションメッセージを格納します。
netlify/functions/form-validator/form-validator.ts
import { Handler, HandlerEvent, HandlerContext } from '@netlify/functions'
// 自作ライブラリの呼び出し
import lib from '~/netlify/lib'
/* eslint require-await: 'off' */
// eslint Doc: https://eslint.org/docs/user-guide/configuring/rules
export const handler: Handler = async (event: HandlerEvent, _context: HandlerContext) => {
// リクエストオリジン
const requestOrigin: string | undefined = event.headers.origin
// プリフライトリクエストの場合
if (event.httpMethod === 'OPTIONS') {
return lib.httpRequest.checkCors(requestOrigin)
// リクエストがPOSTではない場合
} else if (event.httpMethod !== 'POST') {
return lib.httpRequest.notAllowedRequestMethod()
}
const headers = lib.httpRequest.corsHeaders(requestOrigin)
let message: string = ''
if (!event.body) {
message = '値を入力してください'
} else if (event.body.length > 10) {
message = `"${event.body}"は10文字以内で入力してください`
}
return {
statusCode: 200,
headers,
body: JSON.stringify({
message
})
}
}
event.body
...axios
からのリクエストに付与されるパラメーターを取得できる。
先にプリフライトリクエストの対応を行い、
// プリフライトリクエストの場合
if (event.httpMethod === 'OPTIONS') {
return lib.httpRequest.checkCors(requestOrigin)
// リクエストがPOSTではない場合
} else if (event.httpMethod !== 'POST') {
return lib.httpRequest.notAllowedRequestMethod()
}
無事通過後、headers
の値を用意するように変更しています。
const headers = lib.httpRequest.corsHeaders(requestOrigin)
Nuxtからフォームの値をリクエストしよう
pages/index.vue
<template>
<div>
<v-container>
<!-- 削除 -->
<!-- <v-btn
@click="requestFunctions"
>
Request Functions
</v-btn> -->
<!-- 追加 -->
<v-card-title
class="font-weight-bold"
>
Netlify Functions
</v-card-title>
<v-text-field
solo
@input="formValidation"
/>
<div>
message: {{ message }}
</div>
...
</template>
<script lang="ts">
...
@Component
export default class IndexPage extends Vue {
// 追加
message: string = ''
asyncData ({ app: { $accessor } }: Context): AsyncData {
return {
categories: $accessor.categories,
posts: $accessor.posts,
tags: $accessor.tags
}
}
// 削除
// async requestFunctions (): Promise<void> {
// await this.$axios.$post(
// '/.netlify/functions/form-validator',
// { data: 'Nuxt request parameter' }
// )
// .then((response: { message: string }) => {
// console.log(response)
// })
// }
// 追加
async formValidation (inputValue: string): Promise<void> {
await this.$axios.$post(
'/.netlify/functions/form-validator',
inputValue
)
.then((response: { message: string }) => {
(this.message = response.message)
})
}
}
</script>
@input
... フォームに入力されるごとにメソッドが発火する。formValidation (inputValue: string)
...<v-text-field>
の@input
に渡すメソッド引数には、フォームに入力された値が取得できる。this.$axios.$post(..., inputValue)
... フォームに入力された値をそのままFunctionsに渡している。Functionsではevent.body
で取得可能。
表示されたフォームに10文字以上入力すると、Functionsからメッセージが返されたら成功です。
本番環境の動きを確認する
デプロイして本番環境の挙動も確認しましょう。
% yarn functions:deploy
本番環境でもメッセージが返されました。
NetlifyのFunctionsプロジェクトを開いてみましょう。
複数のログが確認取れます。
これで本番環境の挙動も正しいことが確認できました。
今回の実装は以上です。
% git add -A
% git commit -m "Add http-request-handler.ts for Fucntions library"
まとめと次回
今回は、フォームのバリデーションを行うFunctionsプロジェクトを作成しました。
以上で、ブログ検索機能のベースとなる実装はできました。
次回から本格的にブログ検索機能を構築します。