Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions site/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export default defineConfig({
integrations: [
starlight({
title: 'Echo',
defaultLocale: 'root',
locales: {
root: { label: 'English', lang: 'en' },
'zh-cn': { label: '简体中文', lang: 'zh-CN' },
ja: { label: '日本語', lang: 'ja' },
},
logo: {
light: './src/assets/logo-light.svg',
dark: './src/assets/logo-dark.svg',
Expand Down Expand Up @@ -73,9 +79,9 @@ export default defineConfig({
// Autogenerated from the content dirs — new pages appear automatically,
// ordered by each page's `sidebar.order` frontmatter.
sidebar: [
{ label: 'Guide', items: [{ autogenerate: { directory: 'guide' } }] },
{ label: 'Middleware', items: [{ autogenerate: { directory: 'middleware' } }] },
{ label: 'Cookbook', items: [{ autogenerate: { directory: 'cookbook' } }] },
{ label: 'Guide', translations: { 'zh-CN': '指南', ja: 'ガイド' }, items: [{ autogenerate: { directory: 'guide' } }] },
{ label: 'Middleware', translations: { 'zh-CN': '中间件', ja: 'ミドルウェア' }, items: [{ autogenerate: { directory: 'middleware' } }] },
{ label: 'Cookbook', translations: { 'zh-CN': '示例', ja: 'クックブック' }, items: [{ autogenerate: { directory: 'cookbook' } }] },
],
// tune the built-in code theme toward our terminal palette
expressiveCode: { themes: ['github-dark', 'github-light'] },
Expand Down
108 changes: 108 additions & 0 deletions site/src/content/docs/ja/cookbook/auto-tls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: 自動 TLS
description: Let's Encrypt から TLS 証明書を自動で取得し、更新します。
sidebar:
order: 3
---

このレシピは、ドメインの TLS 証明書を Let's Encrypt から自動取得します。autocert manager の
`TLSConfig` を使って `StartConfig` を設定し、ポート `443` で待ち受けます。

`https://<DOMAIN>` にアクセスしてください。すべて正しく設定されていれば、TLS 経由で提供される
ウェルカムメッセージが表示されます。

:::tip
- セキュリティを高めるには、autocert manager で host policy を指定してください。
- [Let's Encrypt rate limits](https://letsencrypt.org/docs/rate-limits) に達しないよう、証明書をキャッシュしてください。
- HTTP トラフィックを HTTPS にリダイレクトするには、[リダイレクトミドルウェア](/ja/middleware/redirect/#https-redirect)を使います。
:::

## サーバー

```go
package main

import (
"context"
"crypto/tls"
"errors"
"log/slog"
"net/http"
"os"

"golang.org/x/crypto/acme"

"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
"golang.org/x/crypto/acme/autocert"
)

func main() {
e := echo.New()
e.Logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))

e.Use(middleware.Recover())
e.Use(middleware.RequestLogger())

e.GET("/", func(c *echo.Context) error {
return c.HTML(http.StatusOK, `
<h1>Welcome to Echo!</h1>
<h3>TLS certificates automatically installed from Let's Encrypt :)</h3>
`)
})

m := &autocert.Manager{
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist("example.com", "www.example.com"),
// Cache certificates to avoid issues with rate limits (https://letsencrypt.org/docs/rate-limits)
Cache: autocert.DirCache("/var/www/.cache"),
// Email: "[email protected]", // optional but recommended
}

sc := echo.StartConfig{
Address: ":443",
TLSConfig: m.TLSConfig(),
}
if err := sc.Start(context.Background(), e); err != nil {
e.Logger.Error("failed to start server", "error", err)
}
}
```

## カスタム HTTP サーバーを使う

`http.Server` を完全に制御したい場合は、代わりに autocert manager をカスタム `tls.Config` に接続します。

```go
func customHTTPServer() {
e := echo.New()
e.Use(middleware.Recover())
e.Use(middleware.RequestLogger())
e.GET("/", func(c *echo.Context) error {
return c.HTML(http.StatusOK, `
<h1>Welcome to Echo!</h1>
<h3>TLS certificates automatically installed from Let's Encrypt :)</h3>
`)
})

autoTLSManager := autocert.Manager{
Prompt: autocert.AcceptTOS,
// Cache certificates to avoid issues with rate limits (https://letsencrypt.org/docs/rate-limits)
Cache: autocert.DirCache("/var/www/.cache"),
//HostPolicy: autocert.HostWhitelist("<DOMAIN>"),
}
s := http.Server{
Addr: ":443",
Handler: e, // set Echo as handler
TLSConfig: &tls.Config{
//Certificates: nil, // <-- s.ListenAndServeTLS will populate this field
GetCertificate: autoTLSManager.GetCertificate,
NextProtos: []string{acme.ALPNProto},
},
//ReadTimeout: 30 * time.Second, // use custom timeouts
}
if err := s.ListenAndServeTLS("", ""); err != nil && !errors.Is(err, http.ErrServerClosed) {
e.Logger.Error("failed to start server", "error", err)
}
}
```
119 changes: 119 additions & 0 deletions site/src/content/docs/ja/cookbook/cors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
title: CORS
description: allow list またはカスタム origin 関数で Cross-Origin Resource Sharing を有効にします。
sidebar:
order: 4
---

[CORS ミドルウェア](/ja/middleware/cors/)は、どの origin が API にアクセスできるかを制御します。
許可する origin の固定リストを渡すことも、リクエストごとに判断する関数を指定することもできます。

## origin の allow list

許可する origin を `middleware.CORS` に直接渡します。

```go
package main

import (
"context"
"net/http"

"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)

var (
users = []string{"Joe", "Veer", "Zion"}
)

func getUsers(c *echo.Context) error {
return c.JSON(http.StatusOK, users)
}

func main() {
e := echo.New()
e.Use(middleware.RequestLogger())
e.Use(middleware.Recover())

// CORS default
// Allows requests from any origin wth GET, HEAD, PUT, POST or DELETE method.
// e.Use(middleware.CORS("*"))

// CORS restricted
// Allows requests from any `https://labstack.com` or `https://labstack.net` origin
e.Use(middleware.CORS("https://labstack.com", "https://labstack.net"))

e.GET("/api/users", getUsers)

sc := echo.StartConfig{Address: ":1323"}
if err := sc.Start(context.Background(), e); err != nil {
e.Logger.Error("failed to start server", "error", err)
}
}
```

## カスタム origin 関数

動的ポリシーには、`UnsafeAllowOriginFunc` を指定した `CORSWithConfig` を使います。
この関数はリクエストコンテキストと origin を受け取り、返す origin、リクエストを許可するか、
任意のエラーを返します。

```go
package main

import (
"context"
"net/http"
"strings"

"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)

var (
users = []string{"Joe", "Veer", "Zion"}
)

func getUsers(c *echo.Context) error {
return c.JSON(http.StatusOK, users)
}

// allowOrigin takes the origin as an argument and returns:
// - origin to add to the response Access-Control-Allow-Origin header
// - whether the request is allowed or not
// - an optional error. this will stop handler chain execution and return an error response.
//
// return origin, true, err // blocks request with error
// return origin, true, nil // allows CSRF request through
// return origin, false, nil // falls back to legacy token logic
func allowOrigin(c *echo.Context, origin string) (string, bool, error) {
// In this example we use a naive suffix check but we can imagine various
// kind of custom logic. For example, an external datasource could be used
// to maintain the list of allowed origins.
if strings.HasSuffix(origin, ".example.com") {
return origin, true, nil
}
return "", false, nil
}

func main() {
e := echo.New()
e.Use(middleware.RequestLogger())
e.Use(middleware.Recover())

// CORS restricted with a custom function to allow origins
// and with the GET, PUT, POST or DELETE methods allowed.
e.Use(middleware.CORSWithConfig(middleware.CORSConfig{
UnsafeAllowOriginFunc: allowOrigin,
AllowMethods: []string{http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete},
}))

e.GET("/api/users", getUsers)

sc := echo.StartConfig{Address: ":1323"}
if err := sc.Start(context.Background(), e); err != nil {
e.Logger.Error("failed to start server", "error", err)
}
}
```
Loading
Loading