diff --git a/.travis.yml b/.travis.yml
index 8af4fd52..1e4f6a69 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,9 @@
 language: go
+
+os:
+  - linux
+#  - windows
+  - osx
 go:
   - 1.13.x
 env:
diff --git a/README.md b/README.md
index 2005104a..0366a942 100644
--- a/README.md
+++ b/README.md
@@ -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).
diff --git a/README_CH.md b/README_CH.md
index abee1c62..ea1467aa 100644
--- a/README_CH.md
+++ b/README_CH.md
@@ -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).
diff --git a/README_NEW.md b/README_NEW.md
new file mode 100644
index 00000000..93b385c1
--- /dev/null
+++ b/README_NEW.md
@@ -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).
diff --git a/application.go b/application.go
index 3bc3d493..e55b14ae 100644
--- a/application.go
+++ b/application.go
@@ -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,
diff --git a/listen.go b/listen.go
index 1ba0f1c4..b4867c4f 100644
--- a/listen.go
+++ b/listen.go
@@ -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,
+	}
+}
diff --git a/listen_test.go b/listen_test.go
new file mode 100644
index 00000000..c5f6cc6a
--- /dev/null
+++ b/listen_test.go
@@ -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")
+}
diff --git a/methods_test.go b/methods_test.go
new file mode 100644
index 00000000..6d8f32db
--- /dev/null
+++ b/methods_test.go
@@ -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)
+	}
+}
diff --git a/middleware/cors.go b/middleware/cors.go
deleted file mode 100644
index fc5b2cd9..00000000
--- a/middleware/cors.go
+++ /dev/null
@@ -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()
-	}
-}
diff --git a/middleware/csrf.go b/middleware/csrf.go
deleted file mode 100644
index 29502495..00000000
--- a/middleware/csrf.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package middleware
-
-import (
-	"github.com/gofiber/fiber"
-)
-
-// CSRF :
-func CSRF() func(*fiber.Ctx) {
-	return func(c *fiber.Ctx) {
-		c.Next()
-	}
-}
diff --git a/middleware/helmet.go b/middleware/helmet.go
deleted file mode 100644
index d937d6b3..00000000
--- a/middleware/helmet.go
+++ /dev/null
@@ -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()
-	}
-}
diff --git a/middleware/limiter.go b/middleware/limiter.go
deleted file mode 100644
index bf25b74b..00000000
--- a/middleware/limiter.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package middleware
-
-import (
-	"github.com/gofiber/fiber"
-)
-
-// Limiter :
-func Limiter() func(*fiber.Ctx) {
-	return func(c *fiber.Ctx) {
-		c.Next()
-	}
-}
diff --git a/middleware/logger.go b/middleware/logger.go
deleted file mode 100644
index 46e047cb..00000000
--- a/middleware/logger.go
+++ /dev/null
@@ -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()
-	}
-}
diff --git a/middleware/session.go b/middleware/session.go
deleted file mode 100644
index 06eb87f2..00000000
--- a/middleware/session.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package middleware
-
-import (
-	"github.com/gofiber/fiber"
-)
-
-// Session :
-func Session() func(*fiber.Ctx) {
-	return func(c *fiber.Ctx) {
-		c.Next()
-	}
-}
diff --git a/request.go b/request.go
index d0b172a5..23a0aa9f 100644
--- a/request.go
+++ b/request.go
@@ -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]
diff --git a/request_test.go b/request_test.go
index 74d39505..45f09c2f 100644
--- a/request_test.go
+++ b/request_test.go
@@ -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)
+	}
+}
diff --git a/response.go b/response.go
index d573e74e..4a71839f 100644
--- a/response.go
+++ b/response.go
@@ -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
diff --git a/response_test.go b/response_test.go
index 88146579..abf1cc88 100644
--- a/response_test.go
+++ b/response_test.go
@@ -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>`)
+	}
+}
diff --git a/static.go b/static.go
index 6463b759..4de39730 100644
--- a/static.go
+++ b/static.go
@@ -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 {
diff --git a/static_test.go b/static_test.go
new file mode 100644
index 00000000..e291c9a7
--- /dev/null
+++ b/static_test.go
@@ -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())
+	}
+}
diff --git a/utils.go b/utils.go
index 14dbf384..3ac0f0e0 100644
--- a/utils.go
+++ b/utils.go
@@ -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 }