Skip to content

Commit

Permalink
Merge pull request #243 from cloudwego/release/v0.3.1
Browse files Browse the repository at this point in the history
chore: release v0.3.1
  • Loading branch information
Duslia authored Sep 14, 2022
2 parents a83e52c + 65ee336 commit 0bbfc48
Show file tree
Hide file tree
Showing 23 changed files with 510 additions and 97 deletions.
25 changes: 18 additions & 7 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#### What type of PR is this?

<!--
Add one of the following kinds:
Expand All @@ -11,21 +10,33 @@ optimize: A new optimization
fix: A bug fix
perf: A code change that improves performance
refactor: A code change that neither fixes a bug nor adds a feature
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
style: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc)
test: Adding missing tests or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
-->

#### What this PR does / why we need it (English/Chinese):
#### Check the PR title.
<!--
The description of the title will be attached in Release Notes,
so please describe it from user-oriented, what this PR does / why we need it.
Please check your PR title with the below requirements:
-->
- [ ] This PR title match the format: \<type\>(optional scope): \<description\>
- [ ] The description of this PR title is user-oriented and clear enough for others to understand.


#### (Optional) Translate the PR title into Chinese.


#### (Optional) More detail description for this PR(en: English/zh: Chinese).
<!--
The description will be attached in Release Notes,
so please describe it from user-oriented.
Provide more detailed info for review. If it is a perf type PR, perf data is suggested to give.
-->
en:
zh(optional):

#### Which issue(s) this PR fixes:

<!--
*Automatically closes linked issue when PR is merged.
Automatically closes linked issue when PR is merged.
Eg: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->
5 changes: 5 additions & 0 deletions examples/html_rendering/index.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<h1>
{[{ .title }]}
</h1>
</html>
60 changes: 60 additions & 0 deletions examples/html_rendering/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2022 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package main

import (
"context"
"fmt"
"html/template"
"time"

"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)

func formatAsDate(t time.Time) string {
year, month, day := t.Date()
return fmt.Sprintf("%d/%02d/%02d", year, month, day)
}

func main() {
// set interval to 0 means using fs-watching mechanism.
h := server.Default(server.WithAutoReloadRender(true, 0))

h.Delims("{[{", "}]}")

h.SetFuncMap(template.FuncMap{
"formatAsDate": formatAsDate,
})
h.LoadHTMLGlob("./examples/html_rendering/*")

h.GET("/index", func(c context.Context, ctx *app.RequestContext) {
ctx.HTML(consts.StatusOK, "index.tmpl", utils.H{
"title": "Main website",
})
})

h.GET("/raw", func(c context.Context, ctx *app.RequestContext) {
ctx.HTML(consts.StatusOK, "template.html", utils.H{
"now": time.Date(2017, 0o7, 0o1, 0, 0, 0, 0, time.UTC),
})
})

h.Spin()
}
1 change: 1 addition & 0 deletions examples/html_rendering/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Date: {[{.now | formatAsDate}]}</h1>
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ go 1.16
require (
github.com/bytedance/go-tagexpr/v2 v2.9.2
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7
github.com/bytedance/sonic v1.3.0
github.com/cloudwego/netpoll v0.2.4
github.com/bytedance/sonic v1.3.5
github.com/cloudwego/netpoll v0.2.6
github.com/fsnotify/fsnotify v1.5.4
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad
google.golang.org/protobuf v1.27.1
)
13 changes: 8 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ github.com/bytedance/go-tagexpr/v2 v2.9.2 h1:QySJaAIQgOEDQBLS3x9BxOWrnhqu5sQ+f6H
github.com/bytedance/go-tagexpr/v2 v2.9.2/go.mod h1:5qsx05dYOiUXOUgnQ7w3Oz8BYs2qtM/bJokdLb79wRM=
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7 h1:PtwsQyQJGxf8iaPptPNaduEIu9BnrNms+pcRdHAxZaM=
github.com/bytedance/gopkg v0.0.0-20220413063733-65bf48ffb3a7/go.mod h1:2ZlV9BaUH4+NXIBF0aMdKKAnHTzqH+iMU4KUjAbL23Q=
github.com/bytedance/sonic v1.3.0 h1:T2rlvNytw6bTmczlAXvGqmuMzIqGJBOsJKYwRPWR7Y8=
github.com/bytedance/sonic v1.3.0/go.mod h1:V973WhNhGmvHxW6nQmsHEfHaoU9F3zTF+93rH03hcUQ=
github.com/bytedance/sonic v1.3.5 h1:xfBNhsG3QCC+AMCmCHxNQg0StI5IM/B9Jtwjqi5WlI0=
github.com/bytedance/sonic v1.3.5/go.mod h1:V973WhNhGmvHxW6nQmsHEfHaoU9F3zTF+93rH03hcUQ=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06 h1:1sDoSuDPWzhkdzNVxCxtIaKiAe96ESVPv8coGwc1gZ4=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/cloudwego/netpoll v0.2.4 h1:Kbo2HA1cXEgoy/bu1jSNrjcqZj2diENcJqLy6vKiROU=
github.com/cloudwego/netpoll v0.2.4/go.mod h1:1T2WVuQ+MQw6h6DpE45MohSvDTKdy2DlzCx2KsnPI4E=
github.com/cloudwego/netpoll v0.2.6 h1:vzN8cyayoa9RdCOG87tqkYO/j2hA4SMLC+vkcNUq6uI=
github.com/cloudwego/netpoll v0.2.6/go.mod h1:1T2WVuQ+MQw6h6DpE45MohSvDTKdy2DlzCx2KsnPI4E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/goccy/go-json v0.9.4 h1:L8MLKG2mvVXiQu07qB6hmfqeSYQdOnqPot2GhsIwIaI=
github.com/goccy/go-json v0.9.4/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand Down Expand Up @@ -58,8 +60,9 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VA
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe h1:W8vbETX/n8S6EmY0Pu4Ix7VvpsJUESTwl0oCK8MJOgk=
golang.org/x/sys v0.0.0-20220110181412-a018aaa089fe/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
Expand Down
1 change: 1 addition & 0 deletions internal/bytestr/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var (
)

var (
StrBackSlash = []byte("\\")
StrSlash = []byte("/")
StrSlashSlash = []byte("//")
StrSlashDotDot = []byte("/..")
Expand Down
16 changes: 8 additions & 8 deletions pkg/app/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ func TestClientReadTimeout(t *testing.T) {
ReadTimeout: time.Second * 4,
MaxIdempotentCallAttempts: 1,
Dialer: standard.NewDialer(),
Addr: opt.Addr,
},
Addr: opt.Addr,
}

req := protocol.AcquireRequest()
Expand Down Expand Up @@ -689,9 +689,9 @@ func TestHostClientPendingRequests(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foobar",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, time.Second, nil),
},
Addr: "foobar",
}

