Netlify Functionsを使ってフォームバリデーション機能を構築しよう【Nuxt.js】
  • 2022.02.17に公開
  • ブログ構築TS
  • 8. NetlifyFunctionsを使った検索機能
  • No.5 / 9

今回達成すること

前回実装したCORS設定の処理を、どこからでも呼び出せるように自作ライブラリに移動します。

そしてフォームのバリデーションを行うFunctionsプロジェクトを完成させます。

2022-02-17 12-48-37

ライブライファイルを作成する

「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リクエストを処理するライブラリを作成する

http-request-handler.tsに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に集約する

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 <クラスインスタンス生成>
}

バリデーションを行う関数を作成する

それではform-validator.tsから自作ライブラリを呼び出し、バリデーションを行う関数を作成します。

レスポンス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からフォームの値をリクエストしよう

index.vueに新たにフォームを用意し、入力の度にNuxtからFunctionsへリクエストを行うように編集します。

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からメッセージが返されたら成功です。

2022-02-17 12-48-37

本番環境の動きを確認する

デプロイして本番環境の挙動も確認しましょう。

% yarn functions:deploy

本番環境でもメッセージが返されました。

2022-02-17 17-28-45

NetlifyのFunctionsプロジェクトを開いてみましょう。

複数のログが確認取れます。

2022-02-17 17-26-56

これで本番環境の挙動も正しいことが確認できました。

今回の実装は以上です。

% git add -A
% git commit -m "Add http-request-handler.ts for Fucntions library"

まとめと次回

今回は、フォームのバリデーションを行うFunctionsプロジェクトを作成しました。

以上で、ブログ検索機能のベースとなる実装はできました。

次回から本格的にブログ検索機能を構築します。

あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
ブログ構築TSの投稿
1
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #01
Nuxt.jsをローカルPCに立ち上げよう
2
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #02
Nuxt.jsプロジェクトをGitHubにPushしよう
3
  • Nuxt.js×TypeScript開発環境構築
  • /
  • #03
nuxt-property-decoratorのインストールとTypeScriptのセットアップ
1
  • Vuetifyセットアップ
  • /
  • #01
TypeScript環境のNuxt.jsにVuetifyを導入しよう
2
  • Vuetifyセットアップ
  • /
  • #02
VuetifyにカスタムCSSを追加してSASS変数を理解しよう
3
  • Vuetifyセットアップ
  • /
  • #03
VuetifyにカスタムSVGアイコンを追加しよう
1
  • NetlifyCLIを使ったNuxtデプロイ
  • /
  • #01
Netlify CLIをインストールして本番環境のサイトを作成しよう
2
  • NetlifyCLIを使ったNuxtデプロイ
  • /
  • #02
netlify.tomlを使ってNuxt.jsをNetlifyに手動デプロイしよう
1
  • Contentfulモデル構築
  • /
  • #01
Contentfulの料金とCommunityプランの無料枠を理解する
2
  • Contentfulモデル構築
  • /
  • #02
Contentfulへ新規会員登録、ロケールの変更、API Keyの発行を行う
3
  • Contentfulモデル構築
  • /
  • #03
Contentful ブログカテゴリーモデルを作成しよう
4
  • Contentfulモデル構築
  • /
  • #04
Contentful カテゴリーモデルに1対1で関連づくblogPostモデルを作成しよう
5
  • Contentfulモデル構築
  • /
  • #05
Contentful ブログ記事に1対多で関連づくplogTagモデルを作成しよう
6
  • Contentfulモデル構築
  • /
  • #06
Contentful カテゴリー・ブログ記事・タグコンテンツを作成しよう
1
  • Nuxt.js×Contentfulセットアップ
  • /
  • #01
Nuxt.js×Contentfulセットアップ。モジュールのインストールからAPI Keyの登録まで
2
  • Nuxt.js×Contentfulセットアップ
  • /
  • #02
Contentful APIリクエストの実行 Nuxt.jsにブログコンテンツを表示しよう
3
  • Nuxt.js×Contentfulセットアップ
  • /
  • #03
ContentfulAPIをNetlifyにデプロイしよう【Nuxt FullStaticのasyncDataとfetch】
1
  • Vuex×TypeScriptセットアップ
  • /
  • #01
