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
7 changes: 4 additions & 3 deletions site/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default defineConfig({
'zh-cn': { label: '简体中文', lang: 'zh-CN' },
ja: { label: '日本語', lang: 'ja' },
es: { label: 'Español', lang: 'es' },
'pt-br': { label: 'Português', lang: 'pt-BR' },
},
logo: {
light: './src/assets/logo-light.svg',
Expand Down Expand Up @@ -104,9 +105,9 @@ export default defineConfig({
// Autogenerated from the content dirs — new pages appear automatically,
// ordered by each page's `sidebar.order` frontmatter.
sidebar: [
{ label: 'Guide', translations: { 'zh-CN': '指南', ja: 'ガイド', es: 'Guía' }, items: [{ autogenerate: { directory: 'guide' } }] },
{ label: 'Middleware', translations: { 'zh-CN': '中间件', ja: 'ミドルウェア', es: 'Middleware' }, items: [{ autogenerate: { directory: 'middleware' } }] },
{ label: 'Cookbook', translations: { 'zh-CN': '示例', ja: 'クックブック', es: 'Recetario' }, items: [{ autogenerate: { directory: 'cookbook' } }] },
{ label: 'Guide', translations: { 'zh-CN': '指南', ja: 'ガイド', es: 'Guía', 'pt-BR': 'Guia' }, items: [{ autogenerate: { directory: 'guide' } }] },
{ label: 'Middleware', translations: { 'zh-CN': '中间件', ja: 'ミドルウェア', es: 'Middleware', 'pt-BR': 'Middleware' }, items: [{ autogenerate: { directory: 'middleware' } }] },
{ label: 'Cookbook', translations: { 'zh-CN': '示例', ja: 'クックブック', es: 'Recetario', 'pt-BR': 'Receitas' }, items: [{ autogenerate: { directory: 'cookbook' } }] },
],
// tune the built-in code theme toward our terminal palette
expressiveCode: { themes: ['github-dark', 'github-light'] },
Expand Down
110 changes: 110 additions & 0 deletions site/src/content/docs/pt-br/cookbook/auto-tls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
title: Auto TLS
description: Obtenha e renove automaticamente certificados TLS da Let's Encrypt.
sidebar:
order: 3
---

Esta receita obtém certificados TLS para um domínio automaticamente da Let's Encrypt.
Configure um `StartConfig` com o `TLSConfig` do gerenciador autocert e escute na
porta `443`.

Acesse `https://<DOMAIN>`. Se tudo estiver configurado corretamente, você deverá ver
uma mensagem de boas-vindas servida por TLS.

:::tip
- Para segurança adicional, especifique uma política de host no gerenciador autocert.
- Faça cache de certificados para evitar atingir os [limites de taxa da Let's Encrypt](https://letsencrypt.org/docs/rate-limits).
- Para redirecionar tráfego HTTP para HTTPS, use o [middleware de redirect](/pt-br/middleware/redirect/#https-redirect).
:::

## Servidor

```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)
}
}
```

## Usando um servidor HTTP customizado

Se você precisar de controle total sobre o `http.Server`, conecte o gerenciador autocert a um
`tls.Config` customizado:

```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)
}
}
```
120 changes: 120 additions & 0 deletions site/src/content/docs/pt-br/cookbook/cors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
title: CORS
description: Habilite Cross-Origin Resource Sharing com uma allow list ou função de origem customizada.
sidebar:
order: 4
---

O [middleware CORS](/pt-br/middleware/cors/) controla quais origens podem acessar sua API.
Você pode passar uma lista fixa de origens permitidas ou fornecer uma função que decide
por request.

## Allow list de origens

Passe as origens permitidas diretamente para `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)
}
}
```

## Função de origem customizada

Para políticas dinâmicas, use `CORSWithConfig` com `UnsafeAllowOriginFunc`. A
função recebe o contexto do request e a origem, e retorna a origem a ser ecoada de volta,
se o request é permitido, e um erro opcional.

```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