pendingRequests := c.PendingRequests()
Expand Down Expand Up @@ -780,10 +780,10 @@ func TestHostClientMaxConnsWithDeadline(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foobar",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, time.Second, nil),
MaxConns: 1,
},
Addr: "foobar",
}

for i := 0; i < 5; i++ {
Expand Down Expand Up @@ -849,10 +849,10 @@ func TestHostClientMaxConnDuration(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foobar",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, time.Second, nil),
MaxConnDuration: 10 * time.Millisecond,
},
Addr: "foobar",
}

for i := 0; i < 5; i++ {
Expand Down Expand Up @@ -895,11 +895,11 @@ func TestHostClientMultipleAddrs(t *testing.T) {
dialsCount := make(map[string]int)
c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foo,bar,baz",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, 1*time.Second, func(network, addr string, timeout time.Duration, tlsConfig *tls.Config) {
dialsCount[addr]++
}),
},
Addr: "foo,bar,baz",
}

for i := 0; i < 9; i++ {
Expand Down Expand Up @@ -961,9 +961,9 @@ func TestClientFollowRedirects(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "xxx",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, 1*time.Second, nil),
},
Addr: "xxx",
}

for i := 0; i < 10; i++ {
Expand Down Expand Up @@ -1055,11 +1055,11 @@ func TestHostClientMaxConnWaitTimeoutSuccess(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foobar",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, time.Second, nil),
MaxConns: 1,
MaxConnWaitTimeout: 200 * time.Millisecond,
},
Addr: "foobar",
}

