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

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ package pulse
import (
"fmt"
"github.com/common-nighthawk/go-figure"
"github.com/valyala/fasthttp"
"net"
"net/http"
)

type (
Pulse struct {
config *Config
server *fasthttp.Server
server *http.Server
Router *Router
}

Expand All @@ -34,7 +34,7 @@ const (
func New(config ...Config) *Pulse {
app := &Pulse{
config: &Config{},
server: &fasthttp.Server{},
server: &http.Server{},
}

if len(config) > 0 {
Expand Down Expand Up @@ -73,7 +73,7 @@ func (f *Pulse) Run(address string) {
}

func (f *Pulse) Stop() {
err := f.server.Shutdown()
err := f.server.Shutdown(nil)
if err != nil {
return
}
Expand Down
142 changes: 62 additions & 80 deletions context.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
package pulse

import (
"bytes"
"github.com/gopulse/pulse/utils"
"github.com/valyala/fasthttp"
"encoding/json"
"net/http"
"strings"
"time"
)

type handlerFunc func(ctx *Context) error

type Context struct {
RequestCtx *fasthttp.RequestCtx
Params map[string]string
paramValues []string
handlers []handlerFunc
handlerIdx int
Cookies *fasthttp.Cookie
ResponseWriter http.ResponseWriter
Request *http.Request
Params map[string]string
paramValues []string
handlers []handlerFunc
handlerIdx int
Cookies []*http.Cookie
}

func (c *Context) Write(p []byte) (n int, err error) {
return c.ResponseWriter.Write(p)
}

type Cookie struct {
Name string `json:"name"`
Value string `json:"value"`
Path string `json:"path"`
Domain string `json:"domain"`
MaxAge int `json:"max_age"`
Expires time.Time `json:"expires"`
Secure bool `json:"secure"`
HTTPOnly bool `json:"http_only"`
SameSite string `json:"same_site"`
SessionOnly bool `json:"session_only"`
Name string
Value string
Path string
Domain string
MaxAge int
Expires time.Time
Secure bool
HTTPOnly bool
SameSite http.SameSite
}

// NewContext returns a new Context.
func NewContext(ctx *fasthttp.RequestCtx, params map[string]string) *Context {
func NewContext(w http.ResponseWriter, req *http.Request) *Context {
return &Context{
RequestCtx: ctx,
Params: params,
paramValues: make([]string, 0, 10),
handlers: nil,
handlerIdx: -1,
ResponseWriter: w,
Request: req,
Params: make(map[string]string),
paramValues: make([]string, 0, 10),
handlers: nil,
handlerIdx: -1,
}
}

// Context returns the fasthttp.RequestCtx
func (c *Context) Context() *fasthttp.RequestCtx {
return c.RequestCtx
}

// WithParams sets the params for the context.
func (c *Context) WithParams(params map[string]string) *Context {
c.Params = params
Expand All @@ -61,17 +60,14 @@ func (c *Context) Param(key string) string {

// Query returns the query value for the given key.
func (c *Context) Query(key string) string {
return string(c.RequestCtx.QueryArgs().Peek(key))
return c.Request.URL.Query().Get(key)
}

// String sets the response body to the given string.
func (c *Context) String(value string) {
if c.RequestCtx.Response.Body() == nil {
c.RequestCtx.Response.SetBodyString(value)
} else {
buf := bytes.NewBuffer(c.RequestCtx.Response.Body())
buf.WriteString(value)
c.RequestCtx.Response.SetBody(buf.Bytes())
_, err := c.ResponseWriter.Write([]byte(value))
if err != nil {
return
}
}

Expand All @@ -82,7 +78,7 @@ func (c *Context) SetData(key string, value interface{}) {

// GetData returns the http header value for the given key.
func (c *Context) GetData(key string) string {
return string(c.RequestCtx.Response.Header.Peek(key))
return string(c.Request.Header.Get(key))
}

// Next calls the next handler in the chain.
Expand All @@ -106,42 +102,26 @@ func (c *Context) Abort() {

// SetCookie sets a cookie with the given name, value, and options.
func (c *Context) SetCookie(cookie *Cookie) {
acCookie := fasthttp.AcquireCookie()

acCookie.SetKey(cookie.Name)
acCookie.SetValue(cookie.Value)
acCookie.SetPath(cookie.Path)
acCookie.SetDomain(cookie.Domain)
acCookie.SetSecure(cookie.Secure)
acCookie.SetHTTPOnly(cookie.HTTPOnly)
acCookie.SetSecure(cookie.Secure)
if !cookie.SessionOnly {
acCookie.SetMaxAge(cookie.MaxAge)
acCookie.SetExpire(cookie.Expires)
}

switch strings.ToLower(cookie.SameSite) {
case string(rune(fasthttp.CookieSameSiteStrictMode)):
acCookie.SetSameSite(fasthttp.CookieSameSiteStrictMode)
case string(rune(fasthttp.CookieSameSiteNoneMode)):
acCookie.SetSameSite(fasthttp.CookieSameSiteNoneMode)
case string(rune(fasthttp.CookieSameSiteDisabled)):
acCookie.SetSameSite(fasthttp.CookieSameSiteDisabled)
default:
acCookie.SetSameSite(fasthttp.CookieSameSiteDefaultMode)
}

c.RequestCtx.Response.Header.SetCookie(acCookie)
fasthttp.ReleaseCookie(acCookie)
http.SetCookie(c.ResponseWriter, &http.Cookie{
Name: cookie.Name,
Value: cookie.Value,
Path: cookie.Path,
Domain: cookie.Domain,
Expires: cookie.Expires,
MaxAge: cookie.MaxAge,
Secure: cookie.Secure,
HttpOnly: cookie.HTTPOnly,
SameSite: cookie.SameSite,
})
}

// GetCookie returns the value of the cookie with the given name.
func (c *Context) GetCookie(name string) string {
cookie := c.RequestCtx.Request.Header.Cookie(name)
if cookie == nil {
cookie, err := c.Request.Cookie(name)
if err != nil {
return ""
}
return string(cookie)
return cookie.Value
}

// ClearCookie deletes the cookie with the given name.
Expand All @@ -158,27 +138,27 @@ func (c *Context) ClearCookie(name string) {

// SetResponseHeader sets the http header value to the given key.
func (c *Context) SetResponseHeader(key, value string) {
c.RequestCtx.Response.Header.Set(key, value)
c.ResponseWriter.Header().Set(key, value)
}

// GetResponseHeader returns the http header value for the given key.
func (c *Context) GetResponseHeader(key string) string {
return string(c.RequestCtx.Request.Header.Peek(key))
return c.ResponseWriter.Header().Get(key)
}

// SetRequestHeader SetResponseHeader sets the http header value to the given key.
func (c *Context) SetRequestHeader(key, value string) {
c.RequestCtx.Request.Header.Set(key, value)
c.Request.Header.Set(key, value)
}

// GetRequestHeader GetResponseHeader returns the http header value for the given key.
func (c *Context) GetRequestHeader(key string) string {
return string(c.RequestCtx.Request.Header.Peek(key))
return c.Request.Header.Get(key)
}

// SetContentType sets the Content-Type header in the response to the given value.
func (c *Context) SetContentType(value string) {
c.RequestCtx.Response.Header.SetContentType(value)
c.ResponseWriter.Header().Set("Content-Type", value)
}

// Accepts checks if the specified content types are acceptable.
Expand All @@ -204,22 +184,24 @@ func (c *Context) Accepts(types ...string) string {

// Status sets the response status code.
func (c *Context) Status(code int) {
c.RequestCtx.Response.SetStatusCode(code)
c.ResponseWriter.WriteHeader(code)
}

// JSON sets the response body to the given JSON representation.
func (c *Context) JSON(code int, obj interface{}) ([]byte, error) {
c.RequestCtx.Response.Header.SetContentType("application/json")
c.RequestCtx.Response.SetStatusCode(code)
jsonBody, err := utils.ToJSON(obj)
c.ResponseWriter.Header().Set("Content-Type", "application/json")
c.Status(code)
jsonBody, err := json.Marshal(obj)
if err != nil {
return nil, err
}
c.RequestCtx.Response.SetBodyString(jsonBody)
if _, err := c.ResponseWriter.Write(jsonBody); err != nil {
return nil, err
}

return []byte(jsonBody), nil
return jsonBody, nil
}

func (c *Context) BodyParser(v interface{}) error {
return utils.FromJSON(c.RequestCtx.Request.Body(), v)
return json.NewDecoder(c.Request.Body).Decode(v)
}
20 changes: 10 additions & 10 deletions context_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package pulse

import (
"net/http"
"testing"
"time"
)
Expand Down Expand Up @@ -56,16 +57,15 @@ func TestContext_SetCookie(t *testing.T) {

router.Get("/", func(ctx *Context) error {
cookie := Cookie{
Name: "Test Cookie 1",
Value: "Test Cookie 1",
Path: "/",
Domain: "localhost",
MaxAge: 0,
Expires: time.Now().Add(24 * time.Hour),
Secure: false,
HTTPOnly: false,
SameSite: "Lax",
SessionOnly: false,
Name: "Test Cookie 1",
Value: "Test Cookie 1",
Path: "/",
Domain: "localhost",
MaxAge: 0,
Expires: time.Now().Add(24 * time.Hour),
Secure: false,
HTTPOnly: false,
SameSite: http.SameSiteLaxMode,
}
ctx.SetCookie(&cookie)
return nil
Expand Down
4 changes: 0 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ module github.com/gopulse/pulse

go 1.19

require github.com/valyala/fasthttp v1.45.0

require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
)
Loading