Merge pull request #3 from gofiber/master

Commit from Fiber master
pull/75/head
Vic Shóstak 2020-02-07 21:40:04 +03:00 committed by GitHub
commit dce03337f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1648 additions and 391 deletions

View File

@ -1,4 +1,9 @@
language: go
os:
- linux
# - windows
- osx
go:
- 1.13.x
env:

View File

@ -150,4 +150,4 @@ Thanks for your support! 😘 Together, we make `Fiber`.
## License
⚠️ _Please note:_ `gofiber/fiber` is free and open-source software licensed under the [MIT License](https://github.com/gofiber/fiber/edit/master/LICENSE).
⚠️ _Please note:_ `gofiber/fiber` is free and open-source software licensed under the [MIT License](https://github.com/gofiber/fiber/master/LICENSE).

View File

@ -150,4 +150,4 @@ func main() {
## License
⚠️ _请注意:_ `gofiber/fiber` 是根据以下条款获得许可的免费开源软件 [MIT License](https://github.com/gofiber/fiber/edit/master/LICENSE).
⚠️ _请注意:_ `gofiber/fiber` 是根据以下条款获得许可的免费开源软件 [MIT License](https://github.com/gofiber/fiber/master/LICENSE).

181
README_NEW.md Normal file
View File

@ -0,0 +1,181 @@
[![Fiber Logo](https://i.imgur.com/zzmW4eK.png)](https://fiber.wiki)
[Express](https://github.com/expressjs/express) inspired web framework build on [Fasthttp](https://github.com/valyala/fasthttp) for [Go](https://golang.org/doc/).
Designed to ease things up for fast development with zero memory allocation and performance in mind.
[![](https://img.shields.io/github/release/gofiber/fiber)](https://github.com/gofiber/fiber/releases)
[![](https://img.shields.io/badge/godoc-reference-blue.svg?longCache=true&style=flat)](https://pkg.go.dev/github.com/gofiber/fiber?tab=doc)
![](https://img.shields.io/badge/coverage-84%25-brightgreen.svg?longCache=true&style=flat)
![](https://img.shields.io/badge/go-100%25-brightgreen.svg?longCache=true&style=flat)
![](https://img.shields.io/badge/goreport-A+-brightgreen.svg?longCache=true&style=flat)
[![](https://img.shields.io/badge/gitter-chat-brightgreen.svg?longCache=true&style=flat)](https://pkg.go.dev/github.com/gofiber/fiber?tab=doc)
```golang
package main
import "github.com/gofiber/fiber"
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) {
c.Write("Hello, World!")
})
app.Listen(3000)
}
```
## Benchmarks
These tests are performed by [TechEmpower](https://github.com/TechEmpower/FrameworkBenchmarks) and [Go Web](https://github.com/smallnest/go-web-framework-benchmark). If you want to see all results, please visit our [wiki#benchmarks](https://fiber.wiki/#benchmarks).
<p float="left" align="middle">
<img src="https://fiber.wiki/static/benchmarks/benchmark-pipeline.png" width="49%" />
<img src="https://fiber.wiki/static/benchmarks/benchmark_alloc.png" width="49%" />
</p>
## Installation
Before installing, [download and install Go](https://golang.org/dl/).
Go `1.11` or higher is required.
Installation is done using the
[`go get`](https://golang.org/cmd/go/#hdr-Add_dependencies_to_current_module_and_install_them) command:
```bash
go get github.com/gofiber/fiber
```
## Features
* Robust [routing](https://fiber.wiki/#/routing)
* Serve [static files](https://fiber.wiki/#/application?id=static)
* [Extreme performance](https://fiber.wiki/#/benchmarks)
* Low memory footprint
* Express [API endpoints](https://fiber.wiki/#/context)
* Middleware & [Next](https://fiber.wiki/#context?id=next) support
* Rapid server-side programming
* [And much more, click here](https://fiber.wiki/)
## Philosophy
People switching from [Node.js](https://nodejs.org/en/about/) to [Go](https://golang.org/doc/) often end up in a bad learning curve to start building their webapps or micro services. Fiber, as a web framework, was created with the idea of minimalism so new and experienced gophers can rapidly develop web application's.
Fiber is inspired by the Express framework, the most populair web framework on web. We combined the ease of Express and raw performance of Go. If you have ever implemented a web application on Node.js using Express.js, then many methods and principles will seem very common to you.
## Examples
Listed below are some of the common examples. If you want to see more code examples, please visit our [recipes repository](https://github.com/gofiber/recipes) or [api documentation](https://fiber.wiki).
_**Static files**_
```golang
// ...
app := fiber.New()
app.Static("./public")
// http://localhost:3000/js/script.js
// http://localhost:3000/css/style.css
app.Static("/xxx", "./public")
// http://localhost:3000/xxx/js/script.js
// http://localhost:3000/xxx/css/style.css
app.Listen(3000)
```
_**Routing**_
```golang
// ...
app := fiber.New()
// param
app.Get("/:name", func(c *fiber.Ctx) {
c.Send("Hello, " + c.Params("name"))
})
// optional param
app.Get("/:name/:lastname?", func(c *fiber.Ctx) {
c.Send("Hello, " + c.Params("name") + " " + c.Params("lastname"))
})
// wildcard
app.Get("/api*", func(c *fiber.Ctx) {
c.Send("/api" + c.Params("*"))
})
app.Listen(3000)
```
_**Middleware**_
```golang
// ...
app := fiber.New()
// match any post route
app.Post(func(c *fiber.Ctx) {
user, pass, ok := c.BasicAuth()
if !ok || user != "john" || pass != "doe" {
c.Status(403).Send("Sorry John")
return
}
c.Next()
})
// match all routes starting with /api
app.Use("/api", func(c *fiber.Ctx) {
c.Set("Access-Control-Allow-Origin", "*")
c.Set("Access-Control-Allow-Headers", "X-Requested-With")
c.Next()
})
// optional param
app.Post("/api/register", func(c *fiber.Ctx) {
username := c.Body("username")
password := c.Body("password")
// ..
})
app.Listen(3000)
```
_**404 Handling**_
```golang
// ...
app := fiber.New()
// ..application routes
// last route
app.Use(func (c *fiber.Ctx) {
c.SendStatus(404)
})
app.Listen(3000)
```
_**JSON Response**_
```golang
// ...
app := fiber.New()
type Data struct {
Name string `json:"name"`
Age int `json:"age"`
}
// last route
app.Get("/json", func (c *fiber.Ctx) {
c.JSON(&Data{
Name: "John",
Age: 20,
})
})
app.Listen(3000)
```
## License
`gofiber/fiber` is free and open-source software licensed under the [MIT License](https://github.com/gofiber/fiber/master/LICENSE).

View File

@ -10,6 +10,8 @@ package fiber
import (
"flag"
"time"
"github.com/valyala/fasthttp"
)
const (
@ -33,7 +35,8 @@ var (
// Fiber structure
type Fiber struct {
// Server name header
Server string
Server string
httpServer *fasthttp.Server
// Show fiber banner
Banner bool
// https://github.com/valyala/fasthttp/blob/master/server.go#L150
@ -72,10 +75,11 @@ type engine struct {
func New() *Fiber {
flag.Parse()
return &Fiber{
Server: "",
Banner: true,
Prefork: *prefork,
child: *child,
Server: "",
httpServer: nil,
Banner: true,
Prefork: *prefork,
child: *child,
Engine: &engine{
Concurrency: 256 * 1024,
DisableKeepAlive: false,

View File

@ -21,6 +21,14 @@ import (
"github.com/valyala/fasthttp/reuseport"
)
// Shutdown server gracefully
func (r *Fiber) Shutdown() error {
if r.httpServer == nil {
return fmt.Errorf("Server is not running")
}
return r.httpServer.Shutdown()
}
// Listen : https://gofiber.github.io/fiber/#/application?id=listen
func (r *Fiber) Listen(address interface{}, tls ...string) {
host := ""
@ -36,29 +44,7 @@ func (r *Fiber) Listen(address interface{}, tls ...string) {
log.Fatal("Listen: Host must be an INT port or STRING address")
}
// Create fasthttp server
server := &fasthttp.Server{
Handler: r.handler,
Name: r.Server,
Concurrency: r.Engine.Concurrency,
DisableKeepalive: r.Engine.DisableKeepAlive,
ReadBufferSize: r.Engine.ReadBufferSize,
WriteBufferSize: r.Engine.WriteBufferSize,
ReadTimeout: r.Engine.ReadTimeout,
WriteTimeout: r.Engine.WriteTimeout,
IdleTimeout: r.Engine.IdleTimeout,
MaxConnsPerIP: r.Engine.MaxConnsPerIP,
MaxRequestsPerConn: r.Engine.MaxRequestsPerConn,
TCPKeepalive: r.Engine.TCPKeepalive,
TCPKeepalivePeriod: r.Engine.TCPKeepalivePeriod,
MaxRequestBodySize: r.Engine.MaxRequestBodySize,
ReduceMemoryUsage: r.Engine.ReduceMemoryUsage,
GetOnly: r.Engine.GetOnly,
DisableHeaderNamesNormalizing: r.Engine.DisableHeaderNamesNormalizing,
SleepWhenConcurrencyLimitsExceeded: r.Engine.SleepWhenConcurrencyLimitsExceeded,
NoDefaultServerHeader: r.Server == "",
NoDefaultContentType: r.Engine.NoDefaultContentType,
KeepHijackedConns: r.Engine.KeepHijackedConns,
}
r.httpServer = r.setupServer()
// Prefork enabled
if r.Prefork && runtime.NumCPU() > 1 {
@ -66,7 +52,7 @@ func (r *Fiber) Listen(address interface{}, tls ...string) {
cores := fmt.Sprintf("%s\x1b[1;30m %v cores", host, runtime.NumCPU())
fmt.Printf(banner, Version, " prefork", "Express on steroids", cores)
}
r.prefork(server, host, tls...)
r.prefork(host, tls...)
}
// Prefork disabled
@ -81,18 +67,18 @@ func (r *Fiber) Listen(address interface{}, tls ...string) {
// enable TLS/HTTPS
if len(tls) > 1 {
if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil {
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
log.Fatal("Listen: ", err)
}
}
if err := server.Serve(ln); err != nil {
if err := r.httpServer.Serve(ln); err != nil {
log.Fatal("Listen: ", err)
}
}
// https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) {
func (r *Fiber) prefork(host string, tls ...string) {
// Master proc
if !r.child {
// Create babies
@ -128,12 +114,38 @@ func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) {
// enable TLS/HTTPS
if len(tls) > 1 {
if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil {
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
log.Fatal("Listen-prefork: ", err)
}
}
if err := server.Serve(ln); err != nil {
if err := r.httpServer.Serve(ln); err != nil {
log.Fatal("Listen-prefork: ", err)
}
}
func (r *Fiber) setupServer() *fasthttp.Server {
return &fasthttp.Server{
Handler: r.handler,
Name: r.Server,
Concurrency: r.Engine.Concurrency,
DisableKeepalive: r.Engine.DisableKeepAlive,
ReadBufferSize: r.Engine.ReadBufferSize,
WriteBufferSize: r.Engine.WriteBufferSize,
ReadTimeout: r.Engine.ReadTimeout,
WriteTimeout: r.Engine.WriteTimeout,
IdleTimeout: r.Engine.IdleTimeout,
MaxConnsPerIP: r.Engine.MaxConnsPerIP,
MaxRequestsPerConn: r.Engine.MaxRequestsPerConn,
TCPKeepalive: r.Engine.TCPKeepalive,
TCPKeepalivePeriod: r.Engine.TCPKeepalivePeriod,
MaxRequestBodySize: r.Engine.MaxRequestBodySize,
ReduceMemoryUsage: r.Engine.ReduceMemoryUsage,
GetOnly: r.Engine.GetOnly,
DisableHeaderNamesNormalizing: r.Engine.DisableHeaderNamesNormalizing,
SleepWhenConcurrencyLimitsExceeded: r.Engine.SleepWhenConcurrencyLimitsExceeded,
NoDefaultServerHeader: r.Server == "",
NoDefaultContentType: r.Engine.NoDefaultContentType,
KeepHijackedConns: r.Engine.KeepHijackedConns,
}
}

32
listen_test.go Normal file
View File

@ -0,0 +1,32 @@
package fiber
import (
"sync"
"testing"
)
var wg sync.WaitGroup
func Test_Connect(t *testing.T) {
return
// app := New()
// app.Banner = false
//
// wg.Add(1)
//
// go func() {
// app.Listen("8080")
// }()
//
// time.Sleep(time.Millisecond * 100)
//
// go func() {
// err := app.Shutdown()
// if err != nil {
// t.Fatalf(`%s: Failed to shutdown server %v`, t.Name(), err)
// }
// wg.Done()
// }()
// wg.Wait()
//app.Listen(":8085")
}

109
methods_test.go Normal file
View File

@ -0,0 +1,109 @@
package fiber
import (
"net/http"
"testing"
)
func Test_Methods(t *testing.T) {
app := New()
app.Connect(func(c *Ctx) {})
app.Put(func(c *Ctx) {})
app.Post(func(c *Ctx) {})
app.Delete(func(c *Ctx) {})
app.Head(func(c *Ctx) {})
app.Patch(func(c *Ctx) {})
app.Options(func(c *Ctx) {})
app.Trace(func(c *Ctx) {})
app.Get(func(c *Ctx) {})
app.All("/special", func(c *Ctx) {})
app.Use("/special/john", func(c *Ctx) {})
req, _ := http.NewRequest("CONNECT", "/", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("PUT", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("POST", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("DELETE", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("HEAD", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("PATCH", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("OPTIONS", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("TRACE", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("GET", "/", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("GET", "/special", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("GET", "/special/john", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}

View File

@ -1,18 +0,0 @@
package middleware
import "github.com/gofiber/fiber"
// app.Use(middleware.Cors())
// Cors : Enable cross-origin resource sharing (CORS) with various options.
func Cors(origin ...string) func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
o := "*"
if len(origin) > 0 {
o = origin[0]
}
c.Set("Access-Control-Allow-Origin", o)
c.Set("Access-Control-Allow-Headers", "X-Requested-With")
c.Next()
}
}

View File

@ -1,12 +0,0 @@
package middleware
import (
"github.com/gofiber/fiber"
)
// CSRF :
func CSRF() func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
c.Next()
}
}

View File

@ -1,32 +0,0 @@
package middleware
import (
"fmt"
"github.com/gofiber/fiber"
)
// HelmetOptions https://github.com/helmetjs/helmet#how-it-works
type HelmetOptions struct {
ContentSecurityPolicy string
CrossDomain string
DNSPrefetchControl string // default
ExpectCt string
FeaturePolicy string
FrameGuard string // default
Hpkp string
Hsts string // default
IeNoOpen string // default
NoCache string
NoSniff string // default
ReferrerPolicy string
XSSFilter string // default
}
// Helmet : Helps secure your apps by setting various HTTP headers.
func Helmet(opt ...*HelmetOptions) func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
fmt.Println("Helmet is still under development, this middleware does nothing yet.")
c.Next()
}
}

View File

@ -1,12 +0,0 @@
package middleware
import (
"github.com/gofiber/fiber"
)
// Limiter :
func Limiter() func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
c.Next()
}
}

View File

@ -1,17 +0,0 @@
package middleware
import (
"fmt"
"time"
"github.com/gofiber/fiber"
)
// Logger : Simple logger
func Logger() func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
currentTime := time.Now().Format("02 Jan, 15:04:05")
fmt.Printf("%s \x1b[1;32m%s \x1b[1;37m%s\x1b[0000m, %s\n", currentTime, c.Method(), c.Path(), c.Get("User-Agent"))
c.Next()
}
}

View File

@ -1,12 +0,0 @@
package middleware
import (
"github.com/gofiber/fiber"
)
// Session :
func Session() func(*fiber.Ctx) {
return func(c *fiber.Ctx) {
c.Next()
}
}

View File

@ -9,11 +9,13 @@ package fiber
import (
"encoding/base64"
"encoding/xml"
"fmt"
"mime"
"mime/multipart"
"strings"
jsoniter "github.com/json-iterator/go"
"github.com/valyala/fasthttp"
)
@ -132,6 +134,12 @@ func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
return ""
}
// BaseUrl : https://gofiber.github.io/fiber/#/context?id=baseurl
func (ctx *Ctx) BaseUrl() string {
fmt.Println("Fiber deprecated c.BaseUrl(), this will be removed in v2: Use c.BaseURL() instead")
return ctx.BaseURL()
}
// BaseURL : https://gofiber.github.io/fiber/#/context?id=baseurl
func (ctx *Ctx) BaseURL() string {
return ctx.Protocol() + "://" + ctx.Hostname()
@ -175,6 +183,8 @@ func (ctx *Ctx) Body(args ...interface{}) string {
switch arg := args[0].(type) {
case string:
return getString(ctx.Fasthttp.Request.PostArgs().Peek(arg))
case []byte:
return getString(ctx.Fasthttp.Request.PostArgs().PeekBytes(arg))
case func(string, string):
ctx.Fasthttp.Request.PostArgs().VisitAll(func(k []byte, v []byte) {
arg(getString(k), getString(v))
@ -186,6 +196,17 @@ func (ctx *Ctx) Body(args ...interface{}) string {
return ""
}
// BodyParser : https://gofiber.github.io/fiber/#/context?id=bodyparser
func (ctx *Ctx) BodyParser(v interface{}) error {
cType := getString(ctx.Fasthttp.Request.Header.ContentType())
if cType == contentTypeJSON {
return jsoniter.Unmarshal(ctx.Fasthttp.Request.Body(), v)
} else if cType == contentTypeXML {
return xml.Unmarshal(ctx.Fasthttp.Request.Body(), v)
}
return fmt.Errorf("Cannot Parse Content-Type: %v", cType)
}
// Cookies : https://gofiber.github.io/fiber/#/context?id=cookies
func (ctx *Ctx) Cookies(args ...interface{}) string {
if len(args) == 0 {
@ -312,10 +333,6 @@ func (ctx *Ctx) OriginalURL() string {
// Params : https://gofiber.github.io/fiber/#/context?id=params
func (ctx *Ctx) Params(key string) string {
if ctx.params == nil {
return ""
}
for i := 0; i < len(*ctx.params); i++ {
if (*ctx.params)[i] == key {
return ctx.values[i]

View File

@ -1,235 +1,673 @@
package fiber
import (
"bytes"
"fmt"
"mime/multipart"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"strings"
"testing"
)
func Test_Accepts(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n\r\n"
// Create fiber app
app := New()
app.Get("/", func(c *Ctx) {
expecting := "html"
result := c.Accepts(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
app.Get("/test", func(c *Ctx) {
expect := ""
result := c.Accepts(expect)
if c.Accepts() != "" {
t.Fatalf(`Expecting %s, got %s`, expect, result)
}
expecting = ".xml"
result = c.Accepts(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
expect = ".xml"
result = c.Accepts(expect)
if result != expect {
t.Fatalf(`Expecting %s, got %s`, expect, result)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req := httptest.NewRequest("GET", "/test", nil)
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_AcceptsCharsets(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\nAccept-Charset: utf-8, iso-8859-1;q=0.5\r\n\r\n"
// Raw http request
app := New()
app.Get("/", func(c *Ctx) {
expecting := "utf-8"
result := c.AcceptsCharsets(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
}
app.Get("/test", func(c *Ctx) {
c.AcceptsCharsets()
expecting = "iso-8859-1"
result = c.AcceptsCharsets(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
expect := "utf-8"
result := c.AcceptsCharsets(expect)
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("Accept-Charset", "utf-8, iso-8859-1;q=0.5")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_AcceptsEncodings(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\nAccept-Encoding: deflate, gzip;q=1.0, *;q=0.5\r\n\r\n"
// Raw http request
app := New()
app.Get("/", func(c *Ctx) {
expecting := "gzip"
result := c.AcceptsEncodings(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
}
expecting = "*"
result = c.AcceptsEncodings(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
app.Get("/test", func(c *Ctx) {
c.AcceptsEncodings()
expect := "gzip"
result := c.AcceptsEncodings(expect)
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("Accept-Encoding", "deflate, gzip;q=1.0, *;q=0.5")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_AcceptsLanguages(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\nAccept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5\r\n\r\n"
// Raw http request
app := New()
app.Get("/", func(c *Ctx) {
expecting := "fr"
result := c.AcceptsLanguages(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
}
expecting = "en"
result = c.AcceptsLanguages(expecting)
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
app.Get("/test", func(c *Ctx) {
c.AcceptsLanguages()
expect := "fr"
result := c.AcceptsLanguages(expect)
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("Accept-Language", "fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_BaseURL(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"
// Raw http request
app := New()
app.Get("/", func(c *Ctx) {
expecting := "http://localhost:8080"
app.Get("/test", func(c *Ctx) {
c.BaseUrl() // deprecated
expect := "http://google.com"
result := c.BaseURL()
if result != expecting {
t.Fatalf(`%s: Expecting %s`, t.Name(), expecting)
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "http://google.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_BasicAuth(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\nAuthorization: Basic am9objpkb2U=\r\n\r\n"
// Raw http request
app := New()
app.Get("/", func(c *Ctx) {
user, pass, ok := c.BasicAuth()
if !ok {
t.Fatalf(`%s: Expecting %s`, t.Name(), "ok")
app.Get("/test", func(c *Ctx) {
expect1 := "john"
expect2 := "doe"
result1, result2, _ := c.BasicAuth()
if result1 != expect1 {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect1, expect1)
}
if user != "john" || pass != "doe" {
if !ok {
t.Fatalf(`%s: Expecting john & doe`, t.Name())
}
if result2 != expect2 {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), result2, expect2)
}
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
req.SetBasicAuth("john", "doe")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Body(t *testing.T) {
// Raw http request
req := "POST /test HTTP/1.1\r\nHost: localhost:8080\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 9\r\n\r\nuser=john"
// Raw http request
app := New()
app.Post("/test", func(c *Ctx) {
if c.Body() != "user=john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user=john")
c.Body(1)
expect := "john=doe"
result := c.Body()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
if c.Body("user") != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
expect = "doe"
result = c.Body("john")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
expect = "doe"
result = c.Body([]byte("john"))
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
c.Body(func(k, v string) {
if k != "user" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user")
expect = "john"
if k != "john" {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, k)
}
if v != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
expect = "doe"
if v != "doe" {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, v)
}
})
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
data := url.Values{}
data.Set("john", "doe")
req, _ := http.NewRequest("POST", "/test", strings.NewReader(data.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Cookies(t *testing.T) {
// Raw http request
req := "GET /test HTTP/1.1\r\nHost: localhost:8080\r\nCookie: user=john\r\n\r\n"
// Raw http request
app := New()
app.Get("/test", func(c *Ctx) {
if c.Cookies() != "user=john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user=john")
c.Cookies(1)
expect := "john=doe"
result := c.Cookies()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
if c.Cookies("user") != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
expect = "doe"
result = c.Cookies("john")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
expect = "doe"
result = c.Cookies([]byte("john"))
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
c.Cookies(func(k, v string) {
if k != "user" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user")
expect = "john"
if k != "john" {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, k)
}
if v != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
expect = "doe"
if v != "doe" {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, v)
}
})
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
req.AddCookie(&http.Cookie{Name: "john", Value: "doe"})
_, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
}
func Test_FormFile(t *testing.T) {
// Raw http request
req := "POST /test HTTP/1.1\r\nHost: localhost:8080\r\nCookie: user=john\r\n\r\n"
// Raw http request
// TODO
}
func Test_FormValue(t *testing.T) {
app := New()
app.Post("/test", func(c *Ctx) {
if c.Cookies() != "user=john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user=john")
expect := "john"
result := c.FormValue("name")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
if c.Cookies("user") != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
}
c.Cookies(func(k, v string) {
if k != "user" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "user")
}
if v != "john" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "john")
}
})
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("name", "john")
writer.Close()
req, _ := http.NewRequest("POST", "/test", body)
contentType := fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())
req.Header.Set("Content-Type", contentType)
req.Header.Set("Content-Length", strconv.Itoa(len(body.Bytes())))
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Fresh(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Fresh()
})
req, _ := http.NewRequest("GET", "/test", nil)
_, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
}
func Test_Get(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := "utf-8, iso-8859-1;q=0.5"
result := c.Get("Accept-Charset")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
expect = "Monster"
result = c.Get("referrer")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("Accept-Charset", "utf-8, iso-8859-1;q=0.5")
req.Header.Set("Referer", "Monster")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Hostname(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := "google.com"
result := c.Hostname()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "http://google.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_IP(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Ip() // deprecated
expect := "0.0.0.0"
result := c.IP()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "http://google.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_IPs(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Ips() // deprecated
expect := []string{"0.0.0.0", "1.1.1.1"}
result := c.IPs()
if result[0] != expect[0] && result[1] != expect[1] {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("X-Forwarded-For", "0.0.0.0, 1.1.1.1")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Is(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Is(".json")
expect := true
result := c.Is("html")
if result != expect {
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("Content-Type", "text/html")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Locals(t *testing.T) {
app := New()
app.Use(func(c *Ctx) {
c.Locals("john", "doe")
c.Next()
})
app.Get("/test", func(c *Ctx) {
expect := "doe"
result := c.Locals("john")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Method(t *testing.T) {
app := New()
app.Get(func(c *Ctx) {
expect := "GET"
result := c.Method()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
app.Post(func(c *Ctx) {
expect := "POST"
result := c.Method()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
app.Put(func(c *Ctx) {
expect := "PUT"
result := c.Method()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("POST", "/test", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("PUT", "/test", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_MultipartForm(t *testing.T) {
app := New()
app.Post("/test", func(c *Ctx) {
expect := "john"
result, err := c.MultipartForm()
if err != nil {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, err)
}
if result.Value["name"][0] != expect {
t.Fatalf(`%s: Expecting %s, got %v`, t.Name(), expect, result)
}
})
// TODO: add all functions from request.go
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
writer.WriteField("name", "john")
writer.Close()
req, _ := http.NewRequest("POST", "/test", body)
contentType := fmt.Sprintf("multipart/form-data; boundary=%s", writer.Boundary())
req.Header.Set("Content-Type", contentType)
req.Header.Set("Content-Length", strconv.Itoa(len(body.Bytes())))
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_OriginalURL(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.OriginalUrl() // deprecated
expect := "/test?search=demo"
result := c.OriginalURL()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "http://google.com/test?search=demo", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Params(t *testing.T) {
app := New()
app.Get("/test/:user", func(c *Ctx) {
expect := "john"
result := c.Params("user")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
app.Get("/test2/*", func(c *Ctx) {
expect := "im/a/cookie"
result := c.Params("*")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test/john", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
req, _ = http.NewRequest("GET", "/test2/im/a/cookie", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Path(t *testing.T) {
app := New()
app.Get("/test/:user", func(c *Ctx) {
expect := "/test/john"
result := c.Path()
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test/john", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Query(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := "john"
result := c.Query("search")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
expect = "20"
result = c.Query("age")
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test?search=john&age=20", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Range(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Range()
})
req, _ := http.NewRequest("GET", "/test", nil)
_, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
}
func Test_Route(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := "/test"
result := c.Route().Path
if result != expect {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_SaveFile(t *testing.T) {
// TODO
}
func Test_Secure(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := false
result := c.Secure()
if result != expect {
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_SignedCookies(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.SignedCookies()
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_Stale(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Stale()
})
req, _ := http.NewRequest("GET", "/test", nil)
_, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
}
func Test_Subdomains(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
expect := []string{"john", "doe"}
result := c.Subdomains()
if result[0] != expect[0] && result[1] != expect[1] {
t.Fatalf(`%s: Expecting %s, got %s`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "http://john.doe.google.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}
func Test_XHR(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Xhr() // deprecated
expect := true
result := c.XHR()
if result != expect {
t.Fatalf(`%s: Expecting %v, got %v`, t.Name(), expect, result)
}
})
req, _ := http.NewRequest("GET", "/test", nil)
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
}

View File

@ -24,8 +24,7 @@ func (ctx *Ctx) Append(field string, values ...string) {
if len(values) == 0 {
return
}
h := ctx.Get(field)
h := getString(ctx.Fasthttp.Response.Header.Peek(field))
for i := range values {
if h == "" {
h += values[i]
@ -51,11 +50,12 @@ func (ctx *Ctx) Attachment(name ...string) {
func (ctx *Ctx) ClearCookie(name ...string) {
if len(name) > 0 {
for i := range name {
//ctx.Fasthttp.Request.Header.DelAllCookies()
ctx.Fasthttp.Response.Header.DelClientCookie(name[i])
}
return
}
//ctx.Fasthttp.Response.Header.DelAllCookies()
ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
ctx.Fasthttp.Response.Header.DelClientCookie(getString(k))
})
@ -352,14 +352,16 @@ func (ctx *Ctx) Vary(fields ...string) {
return
}
vary := ctx.Get(fasthttp.HeaderVary)
for _, field := range fields {
if !strings.Contains(vary, field) {
vary += ", " + field
h := getString(ctx.Fasthttp.Response.Header.Peek(fasthttp.HeaderVary))
for i := range fields {
if h == "" {
h += fields[i]
} else {
h += ", " + fields[i]
}
}
ctx.Set(fasthttp.HeaderVary, vary)
ctx.Set(fasthttp.HeaderVary, h)
}
// Write : https://gofiber.github.io/fiber/#/context?id=write

View File

@ -1,28 +1,567 @@
package fiber
import (
"io/ioutil"
"net/http"
"strings"
"testing"
)
func Test_Append(t *testing.T) {
// Raw http request
req := "GET / HTTP/1.1\r\nHost: localhost:8080\r\n\r\n"
// Create fiber app
app := New()
app.Get("/", func(c *Ctx) {
c.Append("X-Test", "hello", "world")
app.Get("/test", func(c *Ctx) {
c.Append("X-Test", "hel")
c.Append("X-Test", "lo", "world")
})
// Send fake request
res, err := app.FakeRequest(req)
// Check for errors and if route was handled
if err != nil || !strings.Contains(res, "HTTP/1.1 200 OK") {
t.Fatalf(`%s: Error serving FakeRequest %s`, t.Name(), err)
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
// Check if function works correctly
if !strings.Contains(res, "X-Test: hello, world") {
t.Fatalf(`%s: Expecting %s`, t.Name(), "X-Test: hello, world")
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("X-Test") != "hel, lo, world" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "X-Test: hel, lo, world")
}
}
func Test_Attachment(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Attachment("./static/img/logo.png")
})
req, _ := http.NewRequest("GET", "/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Disposition") != `attachment; filename="logo.png"` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `attachment; filename="logo.png"`)
}
if resp.Header.Get("Content-Type") != "image/png" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "image/png")
}
}
func Test_ClearCookie(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.ClearCookie()
})
app.Get("/test2", func(c *Ctx) {
c.ClearCookie("john")
})
req, _ := http.NewRequest("GET", "/test", nil)
req.AddCookie(&http.Cookie{Name: "john", Value: "doe"})
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if !strings.Contains(resp.Header.Get("Set-Cookie"), "expires=") {
t.Fatalf(`%s: Expecting %s`, t.Name(), "expires=")
}
req, _ = http.NewRequest("GET", "/test2", nil)
req.AddCookie(&http.Cookie{Name: "john", Value: "doe"})
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if !strings.Contains(resp.Header.Get("Set-Cookie"), "expires=") {
t.Fatalf(`%s: Expecting %s`, t.Name(), "expires=")
}
}
func Test_Cookie(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
options := &Cookie{
MaxAge: 60,
Domain: "example.com",
Path: "/",
HTTPOnly: true,
Secure: false,
SameSite: "lax",
}
c.Cookie("name", "john", options)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if !strings.Contains(resp.Header.Get("Set-Cookie"), "name=john; max-age=60; domain=example.com; path=/; HttpOnly; SameSite=Lax") {
t.Fatalf(`%s: Expecting %s`, t.Name(), "name=john; max-age=60; domain=example.com; path=/; HttpOnly; SameSite=Lax")
}
}
func Test_Download(t *testing.T) {
// TODO
}
func Test_Format(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Format("Hello, World!")
})
app.Get("/test2", func(c *Ctx) {
c.Format("Hello, World!")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
req.Header.Set("Accept", "text/html")
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != "<p>Hello, World!</p>" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "<p>Hello, World!</p>")
}
// TODO: add all functions from response.go
req, _ = http.NewRequest("GET", "http://example.com/test2", nil)
req.Header.Set("Accept", "application/json")
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `"Hello, World!"` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `"Hello, World!"`)
}
}
func Test_HeadersSent(t *testing.T) {
// TODO
}
func Test_JSON(t *testing.T) {
type SomeStruct struct {
Name string
Age uint8
}
app := New()
app.Get("/test", func(c *Ctx) {
c.Json("")
data := SomeStruct{
Name: "Grame",
Age: 20,
}
c.JSON(data)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json")
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `{"Name":"Grame","Age":20}` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`)
}
}
func Test_JSONBytes(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.JsonBytes([]byte(""))
c.JSONBytes([]byte(`{"Name":"Grame","Age":20}`))
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json")
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `{"Name":"Grame","Age":20}` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`)
}
}
func Test_JSONP(t *testing.T) {
type SomeStruct struct {
Name string
Age uint8
}
app := New()
app.Get("/test", func(c *Ctx) {
c.Jsonp("")
data := SomeStruct{
Name: "Grame",
Age: 20,
}
c.JSONP(data, "alwaysjohn")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/javascript" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "application/javascript")
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `alwaysjohn({"Name":"Grame","Age":20});` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `alwaysjohn({"Name":"Grame","Age":20});`)
}
}
func Test_JSONString(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.JsonString("")
c.JSONString(`{"Name":"Grame","Age":20}`)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "application/json")
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `{"Name":"Grame","Age":20}` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `{"Name":"Grame","Age":20}`)
}
}
func Test_Links(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Links(
"http://api.example.com/users?page=2", "next",
"http://api.example.com/users?page=5", "last",
)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Link") != `<http://api.example.com/users?page=2>; rel="next",<http://api.example.com/users?page=5>; rel="last"` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Link: <http://api.example.com/users?page=2>; rel="next",<http://api.example.com/users?page=5>; rel="last"`)
}
}
func Test_Location(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Location("http://example.com")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Location") != "http://example.com" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "http://example.com")
}
}
func Test_Next(t *testing.T) {
app := New()
app.Use("/", func(c *Ctx) {
c.Next()
})
app.Get("/test", func(c *Ctx) {
c.Set("X-Next-Result", "Works")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("X-Next-Result") != "Works" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "X-Next-Results: Works")
}
}
func Test_Redirect(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Redirect("http://example.com", 301)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 301 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Location") != "http://example.com" {
t.Fatalf(`%s: Expecting %s`, t.Name(), "Location: http://example.com")
}
}
func Test_Render(t *testing.T) {
// TODO
}
func Test_Send(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Send([]byte("Hello, World"))
c.Send("Don't crash please")
c.Send(1337)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `1337` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `1337`)
}
}
func Test_SendBytes(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.SendBytes([]byte("Hello, World"))
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `Hello, World` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World`)
}
}
func Test_SendStatus(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.SendStatus(415)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 415 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `Unsupported Media Type` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Unsupported Media Type`)
}
}
func Test_SendString(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.SendString("Don't crash please")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `Don't crash please` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Don't crash please`)
}
}
func Test_Set(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Set("X-1", "1")
c.Set("X-2", "2")
c.Set("X-3", "3")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("X-1") != "1" {
t.Fatalf(`%s: Expected %v`, t.Name(), "X-1: 1")
}
if resp.Header.Get("X-2") != "2" {
t.Fatalf(`%s: Expected %v`, t.Name(), "X-2: 2")
}
if resp.Header.Get("X-3") != "3" {
t.Fatalf(`%s: Expected %v`, t.Name(), "X-3: 3")
}
}
func Test_Status(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Status(400)
c.Status(415).Send("Hello, World")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 415 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `Hello, World` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World`)
}
}
func Test_Type(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Type(".json")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/json" {
t.Fatalf(`%s: Expected %v`, t.Name(), `Content-Type: application/json`)
}
}
func Test_Vary(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Vary("Origin")
c.Vary("User-Agent")
c.Vary("Accept-Encoding", "Accept")
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Vary") != "Origin, User-Agent, Accept-Encoding, Accept" {
t.Fatalf(`%s: Expected %v`, t.Name(), `Vary: Origin, User-Agent, Accept-Encoding, Accept`)
}
}
func Test_Write(t *testing.T) {
app := New()
app.Get("/test", func(c *Ctx) {
c.Write("Hello, ")
c.Write([]byte("World! "))
c.Write(123)
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `Hello, World! 123` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `Hello, World! 123`)
}
}
func Test_XML(t *testing.T) {
type person struct {
Name string `xml:"name"`
Stars int `xml:"stars"`
}
app := New()
app.Get("/test", func(c *Ctx) {
c.Xml("")
c.XML(person{"John", 50})
})
req, _ := http.NewRequest("GET", "http://example.com/test", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Type") != "application/xml" {
t.Fatalf(`%s: Expected %v`, t.Name(), "application/xml")
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf(`%s: Error %s`, t.Name(), err)
}
if string(body) != `<person><name>John</name><stars>50</stars></person>` {
t.Fatalf(`%s: Expecting %s`, t.Name(), `<person><name>John</name><stars>50</stars></person>`)
}
}

View File

@ -9,6 +9,7 @@ package fiber
import (
"log"
"os"
"path/filepath"
"strings"
)
@ -36,6 +37,11 @@ func (r *Fiber) Static(args ...string) {
wildcard = true
}
// Check if root exists
if _, err := os.Lstat(root); err != nil {
log.Fatal("Static: ", err)
}
// Lets get all files from root
files, _, err := getFiles(root)
if err != nil {

35
static_test.go Normal file
View File

@ -0,0 +1,35 @@
package fiber
import (
"net/http"
"testing"
)
func Test_Static(t *testing.T) {
app := New()
app.Static("./.github")
app.Static("/john", "./.github")
app.Static("*", "./.github/stale.yml")
req, _ := http.NewRequest("GET", "/stale.yml", nil)
resp, err := app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Length") == "" {
t.Fatalf(`%s: Missing Content-Length`, t.Name())
}
req, _ = http.NewRequest("GET", "/john/stale.yml", nil)
resp, err = app.Test(req)
if err != nil {
t.Fatalf(`%s: %s`, t.Name(), err)
}
if resp.StatusCode != 200 {
t.Fatalf(`%s: StatusCode %v`, t.Name(), resp.StatusCode)
}
if resp.Header.Get("Content-Length") == "" {
t.Fatalf(`%s: Missing Content-Length`, t.Name())
}
}

120
utils.go
View File

@ -8,10 +8,13 @@
package fiber
import (
"bufio"
"bytes"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"os"
"path/filepath"
"reflect"
@ -19,8 +22,6 @@ import (
"strings"
"time"
"unsafe"
"github.com/valyala/fasthttp"
)
func getParams(path string) (params []string) {
@ -75,6 +76,9 @@ func getFiles(root string) (files []string, isDir bool, err error) {
}
func getType(ext string) (mime string) {
if ext == "" {
return mime
}
if ext[0] == '.' {
ext = ext[1:]
}
@ -107,92 +111,68 @@ func getBytes(s string) (b []byte) {
return b
}
// FakeRequest creates a readWriter and calls ServeConn on local servver
func (r *Fiber) FakeRequest(raw string) (string, error) {
server := &fasthttp.Server{
Handler: r.handler,
Name: r.Server,
Concurrency: r.Engine.Concurrency,
DisableKeepalive: r.Engine.DisableKeepAlive,
ReadBufferSize: r.Engine.ReadBufferSize,
WriteBufferSize: r.Engine.WriteBufferSize,
ReadTimeout: r.Engine.ReadTimeout,
WriteTimeout: r.Engine.WriteTimeout,
IdleTimeout: r.Engine.IdleTimeout,
MaxConnsPerIP: r.Engine.MaxConnsPerIP,
MaxRequestsPerConn: r.Engine.MaxRequestsPerConn,
TCPKeepalive: r.Engine.TCPKeepalive,
TCPKeepalivePeriod: r.Engine.TCPKeepalivePeriod,
MaxRequestBodySize: r.Engine.MaxRequestBodySize,
ReduceMemoryUsage: r.Engine.ReduceMemoryUsage,
GetOnly: r.Engine.GetOnly,
DisableHeaderNamesNormalizing: r.Engine.DisableHeaderNamesNormalizing,
SleepWhenConcurrencyLimitsExceeded: r.Engine.SleepWhenConcurrencyLimitsExceeded,
NoDefaultServerHeader: r.Server == "",
NoDefaultContentType: r.Engine.NoDefaultContentType,
KeepHijackedConns: r.Engine.KeepHijackedConns,
// Test takes a http.Request and execute a fake connection to the application
// It returns a http.Response when the connection was successfull
func (r *Fiber) Test(req *http.Request) (*http.Response, error) {
// Get raw http request
reqRaw, err := httputil.DumpRequest(req, true)
if err != nil {
return nil, err
}
rw := &readWriter{}
rw.r.WriteString(raw)
ch := make(chan error)
// Setup a fiber server struct
r.httpServer = r.setupServer()
// Create fake connection
conn := &conn{}
// Pass HTTP request to conn
conn.r.Write(reqRaw)
// Serve conn to server
channel := make(chan error)
go func() {
ch <- server.ServeConn(rw)
channel <- r.httpServer.ServeConn(conn)
}()
// Wait for callback
select {
case err := <-ch:
case err := <-channel:
if err != nil {
return "", err
return nil, err
}
case <-time.After(200 * time.Millisecond):
return "", fmt.Errorf("Timeout")
// Throw timeout error after 200ms
case <-time.After(500 * time.Millisecond):
return nil, fmt.Errorf("Timeout")
}
err := server.ServeConn(rw)
// Get raw HTTP response
respRaw, err := ioutil.ReadAll(&conn.w)
if err != nil {
return "", err
return nil, err
}
resp, err := ioutil.ReadAll(&rw.w)
// Create buffer
reader := strings.NewReader(getString(respRaw))
buffer := bufio.NewReader(reader)
// Convert raw HTTP response to http.Response
resp, err := http.ReadResponse(buffer, req)
if err != nil {
return "", err
return nil, err
}
return getString(resp), nil
// Return *http.Response
return resp, nil
}
// Readwriter for test cases
type readWriter struct {
// https://golang.org/src/net/net.go#L113
type conn struct {
net.Conn
r bytes.Buffer
w bytes.Buffer
}
func (rw *readWriter) Close() error {
return nil
}
func (rw *readWriter) Read(b []byte) (int, error) {
return rw.r.Read(b)
}
func (rw *readWriter) Write(b []byte) (int, error) {
return rw.w.Write(b)
}
func (rw *readWriter) RemoteAddr() net.Addr {
func (c *conn) RemoteAddr() net.Addr {
return &net.TCPAddr{
IP: net.IPv4zero,
IP: net.IPv4(0, 0, 0, 0),
}
}
func (rw *readWriter) LocalAddr() net.Addr {
return rw.RemoteAddr()
}
func (rw *readWriter) SetReadDeadline(t time.Time) error {
return nil
}
func (rw *readWriter) SetWriteDeadline(t time.Time) error {
return nil
}
func (c *conn) LocalAddr() net.Addr { return c.LocalAddr() }
func (c *conn) Read(b []byte) (int, error) { return c.r.Read(b) }
func (c *conn) Write(b []byte) (int, error) { return c.w.Write(b) }
func (c *conn) Close() error { return nil }
func (c *conn) SetDeadline(t time.Time) error { return nil }
func (c *conn) SetReadDeadline(t time.Time) error { return nil }
func (c *conn) SetWriteDeadline(t time.Time) error { return nil }