for i := 0; i < 5; i++ {
Expand Down Expand Up @@ -1124,11 +1124,11 @@ func TestHostClientMaxConnWaitTimeoutError(t *testing.T) {

c := &http1.HostClient{
ClientOptions: &http1.ClientOptions{
Addr: "foobar",
Dialer: newMockDialerWithCustomFunc(opt.Network, opt.Addr, time.Second, nil),
MaxConns: 1,
MaxConnWaitTimeout: 10 * time.Millisecond,
},
Addr: "foobar",
}

var errNoFreeConnsCount uint32
Expand Down
35 changes: 35 additions & 0 deletions pkg/app/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import (
"io"
"mime/multipart"
"net"
"net/url"
"os"
"reflect"
"strings"
Expand Down Expand Up @@ -950,6 +951,40 @@ func (ctx *RequestContext) Cookie(key string) []byte {
return ctx.Request.Header.Cookie(key)
}

// SetCookie adds a Set-Cookie header to the Response's headers.
// Parameter introduce:
// name and value is used to set cookie's name and value, eg. Set-Cookie: name=value
// maxAge is use to set cookie's expiry date, eg. Set-Cookie: name=value; max-age=1
// path and domain is used to set the scope of a cookie, eg. Set-Cookie: name=value;domain=localhost; path=/;
// secure and httpOnly is used to sent cookies securely; eg. Set-Cookie: name=value;HttpOnly; secure;
// sameSite let servers specify whether/when cookies are sent with cross-site requests; eg. Set-Cookie: name=value;HttpOnly; secure; SameSite=Lax;
//
// For example:
// 1. ctx.SetCookie("user", "hertz", 1, "/", "localhost",protocol.CookieSameSiteLaxMode, true, true)
// add response header ---> Set-Cookie: user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=Lax;
// 2. ctx.SetCookie("user", "hertz", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
// add response header ---> Set-Cookie: user=hertz; max-age=10; domain=localhost; path=/; SameSite=Lax;
// 3. ctx.SetCookie("", "hertz", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
// add response header ---> Set-Cookie: hertz; max-age=10; domain=localhost; path=/; SameSite=Lax;
// 4. ctx.SetCookie("user", "", 10, "/", "localhost",protocol.CookieSameSiteLaxMode, false, false)
// add response header ---> Set-Cookie: user=; max-age=10; domain=localhost; path=/; SameSite=Lax;
func (ctx *RequestContext) SetCookie(name, value string, maxAge int, path, domain string, sameSite protocol.CookieSameSite, secure, httpOnly bool) {
if path == "" {
path = "/"
}
cookie := protocol.AcquireCookie()
defer protocol.ReleaseCookie(cookie)
cookie.SetKey(name)
cookie.SetValue(url.QueryEscape(value))
cookie.SetMaxAge(maxAge)
cookie.SetPath(path)
cookie.SetDomain(domain)
cookie.SetSecure(secure)
cookie.SetHTTPOnly(httpOnly)
cookie.SetSameSite(sameSite)
ctx.Response.Header.SetCookie(cookie)
}

// UserAgent returns the value of the request user_agent.
func (ctx *RequestContext) UserAgent() []byte {
return ctx.Request.Header.UserAgent()
Expand Down
12 changes: 12 additions & 0 deletions pkg/app/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -919,3 +919,15 @@ func TestBindAndValidate(t *testing.T) {
t.Fatalf("unexpected nil, expected an error")
}
}

func TestRequestContext_SetCookie(t *testing.T) {
c := NewContext(0)
c.SetCookie("user", "hertz", 1, "/", "localhost", protocol.CookieSameSiteLaxMode, true, true)
assert.DeepEqual(t, "user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure; SameSite=Lax", c.Response.Header.Get("Set-Cookie"))
}

func TestRequestContext_SetCookiePathEmpty(t *testing.T) {
c := NewContext(0)
c.SetCookie("user", "hertz", 1, "", "localhost", protocol.CookieSameSiteDisabled, true, true)
assert.DeepEqual(t, "user=hertz; max-age=1; domain=localhost; path=/; HttpOnly; secure", c.Response.Header.Get("Set-Cookie"))
}
11 changes: 11 additions & 0 deletions pkg/app/server/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,14 @@ func WithRegistry(r registry.Registry, info *registry.Info) config.Option {
o.RegistryInfo = info
}}
}

// WithAutoReloadRender sets the config of auto reload render.
// If auto reload render is enabled:
// 1. interval = 0 means reload render according to file watch mechanism.(recommended)
// 2. interval > 0 means reload render every interval.
func WithAutoReloadRender(b bool, interval time.Duration) config.Option {
return config.Option{F: func(o *config.Options) {
o.AutoReloadRender = b
o.AutoReloadInterval = interval
}}
}
6 changes: 6 additions & 0 deletions pkg/app/server/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func TestOptions(t *testing.T) {
WithALPN(true),
WithTraceLevel(stats.LevelDisabled),
WithRegistry(nil, info),
WithAutoReloadRender(true, 5*time.Second),
})
assert.DeepEqual(t, opt.ReadTimeout, time.Second)
assert.DeepEqual(t, opt.IdleTimeout, time.Second)
Expand All @@ -79,6 +80,8 @@ func TestOptions(t *testing.T) {
assert.DeepEqual(t, opt.TraceLevel, stats.LevelDisabled)
assert.DeepEqual(t, opt.RegistryInfo, info)
assert.DeepEqual(t, opt.Registry, nil)
assert.DeepEqual(t, opt.AutoReloadRender, true)
assert.DeepEqual(t, opt.AutoReloadInterval, 5*time.Second)
}

func TestDefaultOptions(t *testing.T) {
Expand All @@ -103,5 +106,8 @@ func TestDefaultOptions(t *testing.T) {
assert.DeepEqual(t, opt.ReadBufferSize, 4096)
assert.DeepEqual(t, opt.ALPN, false)
assert.DeepEqual(t, opt.Registry, registry.NoopRegistry)
assert.DeepEqual(t, opt.AutoReloadRender, false)
assert.Assert(t, opt.RegistryInfo == nil)
assert.DeepEqual(t, opt.AutoReloadRender, false)
assert.DeepEqual(t, opt.AutoReloadInterval, time.Duration(0))
}
Loading

0 comments on commit 0bbfc48

Please sign in to comment.