Vuexの型付け vuex-module-decoratorsとnuxt-typed-vuexどちらを使用するか
2
  • Vuex×TypeScriptセットアップ
  • /
  • #02
nuxt-typed-vuexのインストールとセットアップ。Vuexの型定義と呼び出し方
3
  • Vuex×TypeScriptセットアップ
  • /
  • #03
VuexにContentfulの型定義ファイルとnuxtServerInitを追加しよう
4
  • Vuex×TypeScriptセットアップ
  • /
  • #04
VuexにContentfulAPIレスポンスを保存してVueファイルに表示しよう
1
  • コンテンツページ構築
  • /
  • #01
ブログアプリのページ設計とNuxt.jsの動的ルーティングについて理解しよう
2
  • コンテンツページ構築
  • /
  • #02
カテゴリーのコンテンツページを作成しよう【Nuxt.js×Contentful】
3
  • コンテンツページ構築
  • /
  • #03
カテゴリーに関連付くブログ記事一覧を表示しよう【Nuxt.js×Contentful】
4
  • コンテンツページ構築
  • /
  • #04
injectを使用して共通エラー処理メソッドを作成しよう【Nuxt×TypeScript】
5
  • コンテンツページ構築
  • /
  • #05
NuxtChildを使用してブログ記事ページを作成しよう【Nuxt.js×TypeScript】
6
  • コンテンツページ構築
  • /
  • #06
タグ一覧ページとタグ関連づく記事一覧を表示しよう【Nuxt.js×TypeScript】
7
  • コンテンツページ構築
  • /
  • #07
プライバシーポリシーページを作成しよう【Nuxt.js×TypeScript】
8
  • コンテンツページ構築
  • /
  • #08
@nuxtjs/i18nのインストールとセットアップ。ページタイトルの翻訳化【TypeScript】
1
  • NetlifyFunctionsを使った検索機能
  • /
  • #01
Netlify Functionsを使ってクエリを返す関数を作成しよう【Nuxt.js×TypeScript】
2
  • NetlifyFunctionsを使った検索機能
  • /
  • #02
Netlify Functionsプロジェクトをデプロイしよう【Nuxt.js×TypeScript】
3
  • NetlifyFunctionsを使った検索機能
  • /
  • #03
Nuxt.js × axiosセットアップ Netlify Functionsにリクエストを行う準備をしよう
4
  • NetlifyFunctionsを使った検索機能
  • /
  • #04
オリジン•CORS•プリフライトリクエストを理解する【Nuxt.js×Netlify Functions】
5
  • NetlifyFunctionsを使った検索機能
  • /
  • #05
Netlify Functionsを使ってフォームバリデーション機能を構築しよう【Nuxt.js】
6
  • NetlifyFunctionsを使った検索機能
  • /
  • #06
ツールバーに表示する検索フォームを作成しよう【Nuxt.js×TypeScript】
7
  • NetlifyFunctionsを使った検索機能
  • /
  • #07
検索ページを作成しよう【Vue propsとTypeScriptの書き方 解説】
8
  • NetlifyFunctionsを使った検索機能
  • /
  • #08
Netlify FunctionsからContentfulAPIリクエストを送ろう【Nuxt.js】
9
  • NetlifyFunctionsを使った検索機能
  • /
  • #09
検索ページに「もっと見る」ボタンを実装しよう【Nuxt.js×TypeScript】
1
  • ブログMarkdown対応
  • /
  • #01
@nuxtjs/markdownitのインストールとセットアップ【Nuxt.js×TypeScript】
2
  • ブログMarkdown対応
  • /
  • #02
Nuxt.js×markdown-it 外部リンクを別タブで開くプラグインを追加しよう
3
  • ブログMarkdown対応
  • /
  • #03
Nuxt.js×markdown-it 内部リンクをVueRouterで高速にページ遷移しよう
4
  • ブログMarkdown対応
  • /
  • #04
Nuxt.js×markdown-it アンカーリンクとブログ目次を自動生成しよう
独学プログラマ
独学でも、ここまでできるってよ。
CONTACT
Nuxt.js制作のご依頼は下記メールアドレスまでお送りください。