diff --git a/ctx.go b/ctx.go
index 3c72be3..7ad8566 100644
--- a/ctx.go
+++ b/ctx.go
@@ -9,17 +9,16 @@ import (
"net"
"net/http"
"strings"
+ "sync"
)
type Ctx struct {
- writermem responseWriter
- // origin objects
- writer http.ResponseWriter
- Request *http.Request
- // request info
- path string
- method string
- // response info
+ lock sync.Mutex
+ writermem responseWriter
+ writer http.ResponseWriter
+ Request *http.Request
+ path string
+ method string
StatusCode int
app *App
@@ -29,7 +28,6 @@ type Ctx struct {
locals map[string]interface{}
skippedNodes *[]skippedNode
fullPath string
- //Params Params
}
func newContext(app *App, writer http.ResponseWriter, request *http.Request) *Ctx {
@@ -38,8 +36,8 @@ func newContext(app *App, writer http.ResponseWriter, request *http.Request) *Ct
v := make(Params, 0, app.maxParams)
ctx := &Ctx{
+ lock: sync.Mutex{},
writer: writer,
- writermem: responseWriter{},
Request: request,
path: request.URL.Path,
method: request.Method,
@@ -148,6 +146,9 @@ func (c *Ctx) Param(key string) string {
}
func (c *Ctx) SetParam(key, value string) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
params := append(*c.params, Param{Key: key, Value: value})
c.params = ¶ms
}
@@ -241,11 +242,6 @@ func (c *Ctx) BodyParser(out interface{}) error {
}
func (c *Ctx) QueryParser(out interface{}) error {
- //v := reflect.ValueOf(out)
- //
- //if v.Kind() == reflect.Ptr && v.Elem().Kind() != reflect.Map {
- //}
-
return parseToStruct("query", out, c.Request.URL.Query())
}
@@ -254,8 +250,12 @@ func (c *Ctx) QueryParser(out interface{}) error {
=============================================================== */
func (c *Ctx) Status(code int) *Ctx {
- c.writermem.WriteHeader(code)
- c.StatusCode = c.writermem.status
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ c.StatusCode = code
+ c.writermem.status = code
+
return c
}
@@ -268,7 +268,8 @@ func (c *Ctx) SetHeader(key string, value string) {
}
func (c *Ctx) SendStatus(code int) error {
- c.writermem.WriteHeader(code)
+ c.Status(code)
+ c.writermem.WriteHeaderNow()
return nil
}
@@ -299,12 +300,12 @@ func (c *Ctx) RawWriter() http.ResponseWriter {
return c.writer
}
-func (c *Ctx) Write(data []byte) (int, error) {
- return c.writermem.Write(data)
-}
-
func (c *Ctx) HTML(html string) error {
c.SetHeader("Content-Type", "text/html")
_, err := c.writer.Write([]byte(html))
return err
}
+
+func (c *Ctx) Write(data []byte) (int, error) {
+ return c.writermem.Write(data)
+}
diff --git a/resp.go b/resp.go
deleted file mode 100644
index bb6d6b6..0000000
--- a/resp.go
+++ /dev/null
@@ -1 +0,0 @@
-package nf
diff --git a/xtest/basic/basic.http b/xtest/basic/basic.http
deleted file mode 100644
index f0497fd..0000000
--- a/xtest/basic/basic.http
+++ /dev/null
@@ -1,14 +0,0 @@
-### basic - get
-GET http://127.0.0.1/hello/nf
-
-
-### test resp error
-GET http://127.0.0.1/error
-
-### test basic post
-POST http://127.0.0.1/data
-Content-Type: application/json
-
-{
- "name": "nice"
-}
\ No newline at end of file
diff --git a/xtest/basic/main.go b/xtest/basic/main.go
deleted file mode 100644
index 2e7c2b3..0000000
--- a/xtest/basic/main.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New(nf.Config{})
-
- app.Get("/ok", func(c *nf.Ctx) error {
- return c.SendStatus(200)
- })
-
- api := app.Group("/api")
- api.Use(func(c *nf.Ctx) error {
- c.SetParam("age", "18")
- return c.Next()
- })
-
- api.Get("/:name", func(c *nf.Ctx) error {
- name := c.Param("name")
- age := c.Param("age")
- return c.SendString(name + "@" + age)
- })
-
- log.Fatal(app.Run(":80"))
-}
diff --git a/xtest/bodyLimit/body_limit.http b/xtest/bodyLimit/body_limit.http
deleted file mode 100644
index cbc7673..0000000
--- a/xtest/bodyLimit/body_limit.http
+++ /dev/null
@@ -1,9 +0,0 @@
-### body_limit
-POST http://127.0.0.1/data
-Content-Type: application/json
-
-{
- "name": "zyp",
- "age": 19,
- "likes": ["2233"]
-}
\ No newline at end of file
diff --git a/xtest/bodyLimit/main.go b/xtest/bodyLimit/main.go
deleted file mode 100644
index de83139..0000000
--- a/xtest/bodyLimit/main.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New(nf.Config{BodyLimit: 30})
-
- app.Post("/data", func(c *nf.Ctx) error {
- type Req struct {
- Name string `json:"name"`
- Age int `json:"age"`
- Likes []string `json:"likes"`
- }
-
- var (
- err error
- req = new(Req)
- )
-
- if err = c.BodyParser(req); err != nil {
- return c.JSON(nf.Map{"status": 400, "err": err.Error()})
- }
-
- return c.JSON(nf.Map{"status": 200, "data": req})
- })
-
- app.Post("/url", func(c *nf.Ctx) error {
- type Req struct {
- Name string `form:"name"`
- Age int `form:"age"`
- Likes []string `form:"likes"`
- }
-
- var (
- err error
- req = new(Req)
- )
-
- if err = c.BodyParser(req); err != nil {
- return c.JSON(nf.Map{"status": 400, "err": err.Error()})
- }
-
- return c.JSON(nf.Map{"status": 200, "data": req})
- })
-
- log.Fatal(app.Run("0.0.0.0:80"))
-}
diff --git a/xtest/midd/main.go b/xtest/midd/main.go
deleted file mode 100644
index 8d4f5aa..0000000
--- a/xtest/midd/main.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New(nf.Config{DisableLogger: false})
-
- app.Get("/hello", func(c *nf.Ctx) error {
- return c.SendString("world")
- })
-
- app.Use(ml())
-
- log.Fatal(app.Run(":80"))
-}
-
-func ml() nf.HandlerFunc {
- return func(c *nf.Ctx) error {
- index := []byte(`
my not found
`)
- c.Set("Content-Type", "text/html")
- c.Status(403)
- _, err := c.Write(index)
- return err
- }
-}
diff --git a/xtest/midd2/main.go b/xtest/midd2/main.go
deleted file mode 100644
index b744d0c..0000000
--- a/xtest/midd2/main.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package main
-
-import (
- "errors"
- "github.com/loveuer/nf"
- "github.com/loveuer/nf/nft/resp"
- "log"
-)
-
-func main() {
- app := nf.New()
-
- api := app.Group("/api")
-
- api.Get("/hello",
- auth(),
- func(c *nf.Ctx) error {
- return resp.Resp403(c, errors.New("in hello"))
- },
- )
-
- log.Fatal(app.Run(":80"))
-}
-
-func auth() nf.HandlerFunc {
- return func(c *nf.Ctx) error {
- token := c.Query("token")
- if token != "zyp" {
- return resp.Resp401(c, errors.New("no auth"))
- }
-
- return c.Next()
- }
-}
diff --git a/xtest/multihandler/main.go b/xtest/multihandler/main.go
deleted file mode 100644
index 14b70f3..0000000
--- a/xtest/multihandler/main.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New()
-
- app.Get("/nice", h1, h2)
-
- log.Fatal(app.Run(":80"))
-}
-
-func h1(c *nf.Ctx) error {
- you := c.Query("to")
- if you == "you" {
- return c.JSON(nf.Map{"status": 201, "msg": "nice to meet you"})
- }
-
- //return c.Next()
- return nil
-}
-
-func h2(c *nf.Ctx) error {
- return c.JSON(nf.Map{"status": 200, "msg": "hello world"})
-}
diff --git a/xtest/multihandler/req.http b/xtest/multihandler/req.http
deleted file mode 100644
index 6f515b6..0000000
--- a/xtest/multihandler/req.http
+++ /dev/null
@@ -1,5 +0,0 @@
-### test multi handlers no next
-GET http://127.0.0.1:3333/nice?to=you
-
-### test multi handlers do next
-GET http://127.0.0.1:3333/nice?to=nf
diff --git a/xtest/multipart_form/main.go b/xtest/multipart_form/main.go
deleted file mode 100644
index 50f2865..0000000
--- a/xtest/multipart_form/main.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "github.com/loveuer/nf/nft/resp"
- "log"
-)
-
-func main() {
- app := nf.New(nf.Config{BodyLimit: 10 * 1024 * 1024})
-
- app.Post("/upload", func(c *nf.Ctx) error {
- fs, err := c.MultipartForm()
- if err != nil {
- return resp.Resp400(c, err.Error())
- }
-
- fm := make(map[string][]string)
- for key := range fs.File {
- if _, exist := fm[key]; !exist {
- fm[key] = make([]string, 0)
- }
-
- for f := range fs.File[key] {
- fm[key] = append(fm[key], fs.File[key][f].Filename)
- }
- }
-
- return resp.Resp200(c, nf.Map{"value": fs.Value, "files": fm})
- })
-
- log.Fatal(app.Run(":13322"))
-}
diff --git a/xtest/panic/main.go b/xtest/panic/main.go
deleted file mode 100644
index cc45b63..0000000
--- a/xtest/panic/main.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New(nf.Config{
- DisableRecover: false,
- })
-
- app.Get("/hello/:name", func(c *nf.Ctx) error {
- name := c.Param("name")
-
- if name == "nf" {
- panic("name is nf")
- }
-
- return c.JSON("nice")
- })
-
- log.Fatal(app.Run("0.0.0.0:80"))
-}
diff --git a/xtest/panic/panic.http b/xtest/panic/panic.http
deleted file mode 100644
index 8092822..0000000
--- a/xtest/panic/panic.http
+++ /dev/null
@@ -1,5 +0,0 @@
-### panic test
-GET http://127.0.0.1/hello/nf
-
-### if covered?
-GET http://127.0.0.1/hello/world
\ No newline at end of file
diff --git a/xtest/queryParser/main.go b/xtest/queryParser/main.go
deleted file mode 100644
index 1c61f2d..0000000
--- a/xtest/queryParser/main.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package main
-
-import (
- "github.com/loveuer/nf"
- "log"
-)
-
-func main() {
- app := nf.New()
-
- app.Get("/hello", func(c *nf.Ctx) error {
- type Req struct {
- Name string `query:"name"`
- Age int `query:"age"`
- Likes []string `query:"likes"`
- }
-
- var (
- err error
- req = new(Req)
- rm = make(map[string]interface{})
- )
-
- //if err = c.QueryParser(req); err != nil {
- // return nf.NewNFError(400, "1:"+err.Error())
- //}
-
- if err = c.QueryParser(&rm); err != nil {
- return nf.NewNFError(400, "2:"+err.Error())
- }
-
- return c.JSON(nf.Map{"status": 200, "data": req, "map": rm})
- })
-
- log.Fatal(app.Run("0.0.0.0:80"))
-}
diff --git a/xtest/quit/main.go b/xtest/quit/main.go
deleted file mode 100644
index 72e6943..0000000
--- a/xtest/quit/main.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package main
-
-import (
- "context"
- "github.com/loveuer/nf"
- "log"
- "time"
-)
-
-var (
- app = nf.New()
- quit = make(chan bool)
-)
-
-func main() {
-
- app.Get("/name", handleGet)
-
- go func() {
- err := app.Run(":80")
- log.Print("run with err=", err)
- quit <- true
- }()
-
- <-quit
-}
-
-func handleGet(c *nf.Ctx) error {
- type Req struct {
- Name string `query:"name"`
- Addr []string `query:"addr"`
- }
-
- var (
- err error
- req = Req{}
- )
-
- if err = c.QueryParser(&req); err != nil {
- return nf.NewNFError(400, err.Error())
- }
-
- if req.Name == "quit" {
-
- go func() {
- time.Sleep(2 * time.Second)
- log.Print("app quit = ", app.Shutdown(context.TODO()))
- }()
- }
-
- return c.JSON(nf.Map{"req_map": req})
-}
diff --git a/xtest/tls/main.go b/xtest/tls/main.go
deleted file mode 100644
index 5bf85b8..0000000
--- a/xtest/tls/main.go
+++ /dev/null
@@ -1,119 +0,0 @@
-package main
-
-import (
- "bytes"
- "crypto/rand"
- "crypto/rsa"
- "crypto/tls"
- "crypto/x509"
- "crypto/x509/pkix"
- "encoding/pem"
- "github.com/loveuer/nf"
- "log"
- "math/big"
- "net"
- "time"
-)
-
-func main() {
- app := nf.New(nf.Config{
- DisableHttpErrorLog: true,
- })
-
- app.Get("/hello/:name", func(c *nf.Ctx) error {
- return c.SendString("hello, " + c.Param("name"))
- })
-
- st, _, _ := GenerateTlsConfig()
- log.Fatal(app.RunTLS(":443", st))
-}
-
-func GenerateTlsConfig() (serverTLSConf *tls.Config, clientTLSConf *tls.Config, err error) {
- ca := &x509.Certificate{
- SerialNumber: big.NewInt(2019),
- Subject: pkix.Name{
- Organization: []string{"Company, INC."},
- Country: []string{"US"},
- Province: []string{""},
- Locality: []string{"San Francisco"},
- StreetAddress: []string{"Golden Gate Bridge"},
- PostalCode: []string{"94016"},
- },
- NotBefore: time.Now(),
- NotAfter: time.Now().AddDate(99, 0, 0),
- IsCA: true,
- ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
- KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
- BasicConstraintsValid: true,
- }
- // create our private and public key
- caPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
- if err != nil {
- return nil, nil, err
- }
- // create the CA
- caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
- if err != nil {
- return nil, nil, err
- }
- // pem encode
- caPEM := new(bytes.Buffer)
- pem.Encode(caPEM, &pem.Block{
- Type: "CERTIFICATE",
- Bytes: caBytes,
- })
- caPrivKeyPEM := new(bytes.Buffer)
- pem.Encode(caPrivKeyPEM, &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey),
- })
- // set up our server certificate
- cert := &x509.Certificate{
- SerialNumber: big.NewInt(2019),
- Subject: pkix.Name{
- Organization: []string{"Company, INC."},
- Country: []string{"US"},
- Province: []string{""},
- Locality: []string{"San Francisco"},
- StreetAddress: []string{"Golden Gate Bridge"},
- PostalCode: []string{"94016"},
- },
- IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1), net.IPv6loopback},
- NotBefore: time.Now(),
- NotAfter: time.Now().AddDate(1, 0, 0),
- SubjectKeyId: []byte{1, 2, 3, 4, 6},
- ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
- KeyUsage: x509.KeyUsageDigitalSignature,
- }
- certPrivKey, err := rsa.GenerateKey(rand.Reader, 4096)
- if err != nil {
- return nil, nil, err
- }
- certBytes, err := x509.CreateCertificate(rand.Reader, cert, ca, &certPrivKey.PublicKey, caPrivKey)
- if err != nil {
- return nil, nil, err
- }
- certPEM := new(bytes.Buffer)
- pem.Encode(certPEM, &pem.Block{
- Type: "CERTIFICATE",
- Bytes: certBytes,
- })
- certPrivKeyPEM := new(bytes.Buffer)
- pem.Encode(certPrivKeyPEM, &pem.Block{
- Type: "RSA PRIVATE KEY",
- Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
- })
- serverCert, err := tls.X509KeyPair(certPEM.Bytes(), certPrivKeyPEM.Bytes())
- if err != nil {
- return nil, nil, err
- }
- serverTLSConf = &tls.Config{
- Certificates: []tls.Certificate{serverCert},
- }
- certpool := x509.NewCertPool()
- certpool.AppendCertsFromPEM(caPEM.Bytes())
- clientTLSConf = &tls.Config{
- RootCAs: certpool,
- }
- return
-}