mirror of https://github.com/gofiber/fiber.git
Clean up repository
parent
401b21a0d4
commit
1e7df547ba
|
@ -1,7 +1,7 @@
|
|||
|
||||
# 🚀 Fiber <a href="https://github.com/gofiber/fiber/blob/master/.github/README_RU.md"><img width="20px" src="https://github.com/gofiber/docs/blob/master/static/flags/ru.svg" alt="ru"/></a> <a href="https://github.com/gofiber/fiber/blob/master/.github/README_CH.md"><img width="20px" src="https://github.com/gofiber/docs/blob/master/static/flags/ch.svg" alt="ch"/></a>
|
||||
|
||||
[](https://github.com/gofiber/fiber/releases)  [](https://godoc.org/github.com/gofiber/fiber)  [](https://github.com/gofiber/fiber/blob/master/LICENSE) [](https://gitter.im/gofiber/community) [](https://gitpod.io/#https://github.com/gofiber/fiber)
|
||||
[](https://github.com/gofiber/fiber/releases)  [](https://godoc.org/github.com/gofiber/fiber)  [](https://github.com/gofiber/fiber/blob/master/LICENSE) [](https://gitter.im/gofiber/community) [](https://gitpod.io/#https://github.com/gofiber/fiber)
|
||||
|
||||
<img align="right" height="180px" src="https://github.com/gofiber/docs/blob/master/static/logo_320px_trans.png" alt="Fiber logo" />
|
||||
|
||||
|
|
269
application.go
269
application.go
|
@ -9,9 +9,19 @@ package fiber
|
|||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"github.com/valyala/fasthttp/reuseport"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -102,3 +112,262 @@ func New() *Fiber {
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Connect establishes a tunnel to the server
|
||||
// identified by the target resource.
|
||||
func (r *Fiber) Connect(args ...interface{}) {
|
||||
r.register("CONNECT", args...)
|
||||
}
|
||||
|
||||
// Put replaces all current representations
|
||||
// of the target resource with the request payload.
|
||||
func (r *Fiber) Put(args ...interface{}) {
|
||||
r.register("PUT", args...)
|
||||
}
|
||||
|
||||
// Post is used to submit an entity to the specified resource,
|
||||
// often causing a change in state or side effects on the server.
|
||||
func (r *Fiber) Post(args ...interface{}) {
|
||||
r.register("POST", args...)
|
||||
}
|
||||
|
||||
// Delete deletes the specified resource.
|
||||
func (r *Fiber) Delete(args ...interface{}) {
|
||||
r.register("DELETE", args...)
|
||||
}
|
||||
|
||||
// Head asks for a response identical to that of a GET request,
|
||||
// but without the response body.
|
||||
func (r *Fiber) Head(args ...interface{}) {
|
||||
r.register("HEAD", args...)
|
||||
}
|
||||
|
||||
// Patch is used to apply partial modifications to a resource.
|
||||
func (r *Fiber) Patch(args ...interface{}) {
|
||||
r.register("PATCH", args...)
|
||||
}
|
||||
|
||||
// Options is used to describe the communication options
|
||||
// for the target resource.
|
||||
func (r *Fiber) Options(args ...interface{}) {
|
||||
r.register("OPTIONS", args...)
|
||||
}
|
||||
|
||||
// Trace performs a message loop-back test
|
||||
// along the path to the target resource.
|
||||
func (r *Fiber) Trace(args ...interface{}) {
|
||||
r.register("TRACE", args...)
|
||||
}
|
||||
|
||||
// Get requests a representation of the specified resource.
|
||||
// Requests using GET should only retrieve data.
|
||||
func (r *Fiber) Get(args ...interface{}) {
|
||||
r.register("GET", args...)
|
||||
}
|
||||
|
||||
// All matches any HTTP method
|
||||
func (r *Fiber) All(args ...interface{}) {
|
||||
r.register("ALL", args...)
|
||||
}
|
||||
|
||||
// Use only matches the starting path
|
||||
func (r *Fiber) Use(args ...interface{}) {
|
||||
r.register("MIDWARE", args...)
|
||||
}
|
||||
|
||||
// Static https://fiber.wiki/application#static
|
||||
func (r *Fiber) Static(args ...string) {
|
||||
prefix := "/"
|
||||
root := "./"
|
||||
wildcard := false
|
||||
// enable / disable gzipping somewhere?
|
||||
// todo v2.0.0
|
||||
gzip := true
|
||||
|
||||
if len(args) == 1 {
|
||||
root = args[0]
|
||||
} else if len(args) == 2 {
|
||||
prefix = args[0]
|
||||
root = args[1]
|
||||
if prefix[0] != '/' {
|
||||
prefix = "/" + prefix
|
||||
}
|
||||
}
|
||||
|
||||
// Check if wildcard for single files
|
||||
// app.Static("*", "./public/index.html")
|
||||
// app.Static("/*", "./public/index.html")
|
||||
if prefix == "*" || prefix == "/*" {
|
||||
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 {
|
||||
log.Fatal("Static: ", err)
|
||||
}
|
||||
|
||||
// ./static/compiled => static/compiled
|
||||
mount := filepath.Clean(root)
|
||||
|
||||
// Loop over all files
|
||||
for _, file := range files {
|
||||
// Ignore the .gzipped files by fasthttp
|
||||
if strings.Contains(file, ".fasthttp.gz") {
|
||||
continue
|
||||
}
|
||||
|
||||
// Time to create a fake path for the route match
|
||||
// static/index.html => /index.html
|
||||
path := filepath.Join(prefix, strings.Replace(file, mount, "", 1))
|
||||
|
||||
// Store original file path to use in ctx handler
|
||||
filePath := file
|
||||
|
||||
// If the file is an index.html, bind the prefix to index.html directly
|
||||
if filepath.Base(filePath) == "index.html" || filepath.Base(filePath) == "index.htm" {
|
||||
r.routes = append(r.routes, &Route{"GET", prefix, wildcard, false, nil, nil, func(c *Ctx) {
|
||||
c.SendFile(filePath, gzip)
|
||||
}})
|
||||
}
|
||||
|
||||
// Add the route + SendFile(filepath) to routes
|
||||
r.routes = append(r.routes, &Route{"GET", path, wildcard, false, nil, nil, func(c *Ctx) {
|
||||
c.SendFile(filePath, gzip)
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
||||
// Listen : https://fiber.wiki/application#listen
|
||||
func (r *Fiber) Listen(address interface{}, tls ...string) {
|
||||
host := ""
|
||||
switch val := address.(type) {
|
||||
case int:
|
||||
host = ":" + strconv.Itoa(val) // 8080 => ":8080"
|
||||
case string:
|
||||
if !strings.Contains(val, ":") {
|
||||
val = ":" + val // "8080" => ":8080"
|
||||
}
|
||||
host = val
|
||||
default:
|
||||
log.Fatal("Listen: Host must be an INT port or STRING address")
|
||||
}
|
||||
// Create fasthttp server
|
||||
r.httpServer = r.setupServer()
|
||||
|
||||
// Prefork enabled
|
||||
if r.Prefork && runtime.NumCPU() > 1 {
|
||||
if r.Banner && !r.child {
|
||||
cores := fmt.Sprintf("%s\x1b[1;30m %v cores", host, runtime.NumCPU())
|
||||
fmt.Printf(banner, Version, " prefork", "Express on steroids", cores)
|
||||
}
|
||||
r.prefork(host, tls...)
|
||||
}
|
||||
|
||||
// Prefork disabled
|
||||
if r.Banner {
|
||||
fmt.Printf(banner, Version, "", "Express on steroids", host)
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp4", host)
|
||||
if err != nil {
|
||||
log.Fatal("Listen: ", err)
|
||||
}
|
||||
|
||||
// enable TLS/HTTPS
|
||||
if len(tls) > 1 {
|
||||
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
|
||||
log.Fatal("Listen: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := r.httpServer.Serve(ln); err != nil {
|
||||
log.Fatal("Listen: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown server gracefully
|
||||
func (r *Fiber) Shutdown() error {
|
||||
if r.httpServer == nil {
|
||||
return fmt.Errorf("Server is not running")
|
||||
}
|
||||
return r.httpServer.Shutdown()
|
||||
}
|
||||
|
||||
// https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
|
||||
func (r *Fiber) prefork(host string, tls ...string) {
|
||||
// Master proc
|
||||
if !r.child {
|
||||
// Create babies
|
||||
childs := make([]*exec.Cmd, runtime.NumCPU())
|
||||
|
||||
// #nosec G204
|
||||
for i := range childs {
|
||||
childs[i] = exec.Command(os.Args[0], "-prefork", "-child")
|
||||
childs[i].Stdout = os.Stdout
|
||||
childs[i].Stderr = os.Stderr
|
||||
if err := childs[i].Start(); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, child := range childs {
|
||||
if err := child.Wait(); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Child proc
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
ln, err := reuseport.Listen("tcp4", host)
|
||||
if err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
|
||||
// enable TLS/HTTPS
|
||||
if len(tls) > 1 {
|
||||
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package fiber
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Methods(t *testing.T) {
|
||||
app := New()
|
||||
|
||||
handler := func(c *Ctx) {}
|
||||
methods := []string{"CONNECT", "PUT", "POST", "DELETE", "HEAD", "PATCH", "OPTIONS", "TRACE", "GET", "ALL", "USE"}
|
||||
|
||||
app.Connect("/CONNECT", handler)
|
||||
app.Put("/PUT", handler)
|
||||
app.Post("/POST", handler)
|
||||
app.Delete("/DELETE", handler)
|
||||
app.Head("/HEAD", handler)
|
||||
app.Patch("/PATCH", handler)
|
||||
app.Options("/OPTIONS", handler)
|
||||
app.Trace("/TRACE", handler)
|
||||
app.Get("/GET", handler)
|
||||
app.All("/ALL", handler)
|
||||
app.Use("/USE", handler)
|
||||
|
||||
for _, method := range methods {
|
||||
var req *http.Request
|
||||
if method == "ALL" {
|
||||
req, _ = http.NewRequest("CONNECT", "/"+method, nil)
|
||||
} else if method == "USE" {
|
||||
req, _ = http.NewRequest("OPTIONS", "/"+method+"/test", nil)
|
||||
} else {
|
||||
req, _ = http.NewRequest(method, "/"+method, nil)
|
||||
}
|
||||
resp, err := app.Test(req)
|
||||
if err != nil {
|
||||
t.Fatalf(`%s: %s %s`, t.Name(), method, err)
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
t.Fatalf(`%s: %s expecting 200 but received %v`, t.Name(), method, resp.StatusCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
59
context.go
59
context.go
|
@ -1,59 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// Ctx : struct
|
||||
type Ctx struct {
|
||||
route *Route
|
||||
next bool
|
||||
params *[]string
|
||||
values []string
|
||||
Fasthttp *fasthttp.RequestCtx
|
||||
}
|
||||
|
||||
// Cookie : struct
|
||||
type Cookie struct {
|
||||
Expire int // time.Unix(1578981376, 0)
|
||||
MaxAge int
|
||||
Domain string
|
||||
Path string
|
||||
|
||||
HTTPOnly bool
|
||||
Secure bool
|
||||
SameSite string
|
||||
}
|
||||
|
||||
// Ctx pool
|
||||
var poolCtx = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(Ctx)
|
||||
},
|
||||
}
|
||||
|
||||
// Get new Ctx from pool
|
||||
func acquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
|
||||
ctx := poolCtx.Get().(*Ctx)
|
||||
ctx.Fasthttp = fctx
|
||||
return ctx
|
||||
}
|
||||
|
||||
// Return Context to pool
|
||||
func releaseCtx(ctx *Ctx) {
|
||||
ctx.route = nil
|
||||
ctx.next = false
|
||||
ctx.params = nil
|
||||
ctx.values = nil
|
||||
ctx.Fasthttp = nil
|
||||
poolCtx.Put(ctx)
|
||||
}
|
151
listen.go
151
listen.go
|
@ -1,151 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
"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://fiber.wiki/application#listen
|
||||
func (r *Fiber) Listen(address interface{}, tls ...string) {
|
||||
host := ""
|
||||
switch val := address.(type) {
|
||||
case int:
|
||||
host = ":" + strconv.Itoa(val) // 8080 => ":8080"
|
||||
case string:
|
||||
if !strings.Contains(val, ":") {
|
||||
val = ":" + val // "8080" => ":8080"
|
||||
}
|
||||
host = val
|
||||
default:
|
||||
log.Fatal("Listen: Host must be an INT port or STRING address")
|
||||
}
|
||||
// Create fasthttp server
|
||||
r.httpServer = r.setupServer()
|
||||
|
||||
// Prefork enabled
|
||||
if r.Prefork && runtime.NumCPU() > 1 {
|
||||
if r.Banner && !r.child {
|
||||
cores := fmt.Sprintf("%s\x1b[1;30m %v cores", host, runtime.NumCPU())
|
||||
fmt.Printf(banner, Version, " prefork", "Express on steroids", cores)
|
||||
}
|
||||
r.prefork(host, tls...)
|
||||
}
|
||||
|
||||
// Prefork disabled
|
||||
if r.Banner {
|
||||
fmt.Printf(banner, Version, "", "Express on steroids", host)
|
||||
}
|
||||
|
||||
ln, err := net.Listen("tcp4", host)
|
||||
if err != nil {
|
||||
log.Fatal("Listen: ", err)
|
||||
}
|
||||
|
||||
// enable TLS/HTTPS
|
||||
if len(tls) > 1 {
|
||||
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
|
||||
log.Fatal("Listen: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
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(host string, tls ...string) {
|
||||
// Master proc
|
||||
if !r.child {
|
||||
// Create babies
|
||||
childs := make([]*exec.Cmd, runtime.NumCPU())
|
||||
|
||||
// #nosec G204
|
||||
for i := range childs {
|
||||
childs[i] = exec.Command(os.Args[0], "-prefork", "-child")
|
||||
childs[i].Stdout = os.Stdout
|
||||
childs[i].Stderr = os.Stderr
|
||||
if err := childs[i].Start(); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, child := range childs {
|
||||
if err := child.Wait(); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Child proc
|
||||
runtime.GOMAXPROCS(1)
|
||||
|
||||
ln, err := reuseport.Listen("tcp4", host)
|
||||
if err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
|
||||
// enable TLS/HTTPS
|
||||
if len(tls) > 1 {
|
||||
if err := r.httpServer.ServeTLS(ln, tls[0], tls[1]); err != nil {
|
||||
log.Fatal("Listen-prefork: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package fiber
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// var wg sync.WaitGroup
|
||||
|
||||
func Test_Connect(t *testing.T) {
|
||||
// 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")
|
||||
}
|
70
methods.go
70
methods.go
|
@ -1,70 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
// Connect establishes a tunnel to the server
|
||||
// identified by the target resource.
|
||||
func (r *Fiber) Connect(args ...interface{}) {
|
||||
r.register("CONNECT", args...)
|
||||
}
|
||||
|
||||
// Put replaces all current representations
|
||||
// of the target resource with the request payload.
|
||||
func (r *Fiber) Put(args ...interface{}) {
|
||||
r.register("PUT", args...)
|
||||
}
|
||||
|
||||
// Post is used to submit an entity to the specified resource,
|
||||
// often causing a change in state or side effects on the server.
|
||||
func (r *Fiber) Post(args ...interface{}) {
|
||||
r.register("POST", args...)
|
||||
}
|
||||
|
||||
// Delete deletes the specified resource.
|
||||
func (r *Fiber) Delete(args ...interface{}) {
|
||||
r.register("DELETE", args...)
|
||||
}
|
||||
|
||||
// Head asks for a response identical to that of a GET request,
|
||||
// but without the response body.
|
||||
func (r *Fiber) Head(args ...interface{}) {
|
||||
r.register("HEAD", args...)
|
||||
}
|
||||
|
||||
// Patch is used to apply partial modifications to a resource.
|
||||
func (r *Fiber) Patch(args ...interface{}) {
|
||||
r.register("PATCH", args...)
|
||||
}
|
||||
|
||||
// Options is used to describe the communication options
|
||||
// for the target resource.
|
||||
func (r *Fiber) Options(args ...interface{}) {
|
||||
r.register("OPTIONS", args...)
|
||||
}
|
||||
|
||||
// Trace performs a message loop-back test
|
||||
// along the path to the target resource.
|
||||
func (r *Fiber) Trace(args ...interface{}) {
|
||||
r.register("TRACE", args...)
|
||||
}
|
||||
|
||||
// Get requests a representation of the specified resource.
|
||||
// Requests using GET should only retrieve data.
|
||||
func (r *Fiber) Get(args ...interface{}) {
|
||||
r.register("GET", args...)
|
||||
}
|
||||
|
||||
// All matches any HTTP method
|
||||
func (r *Fiber) All(args ...interface{}) {
|
||||
r.register("ALL", args...)
|
||||
}
|
||||
|
||||
// Use only matches the starting path
|
||||
func (r *Fiber) Use(args ...interface{}) {
|
||||
r.register("MIDWARE", args...)
|
||||
}
|
109
methods_test.go
109
methods_test.go
|
@ -1,109 +0,0 @@
|
|||
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)
|
||||
}
|
||||
}
|
14
response.go
14
response.go
|
@ -19,6 +19,18 @@ import (
|
|||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// Cookie : struct
|
||||
type Cookie struct {
|
||||
Expire int // time.Unix(1578981376, 0)
|
||||
MaxAge int
|
||||
Domain string
|
||||
Path string
|
||||
|
||||
HTTPOnly bool
|
||||
Secure bool
|
||||
SameSite string
|
||||
}
|
||||
|
||||
// Append : https://fiber.wiki/context#append
|
||||
func (ctx *Ctx) Append(field string, values ...string) {
|
||||
if len(values) == 0 {
|
||||
|
@ -224,7 +236,7 @@ func (ctx *Ctx) JsonString(raw string) {
|
|||
ctx.JSONString(raw)
|
||||
}
|
||||
|
||||
// JSONString : https://fiber.wiki/context#jsonstring
|
||||
// JSONString : https://fiber.wiki/context#json
|
||||
func (ctx *Ctx) JSONString(raw string) {
|
||||
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJSON)
|
||||
ctx.Fasthttp.Response.SetBodyString(raw)
|
||||
|
|
34
router.go
34
router.go
|
@ -11,10 +11,20 @@ import (
|
|||
"log"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
// Ctx : struct
|
||||
type Ctx struct {
|
||||
route *Route
|
||||
next bool
|
||||
params *[]string
|
||||
values []string
|
||||
Fasthttp *fasthttp.RequestCtx
|
||||
}
|
||||
|
||||
// Route : struct
|
||||
type Route struct {
|
||||
// HTTP method in uppercase, can be a * for Use() & All()
|
||||
|
@ -33,6 +43,30 @@ type Route struct {
|
|||
Handler func(*Ctx)
|
||||
}
|
||||
|
||||
// Ctx pool
|
||||
var poolCtx = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(Ctx)
|
||||
},
|
||||
}
|
||||
|
||||
// Get new Ctx from pool
|
||||
func acquireCtx(fctx *fasthttp.RequestCtx) *Ctx {
|
||||
ctx := poolCtx.Get().(*Ctx)
|
||||
ctx.Fasthttp = fctx
|
||||
return ctx
|
||||
}
|
||||
|
||||
// Return Context to pool
|
||||
func releaseCtx(ctx *Ctx) {
|
||||
ctx.route = nil
|
||||
ctx.next = false
|
||||
ctx.params = nil
|
||||
ctx.values = nil
|
||||
ctx.Fasthttp = nil
|
||||
poolCtx.Put(ctx)
|
||||
}
|
||||
|
||||
// Function to add a route correctly
|
||||
func (r *Fiber) register(method string, args ...interface{}) {
|
||||
// Set if method is Use() midware
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package fiber
|
83
static.go
83
static.go
|
@ -1,83 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Static https://fiber.wiki/application#static
|
||||
func (r *Fiber) Static(args ...string) {
|
||||
prefix := "/"
|
||||
root := "./"
|
||||
wildcard := false
|
||||
// enable / disable gzipping somewhere?
|
||||
// todo v2.0.0
|
||||
gzip := true
|
||||
|
||||
if len(args) == 1 {
|
||||
root = args[0]
|
||||
} else if len(args) == 2 {
|
||||
prefix = args[0]
|
||||
root = args[1]
|
||||
if prefix[0] != '/' {
|
||||
prefix = "/" + prefix
|
||||
}
|
||||
}
|
||||
|
||||
// Check if wildcard for single files
|
||||
// app.Static("*", "./public/index.html")
|
||||
// app.Static("/*", "./public/index.html")
|
||||
if prefix == "*" || prefix == "/*" {
|
||||
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 {
|
||||
log.Fatal("Static: ", err)
|
||||
}
|
||||
|
||||
// ./static/compiled => static/compiled
|
||||
mount := filepath.Clean(root)
|
||||
|
||||
// Loop over all files
|
||||
for _, file := range files {
|
||||
// Ignore the .gzipped files by fasthttp
|
||||
if strings.Contains(file, ".fasthttp.gz") {
|
||||
continue
|
||||
}
|
||||
|
||||
// Time to create a fake path for the route match
|
||||
// static/index.html => /index.html
|
||||
path := filepath.Join(prefix, strings.Replace(file, mount, "", 1))
|
||||
|
||||
// Store original file path to use in ctx handler
|
||||
filePath := file
|
||||
|
||||
// If the file is an index.html, bind the prefix to index.html directly
|
||||
if filepath.Base(filePath) == "index.html" || filepath.Base(filePath) == "index.htm" {
|
||||
r.routes = append(r.routes, &Route{"GET", prefix, wildcard, false, nil, nil, func(c *Ctx) {
|
||||
c.SendFile(filePath, gzip)
|
||||
}})
|
||||
}
|
||||
|
||||
// Add the route + SendFile(filepath) to routes
|
||||
r.routes = append(r.routes, &Route{"GET", path, wildcard, false, nil, nil, func(c *Ctx) {
|
||||
c.SendFile(filePath, gzip)
|
||||
}})
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
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())
|
||||
}
|
||||
}
|
71
status.go
71
status.go
|
@ -1,71 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
var statusMessages = map[int]string{
|
||||
100: "Continue",
|
||||
101: "Switching Protocols",
|
||||
102: "Processing",
|
||||
200: "OK",
|
||||
201: "Created",
|
||||
202: "Accepted",
|
||||
203: "Non-Authoritative Information",
|
||||
204: "No Content",
|
||||
205: "Reset Content",
|
||||
206: "Partial Content",
|
||||
207: "Multi-Status",
|
||||
208: "Already Reported",
|
||||
226: "IM Used",
|
||||
300: "Multiple Choices",
|
||||
301: "Moved Permanently",
|
||||
302: "Found",
|
||||
303: "See Other",
|
||||
304: "Not Modified",
|
||||
305: "Use Proxy",
|
||||
306: "Switch Proxy",
|
||||
307: "Temporary Redirect",
|
||||
308: "Permanent Redirect",
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
402: "Payment Required",
|
||||
403: "Forbidden",
|
||||
404: "Not Found",
|
||||
405: "Method Not Allowed",
|
||||
406: "Not Acceptable",
|
||||
407: "Proxy Authentication Required",
|
||||
408: "Request Timeout",
|
||||
409: "Conflict",
|
||||
410: "Gone",
|
||||
411: "Length Required",
|
||||
412: "Precondition Failed",
|
||||
413: "Request Entity Too Large",
|
||||
414: "Request URI Too Long",
|
||||
415: "Unsupported Media Type",
|
||||
416: "Requested Range Not Satisfiable",
|
||||
417: "Expectation Failed",
|
||||
418: "I'm a teapot",
|
||||
422: "Unprocessable Entity",
|
||||
423: "Locked",
|
||||
424: "Failed Dependency",
|
||||
426: "Upgrade Required",
|
||||
428: "Precondition Required",
|
||||
429: "Too Many Requests",
|
||||
431: "Request Header Fields Too Large",
|
||||
451: "Unavailable For Legal Reasons",
|
||||
500: "Internal Server Error",
|
||||
501: "Not Implemented",
|
||||
502: "Bad Gateway",
|
||||
503: "Service Unavailable",
|
||||
504: "Gateway Timeout",
|
||||
505: "HTTP Version Not Supported",
|
||||
506: "Variant Also Negotiates",
|
||||
507: "Insufficient Storage",
|
||||
508: "Loop Detected",
|
||||
510: "Not Extended",
|
||||
511: "Network Authentication Required",
|
||||
}
|
124
types.go
124
types.go
|
@ -1,124 +0,0 @@
|
|||
// 🚀 Fiber is an Express.js inspired web framework written in Go with 💖
|
||||
// 📌 Please open an issue if you got suggestions or found a bug!
|
||||
// 🖥 Links: https://github.com/gofiber/fiber, https://fiber.wiki
|
||||
|
||||
// 🦸 Not all heroes wear capes, thank you to some amazing people
|
||||
// 💖 @valyala, @erikdubbelboer, @savsgio, @julienschmidt, @koddr
|
||||
|
||||
package fiber
|
||||
|
||||
const (
|
||||
contentTypeJSON = "application/json"
|
||||
contentTypeJs = "application/javascript"
|
||||
contentTypeXML = "application/xml"
|
||||
contentTypeOctetStream = "application/octet-stream"
|
||||
)
|
||||
|
||||
// https://github.com/nginx/nginx/blob/master/conf/mime.types
|
||||
var contentTypes = map[string]string{
|
||||
"html": "text/html",
|
||||
"htm": "text/html",
|
||||
"shtml": "text/html",
|
||||
"css": "text/css",
|
||||
"xml": "text/xml",
|
||||
"gif": "image/gif",
|
||||
"jpeg": "image/jpeg",
|
||||
"jpg": "image/jpeg",
|
||||
"js": "application/javascript",
|
||||
"atom": "application/atom+xml",
|
||||
"rss": "application/rss+xml",
|
||||
"mml": "text/mathml",
|
||||
"txt": "text/plain",
|
||||
"jad": "text/vnd.sun.j2me.app-descriptor",
|
||||
"wml": "text/vnd.wap.wml",
|
||||
"htc": "text/x-component",
|
||||
"png": "image/png",
|
||||
"svg": "image/svg+xml",
|
||||
"svgz": "image/svg+xml",
|
||||
"tif": "image/tiff",
|
||||
"tiff": "image/tiff",
|
||||
"wbmp": "image/vnd.wap.wbmp",
|
||||
"webp": "image/webp",
|
||||
"ico": "image/x-icon",
|
||||
"jng": "image/x-jng",
|
||||
"bmp": "image/x-ms-bmp",
|
||||
"woff": "font/woff",
|
||||
"woff2": "font/woff2",
|
||||
"jar": "application/java-archive",
|
||||
"war": "application/java-archive",
|
||||
"ear": "application/java-archive",
|
||||
"json": "application/json",
|
||||
"hqx": "application/mac-binhex40",
|
||||
"doc": "application/msword",
|
||||
"pdf": "application/pdf",
|
||||
"ps": "application/postscript",
|
||||
"eps": "application/postscript",
|
||||
"ai": "application/postscript",
|
||||
"rtf": "application/rtf",
|
||||
"m3u8": "application/vnd.apple.mpegurl",
|
||||
"kml": "application/vnd.google-earth.kml+xml",
|
||||
"kmz": "application/vnd.google-earth.kmz",
|
||||
"xls": "application/vnd.ms-excel",
|
||||
"eot": "application/vnd.ms-fontobject",
|
||||
"ppt": "application/vnd.ms-powerpoint",
|
||||
"odg": "application/vnd.oasis.opendocument.graphics",
|
||||
"odp": "application/vnd.oasis.opendocument.presentation",
|
||||
"ods": "application/vnd.oasis.opendocument.spreadsheet",
|
||||
"odt": "application/vnd.oasis.opendocument.text",
|
||||
"wmlc": "application/vnd.wap.wmlc",
|
||||
"7z": "application/x-7z-compressed",
|
||||
"cco": "application/x-cocoa",
|
||||
"jardiff": "application/x-java-archive-diff",
|
||||
"jnlp": "application/x-java-jnlp-file",
|
||||
"run": "application/x-makeself",
|
||||
"pl": "application/x-perl",
|
||||
"pm": "application/x-perl",
|
||||
"prc": "application/x-pilot",
|
||||
"pdb": "application/x-pilot",
|
||||
"rar": "application/x-rar-compressed",
|
||||
"rpm": "application/x-redhat-package-manager",
|
||||
"sea": "application/x-sea",
|
||||
"swf": "application/x-shockwave-flash",
|
||||
"sit": "application/x-stuffit",
|
||||
"tcl": "application/x-tcl",
|
||||
"tk": "application/x-tcl",
|
||||
"der": "application/x-x509-ca-cert",
|
||||
"pem": "application/x-x509-ca-cert",
|
||||
"crt": "application/x-x509-ca-cert",
|
||||
"xpi": "application/x-xpinstall",
|
||||
"xhtml": "application/xhtml+xml",
|
||||
"xspf": "application/xspf+xml",
|
||||
"zip": "application/zip",
|
||||
"bin": "application/octet-stream",
|
||||
"exe": "application/octet-stream",
|
||||
"dll": "application/octet-stream",
|
||||
"deb": "application/octet-stream",
|
||||
"dmg": "application/octet-stream",
|
||||
"iso": "application/octet-stream",
|
||||
"img": "application/octet-stream",
|
||||
"msi": "application/octet-stream",
|
||||
"msp": "application/octet-stream",
|
||||
"msm": "application/octet-stream",
|
||||
"mid": "audio/midi",
|
||||
"midi": "audio/midi",
|
||||
"kar": "audio/midi",
|
||||
"mp3": "audio/mpeg",
|
||||
"ogg": "audio/ogg",
|
||||
"m4a": "audio/x-m4a",
|
||||
"ra": "audio/x-realaudio",
|
||||
"3gpp": "video/3gpp",
|
||||
"3gp": "video/3gpp",
|
||||
"ts": "video/mp2t",
|
||||
"mp4": "video/mp4",
|
||||
"mpeg": "video/mpeg",
|
||||
"mpg": "video/mpeg",
|
||||
"mov": "video/quicktime",
|
||||
"webm": "video/webm",
|
||||
"flv": "video/x-flv",
|
||||
"m4v": "video/x-m4v",
|
||||
"mng": "video/x-mng",
|
||||
"asx": "video/x-ms-asf",
|
||||
"asf": "video/x-ms-asf",
|
||||
"wmv": "video/x-ms-wmv",
|
||||
"avi": "video/x-msvideo",
|
||||
}
|
179
utils.go
179
utils.go
|
@ -179,3 +179,182 @@ 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 }
|
||||
|
||||
var statusMessages = map[int]string{
|
||||
100: "Continue",
|
||||
101: "Switching Protocols",
|
||||
102: "Processing",
|
||||
200: "OK",
|
||||
201: "Created",
|
||||
202: "Accepted",
|
||||
203: "Non-Authoritative Information",
|
||||
204: "No Content",
|
||||
205: "Reset Content",
|
||||
206: "Partial Content",
|
||||
207: "Multi-Status",
|
||||
208: "Already Reported",
|
||||
226: "IM Used",
|
||||
300: "Multiple Choices",
|
||||
301: "Moved Permanently",
|
||||
302: "Found",
|
||||
303: "See Other",
|
||||
304: "Not Modified",
|
||||
305: "Use Proxy",
|
||||
306: "Switch Proxy",
|
||||
307: "Temporary Redirect",
|
||||
308: "Permanent Redirect",
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
402: "Payment Required",
|
||||
403: "Forbidden",
|
||||
404: "Not Found",
|
||||
405: "Method Not Allowed",
|
||||
406: "Not Acceptable",
|
||||
407: "Proxy Authentication Required",
|
||||
408: "Request Timeout",
|
||||
409: "Conflict",
|
||||
410: "Gone",
|
||||
411: "Length Required",
|
||||
412: "Precondition Failed",
|
||||
413: "Request Entity Too Large",
|
||||
414: "Request URI Too Long",
|
||||
415: "Unsupported Media Type",
|
||||
416: "Requested Range Not Satisfiable",
|
||||
417: "Expectation Failed",
|
||||
418: "I'm a teapot",
|
||||
422: "Unprocessable Entity",
|
||||
423: "Locked",
|
||||
424: "Failed Dependency",
|
||||
426: "Upgrade Required",
|
||||
428: "Precondition Required",
|
||||
429: "Too Many Requests",
|
||||
431: "Request Header Fields Too Large",
|
||||
451: "Unavailable For Legal Reasons",
|
||||
500: "Internal Server Error",
|
||||
501: "Not Implemented",
|
||||
502: "Bad Gateway",
|
||||
503: "Service Unavailable",
|
||||
504: "Gateway Timeout",
|
||||
505: "HTTP Version Not Supported",
|
||||
506: "Variant Also Negotiates",
|
||||
507: "Insufficient Storage",
|
||||
508: "Loop Detected",
|
||||
510: "Not Extended",
|
||||
511: "Network Authentication Required",
|
||||
}
|
||||
|
||||
const (
|
||||
contentTypeJSON = "application/json"
|
||||
contentTypeJs = "application/javascript"
|
||||
contentTypeXML = "application/xml"
|
||||
contentTypeOctetStream = "application/octet-stream"
|
||||
)
|
||||
|
||||
// https://github.com/nginx/nginx/blob/master/conf/mime.types
|
||||
var contentTypes = map[string]string{
|
||||
"html": "text/html",
|
||||
"htm": "text/html",
|
||||
"shtml": "text/html",
|
||||
"css": "text/css",
|
||||
"xml": "text/xml",
|
||||
"gif": "image/gif",
|
||||
"jpeg": "image/jpeg",
|
||||
"jpg": "image/jpeg",
|
||||
"js": "application/javascript",
|
||||
"atom": "application/atom+xml",
|
||||
"rss": "application/rss+xml",
|
||||
"mml": "text/mathml",
|
||||
"txt": "text/plain",
|
||||
"jad": "text/vnd.sun.j2me.app-descriptor",
|
||||
"wml": "text/vnd.wap.wml",
|
||||
"htc": "text/x-component",
|
||||
"png": "image/png",
|
||||
"svg": "image/svg+xml",
|
||||
"svgz": "image/svg+xml",
|
||||
"tif": "image/tiff",
|
||||
"tiff": "image/tiff",
|
||||
"wbmp": "image/vnd.wap.wbmp",
|
||||
"webp": "image/webp",
|
||||
"ico": "image/x-icon",
|
||||
"jng": "image/x-jng",
|
||||
"bmp": "image/x-ms-bmp",
|
||||
"woff": "font/woff",
|
||||
"woff2": "font/woff2",
|
||||
"jar": "application/java-archive",
|
||||
"war": "application/java-archive",
|
||||
"ear": "application/java-archive",
|
||||
"json": "application/json",
|
||||
"hqx": "application/mac-binhex40",
|
||||
"doc": "application/msword",
|
||||
"pdf": "application/pdf",
|
||||
"ps": "application/postscript",
|
||||
"eps": "application/postscript",
|
||||
"ai": "application/postscript",
|
||||
"rtf": "application/rtf",
|
||||
"m3u8": "application/vnd.apple.mpegurl",
|
||||
"kml": "application/vnd.google-earth.kml+xml",
|
||||
"kmz": "application/vnd.google-earth.kmz",
|
||||
"xls": "application/vnd.ms-excel",
|
||||
"eot": "application/vnd.ms-fontobject",
|
||||
"ppt": "application/vnd.ms-powerpoint",
|
||||
"odg": "application/vnd.oasis.opendocument.graphics",
|
||||
"odp": "application/vnd.oasis.opendocument.presentation",
|
||||
"ods": "application/vnd.oasis.opendocument.spreadsheet",
|
||||
"odt": "application/vnd.oasis.opendocument.text",
|
||||
"wmlc": "application/vnd.wap.wmlc",
|
||||
"7z": "application/x-7z-compressed",
|
||||
"cco": "application/x-cocoa",
|
||||
"jardiff": "application/x-java-archive-diff",
|
||||
"jnlp": "application/x-java-jnlp-file",
|
||||
"run": "application/x-makeself",
|
||||
"pl": "application/x-perl",
|
||||
"pm": "application/x-perl",
|
||||
"prc": "application/x-pilot",
|
||||
"pdb": "application/x-pilot",
|
||||
"rar": "application/x-rar-compressed",
|
||||
"rpm": "application/x-redhat-package-manager",
|
||||
"sea": "application/x-sea",
|
||||
"swf": "application/x-shockwave-flash",
|
||||
"sit": "application/x-stuffit",
|
||||
"tcl": "application/x-tcl",
|
||||
"tk": "application/x-tcl",
|
||||
"der": "application/x-x509-ca-cert",
|
||||
"pem": "application/x-x509-ca-cert",
|
||||
"crt": "application/x-x509-ca-cert",
|
||||
"xpi": "application/x-xpinstall",
|
||||
"xhtml": "application/xhtml+xml",
|
||||
"xspf": "application/xspf+xml",
|
||||
"zip": "application/zip",
|
||||
"bin": "application/octet-stream",
|
||||
"exe": "application/octet-stream",
|
||||
"dll": "application/octet-stream",
|
||||
"deb": "application/octet-stream",
|
||||
"dmg": "application/octet-stream",
|
||||
"iso": "application/octet-stream",
|
||||
"img": "application/octet-stream",
|
||||
"msi": "application/octet-stream",
|
||||
"msp": "application/octet-stream",
|
||||
"msm": "application/octet-stream",
|
||||
"mid": "audio/midi",
|
||||
"midi": "audio/midi",
|
||||
"kar": "audio/midi",
|
||||
"mp3": "audio/mpeg",
|
||||
"ogg": "audio/ogg",
|
||||
"m4a": "audio/x-m4a",
|
||||
"ra": "audio/x-realaudio",
|
||||
"3gpp": "video/3gpp",
|
||||
"3gp": "video/3gpp",
|
||||
"ts": "video/mp2t",
|
||||
"mp4": "video/mp4",
|
||||
"mpeg": "video/mpeg",
|
||||
"mpg": "video/mpeg",
|
||||
"mov": "video/quicktime",
|
||||
"webm": "video/webm",
|
||||
"flv": "video/x-flv",
|
||||
"m4v": "video/x-m4v",
|
||||
"mng": "video/x-mng",
|
||||
"asx": "video/x-ms-asf",
|
||||
"asf": "video/x-ms-asf",
|
||||
"wmv": "video/x-ms-wmv",
|
||||
"avi": "video/x-msvideo",
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package fiber
|
Loading…
Reference in New Issue