👾

Go言語でHTMLのファイルを表示してみた

2023/07/27に公開

挨拶するだけのHTMLを表示する

これだけなら簡単ですね。今回は、echoというフレームワークを使って、HTMLのファイルを表示してみようと思います。

echoの環境構築はこちらの記事が参考になると思います
https://zenn.dev/joo_hashi/articles/c22ae94460b59a

🏠HTMLのファイルを用意する

/helloのURLにアクセスすると表示されるページ

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
      body {
        background-color: #eee;
      }
      .container {
        text-align: center;
        font-size: 50px;
        color: #666;
      }
    </style>
    <title>Document</title>
  </head>
  <body>
    <div class="container">
      <h1>Hello Go!</h1>
    </div>
  </body>
</html>

404 Not Foundのページを返すHTMLファイル。存在しないURLにアクセスすると表示されます。

404.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>404 Not Found</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        background-color: #f1f1f1;
        margin: 0;
      }
      h1 {
        font-size: 3rem;
        color: #666;
        text-align: center;
      }
      p {
        font-size: 1.5rem;
        color: #666;
        text-align: center;
      }
    </style>
  </head>
  <body>
    <h1>404 Not Found</h1>
  </body>
</html>

🦍Goのコード

Hello Worldのメッセージを変えるAPIと、プロジェクト内に配置したhtmlのファイルを表示するコードです。404.htmlだけは、特殊で存在しないURLにアクセスしたときだけ表示されます。

server.go
package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	// 404ページを表示する関数を実行
	e.HTTPErrorHandler = customHTTPErrorHandler

	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	// /helloのURLにアクセスしたら、Hello GolangというHTMLを返す
	e.GET("/hello", getGreet)
	e.Logger.Fatal(e.Start(":1323"))
}

// h1タグでHello Golangと表示するHTMLを返す
func getGreet(c echo.Context) error {
	return c.File("index.html")
}

// 404ページを表示する関数
func customHTTPErrorHandler(err error, c echo.Context) {
	code := http.StatusInternalServerError
	message := http.StatusText(code)

	if he, ok := err.(*echo.HTTPError); ok {
		code = he.Code
		message = he.Message.(string)
	}

	if code == http.StatusNotFound {
		// 404エラーの場合は404.htmlを返す
		c.File("404.html")
		return
	}

	c.JSON(code, map[string]interface{}{
		"error": map[string]interface{}{
			"code":    code,
			"message": message,
		},
	})
}

URLにアクセスしてみる

Hello Goのページ
http://localhost:1323/hello

存在しないページのURL
http://localhost:1323/fuga

最後に

GoはAPIを作るための言語で、本来はHTMLを表示してテンプレートエンジンを使うような使い方ではないです。もし、Webアプリを作る場合は、Next.js、Reactで作ることになるでしょう。

Next.jsでHTTP通信したら、CORSのエラーにハマりました!
パッケージの追加と、コードの修正をしたら、できました!
私の場合はこれを追加した

go get github.com/labstack/echo/v4@v4.1.17

コードを修正する

package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware" // <-- 追加
)

func main() {
	e := echo.New()

	// CORSを許可する
	e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
		AllowOrigins: []string{"*"},
		AllowMethods: []string{echo.GET, echo.PUT, echo.POST, echo.DELETE},
	}))

	// 404ページを表示する関数を実行
	e.HTTPErrorHandler = customHTTPErrorHandler

	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	// /helloのURLにアクセスしたら、Hello GolangというHTMLを返す
	e.GET("/hello", getGreet)

	// /api/helloのURLにアクセスしたら、Hello GoというJSONを返す
	e.GET("/api/hello", getHello)

	e.Logger.Fatal(e.Start(":1323"))
}

// h1タグでHello Golangと表示するHTMLを返す
func getGreet(c echo.Context) error {
	return c.File("index.html")
}

// Hello GoのJSONを返す関数
// Hello GoのJSONを返す関数
func getHello(c echo.Context) error {
	dummyData := []map[string]interface{}{
		{
			"id":      1,
			"message": "Hello Go",
		},
		{
			"id":      2,
			"message": "Hello again, Go",
		},
		{
			"id":      3,
			"message": "Hello once more, Go",
		},
	}

	return c.JSON(http.StatusOK, dummyData)
}


// 404ページを表示する関数
func customHTTPErrorHandler(err error, c echo.Context) {
	code := http.StatusInternalServerError
	message := http.StatusText(code)

	if he, ok := err.(*echo.HTTPError); ok {
		code = he.Code
		message = he.Message.(string)
	}

	if code == http.StatusNotFound {
		// 404エラーの場合は404.htmlを返す
		c.File("404.html")
		return
	}

	c.JSON(code, map[string]interface{}{
		"error": map[string]interface{}{
			"code":    code,
			"message": message,
		},
	})
}

Next.jsのコード

Next.js13からは、appディレクトリなるものに変わったので、use clientをつけないとサーバーサイドコンポーネントになるそうです!

'use client';
import { useState, useEffect } from "react";

interface Hello {
  id: number;
  message: string;
}

const APIPage = () => {
  const [hello, setHello] = useState<Hello[]>([]);
  useEffect(() => {
    const url = "http://localhost:1323/api/hello";
    fetch(url)
      .then((res) => res.json())
      .then((json) => {
        setHello(json);
      })
      .catch((err) => {
        console.log(err);
      });
  }, []);

  return (
    <div>
      <ul>
        {
          hello.map((h, index) => (
            <li key={index}>
              {h.id} {h.message}
            </li>
          ))
        }
      </ul>
    </div>
  );
}

export default APIPage;

コンポーネントを読み込む

import Counter from "./client/Counter";
import APIPage from "./client/Fetch";

export default function Home() {
  return (
    <div>
      <APIPage />
    </div>
  );
}

実行結果
配列のデータを取得して、UIに表示できました🙌

コンソール見ると、エラーが出てるのでまだ改良が必要そうです。今回はこれでOK

Discussion