Merge remote-tracking branch 'upstream/master'

pull/6/head
Fenny 2020-02-03 13:22:14 +01:00
commit 9ddf4625c0
33 changed files with 861 additions and 191 deletions

8
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,8 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
custom: # Replace with a single custom sponsorship URL

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: "[🐞] "
labels: ""
assignees: ""
---
☝️ **Don't forget to add title above!** ☝️
**Your environment:**
- Fiber Web Framework [e.g. `1.2.3`]:
- OS [e.g. `macOS 10.14.6`]:
- Golang [e.g. `1.13.7`]:
## Describe the bug
A clear and concise description of what the bug is.
## To reproduce
Steps to reproduce the behavior:
1. Create func '...'
2. Run '...'
3. ...
4. See error
## Expected behavior
A clear and concise description of what you expected to happen.
### Screenshots
If applicable, add screenshots to help explain your problem.
### Additional context
Add any other context about the problem here.

View File

@ -0,0 +1,21 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[🔥] "
labels: ""
assignees: ""
---
☝️ **Don't forget to add title above!** ☝️
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

14
.github/config.yml vendored Normal file
View File

@ -0,0 +1,14 @@
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
# Comment to be posted to on first time issues
newIssueWelcomeComment: >
Thanks for opening your first issue here! 🎉 Be sure to follow the issue template!
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: >
Thanks for opening this pull request! 🎉 Please check out our contributing guidelines.
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: >
Congrats on merging your first pull request! 🎉 We here at behaviorbot are proud of you!

26
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,26 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
👋 Hello. Is this still relevant? If so, what is blocking it? Is there
anything you can do to help move it forward?
> This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.
# Comment to post when closing a stale Issue or Pull Request. Set to `false` to disable
closeComment: >
⚡️ This issue has been automatically closed because it has not had recent activity.

120
README.md
View File

@ -1,113 +1,155 @@
<p align="center"> # 🔌 Fiber Web Framework
<img height="150" src="https://gofiber.github.io/fiber/static/logo.jpg">
</p>
<!--
![](https://img.shields.io/github/issues/gofiber/fiber)
![](https://img.shields.io/github/stars/gofiber/fiber)
-->
# Fiber [![](https://img.shields.io/github/release/gofiber/fiber)](https://github.com/gofiber/fiber/releases) ![](https://img.shields.io/github/languages/top/gofiber/fiber) [![](https://godoc.org/github.com/gofiber/fiber?status.svg)](https://godoc.org/github.com/gofiber/fiber) ![](https://goreportcard.com/badge/github.com/gofiber/fiber) [![](https://img.shields.io/github/release/gofiber/fiber)](https://github.com/gofiber/fiber/releases) ![](https://img.shields.io/github/languages/top/gofiber/fiber) [![](https://godoc.org/github.com/gofiber/fiber?status.svg)](https://godoc.org/github.com/gofiber/fiber) ![](https://goreportcard.com/badge/github.com/gofiber/fiber) [![GitHub license](https://img.shields.io/github/license/gofiber/fiber.svg)](https://github.com/gofiber/fiber/blob/master/LICENSE) [![Join the chat at https://gitter.im/FiberGo/community](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/FiberGo/community)
**[Fiber](https://github.com/gofiber/fiber)** is an **[Express](https://expressjs.com/en/4x/api.html)** styled HTTP framework implementation running on **[Fasthttp](https://github.com/valyala/fasthttp)**, the **fastest** HTTP engine for **[Go](https://golang.org/doc/)**. The package make use of similar framework convention as they are in express. People switching from **[Node](https://nodejs.org/en/about/)** to **[Go](https://golang.org/doc/)** often end up in a bad learning curve to start building their webapps, this project is meant to **ease** things up for **fast** development, but with **zero memory allocation** and **performance** in mind. See **[API Documentation](https://gofiber.github.io/fiber/)** <img align="right" height="180px" src="docs/static/logo_320px_trans.png" alt="Fiber logo" />
**[Fiber](https://github.com/gofiber/fiber)** is an [Express](https://expressjs.com/en/4x/api.html)-styled HTTP web framework implementation running on [Fasthttp](https://github.com/valyala/fasthttp), the **fastest** HTTP engine for Go (Golang). The package make use of **similar framework convention** as they are in Express.
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, this project is meant to **ease** things up for **fast** development, but with **zero memory allocation** and **performance** in mind.
**In other languages:** <a href="README_RU.md"><img width="20px" src="docs/static/flags/ru.svg" alt="ru"/></a>
## API Documentation
📚 We created an extended API documentation (_including examples_), **[click here](https://gofiber.github.io/fiber/)**.
## Benchmark
[![](https://gofiber.github.io/fiber/static/benchmarks/benchmark.png)](https://gofiber.github.io/fiber/#/benchmarks) [![](https://gofiber.github.io/fiber/static/benchmarks/benchmark.png)](https://gofiber.github.io/fiber/#/benchmarks)
**[Click here to see all benchmark results](https://gofiber.github.io/fiber/#/benchmarks)**
👉 **[Click here](https://gofiber.github.io/fiber/#/benchmarks)** to see all benchmark results.
## Features ## Features
* Optimized for speed and low memory usage.
* Rapid Server-Side Programming - Optimized for speed and low memory usage
* Easy routing with parameters - Rapid Server-Side Programming
* Static files with custom prefix - Easy routing with parameters
* Middleware with Next support - Static files with custom prefix
* Express API endpoints - Middleware with Next support
* **[API Documentation](https://gofiber.github.io/fiber/)** - Express API endpoints
- [Extended documentation](https://gofiber.github.io/fiber/)
## Installing ## Installing
Assuming youve already installed **[Go](https://golang.org/doc/)**, install the **[Fiber](https://github.com/gofiber/fiber)** package by calling the following command:
```bash Assuming youve already installed Go `1.11+` 😉
$ go get -u github.com/gofiber/fiber
Install the [Fiber](https://github.com/gofiber/fiber) package by calling the following command:
```console
go get -u github.com/gofiber/fiber
``` ```
## Hello world ## Hello, world!
Embedded below is essentially the simplest Fiber app you can create.
```bash Embedded below is essentially the simplest Fiber app you can create:
$ create server.go
```
```go ```go
// server.go
package main package main
import "github.com/gofiber/fiber" import "github.com/gofiber/fiber"
func main() { func main() {
// Create new Fiber instance
app := fiber.New() app := fiber.New()
// Create new route with GET method
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
c.Send("Hello, World!") c.Send("Hello, World!")
}) })
// Start server on http://localhost:8080
app.Listen(8080) app.Listen(8080)
} }
``` ```
```bash
$ go run server.go Go to console and run:
```console
go run server.go
``` ```
Browse to **http://localhost:8080** and you should see `Hello, World!` on the page.
And now, browse to `http://localhost:8080` and you should see `Hello, World!` on the page! 🎉
## Static files ## Static files
To serve static files, use the [Static](https://gofiber.github.io/fiber/#/?id=static-files) method.
To serve static files, use the [Static](https://gofiber.github.io/fiber/#/?id=static-files) method:
```go ```go
package main package main
import "github.com/gofiber/fiber" import "github.com/gofiber/fiber"
func main() { func main() {
// Create new Fiber instance
app := fiber.New() app := fiber.New()
// Serve all static files on ./public folder
app.Static("./public") app.Static("./public")
// Start server on http://localhost:8080
app.Listen(8080) app.Listen(8080)
} }
``` ```
Now, you can load the files that are in the public directory: Now, you can load the files that are in the public directory:
```shell
```console
http://localhost:8080/hello.html http://localhost:8080/hello.html
http://localhost:8080/js/jquery.js http://localhost:8080/js/script.js
http://localhost:8080/css/style.css http://localhost:8080/css/style.css
``` ```
## Middleware ## Middleware
Middleware has never been so easy, just like express you call the Next() matching route function!
Middleware has never been so easy! Just like Express you call the `Next()` matching route function:
```go ```go
package main package main
import "github.com/gofiber/fiber" import "github.com/gofiber/fiber"
func main() { func main() {
// Create new Fiber instance
app := fiber.New() app := fiber.New()
// Define all used middlewares in Use()
app.Use(func(c *fiber.Ctx) { app.Use(func(c *fiber.Ctx) {
c.Write("Match anything!\n") c.Write("Match anything!\n")
c.Next() c.Next()
}) })
app.Use("/api", func(c *fiber.Ctx) { app.Use("/api", func(c *fiber.Ctx) {
c.Write("Match starting with /api\n") c.Write("Match starting with /api\n")
c.Next() c.Next()
}) })
app.Get("/api/user", func(c *fiber.Ctx) { app.Get("/api/user", func(c *fiber.Ctx) {
c.Write("Match exact path /api/user\n") c.Write("Match exact path /api/user\n")
}) })
// Start server on http://localhost:8080
app.Listen(8080) app.Listen(8080)
} }
``` ```
## API Documentation ## Project assistance
We created an extended API documentation including examples, **[click here](https://gofiber.github.io/fiber/)**
If you want to say «thank you» or/and support active development `gofiber/fiber`:
1. Add a GitHub Star to project.
2. Twit about project [on your Twitter](https://twitter.com/intent/tweet?text=%F0%9F%94%8C%20Fiber%20is%20an%20Express.js%20inspired%20Go%20web%20framework%20build%20on%20%F0%9F%9A%80%20Fasthttp%20https%3A%2F%2Fgithub.com%2Fgofiber%2Ffiber).
3. Help us to translate this `README` and [API Docs](https://gofiber.github.io/fiber/) to another language.
Thanks for your support! 😘 Together, we make `Fiber Web Framework` better every day.
## Stargazers over time
[![Stargazers over time](https://starchart.cc/gofiber/fiber.svg)](https://starchart.cc/gofiber/fiber)
## License ## License
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/edit/master/LICENSE).
*Caught a mistake? [Edit this page on GitHub!](https://github.com/gofiber/fiber/blob/master/README.md)*

156
README_RU.md Normal file
View File

@ -0,0 +1,156 @@
# 🔌 Веб фреймворк Fiber
[![](https://img.shields.io/github/release/gofiber/fiber)](https://github.com/gofiber/fiber/releases) ![](https://img.shields.io/github/languages/top/gofiber/fiber) [![](https://godoc.org/github.com/gofiber/fiber?status.svg)](https://godoc.org/github.com/gofiber/fiber) ![](https://goreportcard.com/badge/github.com/gofiber/fiber) [![GitHub license](https://img.shields.io/github/license/gofiber/fiber.svg)](https://github.com/gofiber/fiber/blob/master/LICENSE) [![Join the chat at https://gitter.im/FiberGo/community](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/FiberGo/community)
<img align="right" height="180px" src="docs/static/logo_320px_trans.png" alt="Fiber logo" />
**[Fiber](https://github.com/gofiber/fiber)** — это [Express](https://expressjs.com/en/4x/api.html)-подобный HTTP веб фреймворк, использующий всю мощь [Fasthttp](https://github.com/valyala/fasthttp), самого **быстрого** HTTP движка для Go (Golang). Мы используем **аналогичную** схему именования методов, как и у Express.
Разработчики, пришедшие из [Node.js](https://nodejs.org/en/about/) в [Go](https://golang.org/doc/) очень часто испытывают трудности при создании своих первых веб-приложений. Данный проект призван, в том числе, **облегчить** процесс перехода для таких разработчиков.
**На других языках:** <a href="README.md"><img width="20px" src="docs/static/flags/en.svg" alt="en"/></a>
## Документация по API
📚 Мы создали расширенную документацию по API (_включая примеры_), **[посмотреть](https://gofiber.github.io/fiber/)**.
## Бенчмарк
[![](https://gofiber.github.io/fiber/static/benchmarks/benchmark.png)](https://gofiber.github.io/fiber/#/benchmarks)
👉 **[Click here](https://gofiber.github.io/fiber/#/benchmarks)** to see all benchmark results.
## Особенности
- Оптимизирован для скорости и низкого использования памяти
- Быстрое Server-Side программирование
- Простая маршрутизация с параметрами
- Статические файлы с пользовательским префиксом
- Middleware с поддержкой `Next()`
- Endpoints, как у API Express
- [Расширенная документация](https://gofiber.github.io/fiber/)
## Установка
Предположим, вы уже установили Go `1.11+` 😉
Установит пакет [Fiber](https://github.com/gofiber/fiber) с помощью следующей команды в консоле:
```console
go get -u github.com/gofiber/fiber
```
## Hello, world!
Веб-приложение ниже, по сути, является самым простым приложением, которое вы можете создать:
```go
// server.go
package main
import "github.com/gofiber/fiber"
func main() {
// Создание нового инстанса Fiber
app := fiber.New()
// Создание маршрута с GET
app.Get("/", func(c *fiber.Ctx) {
c.Send("Hello, World!")
})
// Старт сервера на http://localhost:8080
app.Listen(8080)
}
```
Перейдите в консоль и запустите:
```console
go run server.go
```
А теперь, откройте в браузере адрес `http://localhost:8080`. Вы должы увидеть надпись `Hello, World!`! 🎉
## Статичные файлы
Для получения доступа к статичным файлам, используйте метод [Static](https://gofiber.github.io/fiber/#/?id=static-files):
```go
package main
import "github.com/gofiber/fiber"
func main() {
// Создание нового инстанса Fiber
app := fiber.New()
// Включение всех файлов в папке ./public для работы
app.Static("./public")
// Старт сервера на http://localhost:8080
app.Listen(8080)
}
```
Теперь вы можете получить доступ ко всем файлам, которые находятся в папке `./public`:
```console
http://localhost:8080/hello.html
http://localhost:8080/js/script.js
http://localhost:8080/css/style.css
```
## Middleware
Еще никогда работа с middleware не была настолько простой! Так же, как и в Express, вы должны вызывать метод `Next()` для дальнейшего следования по маршрутам роутера:
```go
package main
import "github.com/gofiber/fiber"
func main() {
// Создание нового инстанса Fiber
app := fiber.New()
// Определяем все необходимые middlewares
// с помощью метода Use()
app.Use(func(c *fiber.Ctx) {
c.Write("Match anything!\n")
c.Next()
})
app.Use("/api", func(c *fiber.Ctx) {
c.Write("Match starting with /api\n")
c.Next()
})
app.Get("/api/user", func(c *fiber.Ctx) {
c.Write("Match exact path /api/user\n")
})
// Старт сервера на http://localhost:8080
app.Listen(8080)
}
```
## Помощь проекту
Если вы хотите сказать «спасибо» и/или помочь активной разработке `gofiber/fiber`:
1. Добавьте звёздочку GitHub этому репозиторию.
2. Отправьте твит об этом проекте [в свой Twitter](https://twitter.com/intent/tweet?text=%F0%9F%94%8C%20Fiber%20is%20an%20Express.js%20inspired%20Go%20web%20framework%20build%20on%20%F0%9F%9A%80%20Fasthttp%20https%3A%2F%2Fgithub.com%2Fgofiber%2Ffiber).
3. Помогите нам перевести `README` и [Документацию по API](https://gofiber.github.io/fiber/) на другой язык.
Спасибо за поддержку! 😘 Вместе мы делаем `Fiber Web Framework` лучше каждый день.
## Звёздочки с течением времени
[![Stargazers over time](https://starchart.cc/gofiber/fiber.svg)](https://starchart.cc/gofiber/fiber)
## Лицензия
⚠️ _Обратите внимание:_ `gofiber/fiber` является свободным программным обеспечением с открытым исходным кодом, лицензируемым в соответствии с [MIT License](LICENSE).

View File

@ -13,6 +13,7 @@ import (
) )
const ( const (
// Version : Fiber version
Version = "1.2.3" Version = "1.2.3"
// https://play.golang.org/p/r6GNeV1gbH // https://play.golang.org/p/r6GNeV1gbH
banner = "" + banner = "" +
@ -40,7 +41,7 @@ type Fiber struct {
Prefork bool Prefork bool
child bool child bool
// Stores all routes // Stores all routes
routes []*route routes []*Route
} }
// Fasthttp settings // Fasthttp settings

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -13,23 +13,23 @@ import (
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )
// Ctx struct // Ctx : struct
type Ctx struct { type Ctx struct {
route *route route *Route
next bool next bool
params *[]string params *[]string
values []string values []string
Fasthttp *fasthttp.RequestCtx Fasthttp *fasthttp.RequestCtx
} }
// Cookie : // Cookie : struct
type Cookie struct { type Cookie struct {
Expire int // time.Unix(1578981376, 0) Expire int // time.Unix(1578981376, 0)
MaxAge int MaxAge int
Domain string Domain string
Path string Path string
HttpOnly bool HTTPOnly bool
Secure bool Secure bool
SameSite string SameSite string
} }

View File

@ -1,8 +1,11 @@
# Application # Application
The app instance conventionally denotes the Fiber application. The app instance conventionally denotes the Fiber application.
#### New #### New
Creates an new Fiber instance that we named "**app**". Creates an new Fiber instance that we named "**app**".
```go ```go
app := fiber.New() app := fiber.New()
// ... // ...
@ -12,7 +15,9 @@ app.Listen(8080)
``` ```
#### Server #### Server
Fiber by default does not send a [server header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server), but you can enable this by changing the server value. Fiber by default does not send a [server header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Server), but you can enable this by changing the server value.
```go ```go
app := fiber.New() app := fiber.New()
@ -23,7 +28,8 @@ app.Listen(8080)
``` ```
#### Banner #### Banner
When you launch your Fiber application, the console will print a banner containing the package version and listening port. This is enabled by default, disable it by setting the Banner value to false.
When you launch your Fiber application, the console will print a banner containing the package version and listening port. This is enabled by default, disable it by setting the Banner value to false.
![](https://i.imgur.com/96l7g9l.png) ![](https://i.imgur.com/96l7g9l.png)
@ -36,10 +42,12 @@ app.Listen(8080)
``` ```
#### Engine #### Engine
You can edit some of the Fasthttp server settings via the Fiber instance. You can edit some of the Fasthttp server settings via the Fiber instance.
Make sure that you set these settings before calling the [Listen](#listen) method. You can find the description of each value in [Fasthttp server settings](https://github.com/valyala/fasthttp/blob/master/server.go#L150) Make sure that you set these settings before calling the [Listen](#listen) method. You can find the description of each value in [Fasthttp server settings](https://github.com/valyala/fasthttp/blob/master/server.go#L150)
**Only change these settings if you know what you are doing.** **Only change these settings if you know what you are doing.**
```go ```go
app := fiber.New() app := fiber.New()
@ -68,13 +76,14 @@ app.Listen(8080)
``` ```
#### Prefork #### Prefork
Prefork enables use of the **[SO_REUSEPORT](https://lwn.net/Articles/542629/)** socket option, which is available in newer versions of many operating systems, including DragonFly BSD and Linux (kernel version 3.9 and later). This will spawn multiple go processes listening on the same port. Prefork enables use of the **[SO_REUSEPORT](https://lwn.net/Articles/542629/)** socket option, which is available in newer versions of many operating systems, including DragonFly BSD and Linux (kernel version 3.9 and later). This will spawn multiple go processes listening on the same port.
NGINX has a great article about [Socket Sharding](https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/), these pictures are taken from the same article. NGINX has a great article about [Socket Sharding](https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/), these pictures are taken from the same article.
<img src="https://cdn.wp.nginx.com/wp-content/uploads/2015/05/Slack-for-iOS-Upload-1-e1432652484191.png" style="width: 50%;float: left;"/> <img src="https://cdn.wp.nginx.com/wp-content/uploads/2015/05/Slack-for-iOS-Upload-1-e1432652484191.png" style="width: 50%;float: left;"/>
<img src="https://cdn.wp.nginx.com/wp-content/uploads/2015/05/Slack-for-iOS-Upload-e1432652376641.png" style="width: 50%;float: left;"/> <img src="https://cdn.wp.nginx.com/wp-content/uploads/2015/05/Slack-for-iOS-Upload-e1432652376641.png" style="width: 50%;float: left;"/>
<div style="clear:both"></div> <div style="clear:both"></div>
You can enable the **prefork** feature by adding the **-prefork** flag. You can enable the **prefork** feature by adding the **-prefork** flag.
@ -83,6 +92,7 @@ You can enable the **prefork** feature by adding the **-prefork** flag.
``` ```
Or enable the **Prefork** option in your app. Or enable the **Prefork** option in your app.
```go ```go
app := fiber.New() app := fiber.New()
@ -99,7 +109,9 @@ app.Listen(8080)
``` ```
#### Methods #### Methods
Routes an HTTP request, where METHOD is the [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) of the request, such as GET, PUT, POST, and so on capitalized. Thus, the actual methods are **app.Get()**, **app.Post()**, **app.Put()**, and so on. Routes an HTTP request, where METHOD is the [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) of the request, such as GET, PUT, POST, and so on capitalized. Thus, the actual methods are **app.Get()**, **app.Post()**, **app.Put()**, and so on.
```go ```go
// Function signature // Function signature
app.Get(handler func(*Ctx)) app.Get(handler func(*Ctx))
@ -123,36 +135,47 @@ app.Use(...) // Will only see wheter url starts with specified path without :par
``` ```
#### Static #### Static
To serve static files such as images, CSS files, and JavaScript files, replace your function handler with a file or directory string. To serve static files such as images, CSS files, and JavaScript files, replace your function handler with a file or directory string.
By default this method will send `index.html` files in response to a request on a directory. By default this method will send `index.html` files in response to a request on a directory.
```go ```go
// Function signature // Function signature
app.Static(root string) app.Static(root string)
app.Static(prefix, root string) app.Static(prefix, root string)
``` ```
For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public: For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public:
```go ```go
app.Static("./public") app.Static("./public")
``` ```
Now, you can load the files that are in the public directory: Now, you can load the files that are in the public directory:
```shell ```shell
http://localhost:8080/hello.html http://localhost:8080/hello.html
http://localhost:8080/js/jquery.js http://localhost:8080/js/jquery.js
http://localhost:8080/css/style.css http://localhost:8080/css/style.css
``` ```
To use multiple static assets directories, call the Static function multiple times: To use multiple static assets directories, call the Static function multiple times:
```go ```go
app.Static("./public") app.Static("./public")
app.Static("./files") app.Static("./files")
``` ```
?>For best results, use a reverse proxy cache like [NGINX](https://www.nginx.com/resources/wiki/start/topics/examples/reverseproxycachingexample/) to improve performance of serving static assets.
?>For best results, use a reverse proxy cache like [NGINX](https://www.nginx.com/resources/wiki/start/topics/examples/reverseproxycachingexample/) to improve performance of serving static assets.
To create a virtual path prefix (where the path does not actually exist in the file system) for files that are served by the express.static function, specify a mount path for the static directory, as shown below: To create a virtual path prefix (where the path does not actually exist in the file system) for files that are served by the express.static function, specify a mount path for the static directory, as shown below:
```go ```go
app.Static("/static", "./public") app.Static("/static", "./public")
``` ```
Now, you can load the files that are in the public directory from the /static path prefix. Now, you can load the files that are in the public directory from the /static path prefix.
```shell ```shell
http://localhost:8080/static/hello.html http://localhost:8080/static/hello.html
http://localhost:8080/static/js/jquery.js http://localhost:8080/static/js/jquery.js
@ -160,7 +183,9 @@ http://localhost:8080/static/css/style.css
``` ```
#### Listen #### Listen
Binds and listens for connections on the specified address. This can be a **INT** for port or **STRING** for address. To enable **TLS/HTTPS** you can append your **cert** and **key** path. Binds and listens for connections on the specified address. This can be a **INT** for port or **STRING** for address. To enable **TLS/HTTPS** you can append your **cert** and **key** path.
```go ```go
// Function signature // Function signature
app.Listen(address interface{}, tls ...string) app.Listen(address interface{}, tls ...string)
@ -175,5 +200,4 @@ app.Listen("127.0.0.1:8080")
app.Listen(443, "server.crt", "server.key") app.Listen(443, "server.crt", "server.key")
``` ```
_Caught a mistake? [Edit this page on GitHub!](https://github.com/gofiber/fiber/blob/master/docs/application.md)_
*Caught a mistake? [Edit this page on GitHub!](https://github.com/gofiber/fiber/blob/master/docs/application.md)*

View File

@ -1,16 +1,16 @@
# Benchmarks # Benchmarks
#### TechEmpower #### TechEmpower
* **CPU** Intel Xeon Gold 5120
* **MEM** 32GB
* **GO** go1.13.6 linux/amd64
* **OS** Linux
* **NET** Dedicated Cisco 10-gigabit Ethernet switch.
- **CPU** Intel Xeon Gold 5120
- **MEM** 32GB
- **GO** go1.13.6 linux/amd64
- **OS** Linux
- **NET** Dedicated Cisco 10-gigabit Ethernet switch.
Below you can see the results of tested go frameworks responding in plaintext. Below you can see the results of tested go frameworks responding in plaintext.
To view the list yourself, [Plaintext Go Results](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext&l=zijocf-1r). To view the list yourself, [Plaintext Go Results](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext&l=zijocf-1r).
To see all language frameworks, [Plaintext All Results](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext). To see all language frameworks, [Plaintext All Results](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext).
Plaintext Plaintext
[![](static/benchmarks/techempower-plaintext.png)](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext&l=zijocf-1r) [![](static/benchmarks/techempower-plaintext.png)](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=plaintext&l=zijocf-1r)
@ -31,14 +31,15 @@ Data updates
[![](static/benchmarks/techempower-updates.png)](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=update&l=zijocf-1r) [![](static/benchmarks/techempower-updates.png)](https://www.techempower.com/benchmarks/#section=test&runid=350f0783-cc9b-4259-9831-28987799782a&hw=ph&test=update&l=zijocf-1r)
#### Go-Web #### Go-Web
[go-web-framework-benchmark](https://github.com/smallnest/go-web-framework-benchmark) [go-web-framework-benchmark](https://github.com/smallnest/go-web-framework-benchmark)
* **CPU** Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz - **CPU** Intel(R) Xeon(R) Gold 6140 CPU @ 2.30GHz
* **MEM** 4GB - **MEM** 4GB
* **GO** go1.13.6 linux/amd64 - **GO** go1.13.6 linux/amd64
* **OS** Linux - **OS** Linux
The first test case is to mock 0 ms, 10 ms, 100 ms, 500 ms processing time in handlers. The first test case is to mock 0 ms, 10 ms, 100 ms, 500 ms processing time in handlers.
![](static/benchmarks/benchmark.png) ![](static/benchmarks/benchmark.png)
@ -68,8 +69,8 @@ If we enable http pipelining, test result as below:
![](static/benchmarks/concurrency-pipeline.png) ![](static/benchmarks/concurrency-pipeline.png)
<!-- CPU-Bound Test <!-- CPU-Bound Test
This benchmark is outdated This benchmark is outdated
![](static/benchmarks/cpubound_benchmark.png) --> ![](static/benchmarks/cpubound_benchmark.png) -->
*Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/benchmarks.md)* _Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/benchmarks.md)_

View File

@ -1,8 +1,11 @@
# Context # Context
The ctx object represents the HTTP request and response and has methods for the request query string, parameters, body, HTTP headers, and so on. In this documentation and by convention, the context is always referred to as c but its actual name is determined by the parameters to the callback function in which youre working. The ctx object represents the HTTP request and response and has methods for the request query string, parameters, body, HTTP headers, and so on. In this documentation and by convention, the context is always referred to as c but its actual name is determined by the parameters to the callback function in which youre working.
#### Accepts #### Accepts
Checks if the specified content types are acceptable, based on the requests Accept HTTP header field. You can use an extention or content-type format Checks if the specified content types are acceptable, based on the requests Accept HTTP header field. You can use an extention or content-type format
```go ```go
// Function signature // Function signature
c.Accepts(types ...string) string c.Accepts(types ...string) string
@ -31,7 +34,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### AcceptsCharsets #### AcceptsCharsets
Returns the first accepted charset of the specified character sets, based on the requests Accept-Charset HTTP header field Returns the first accepted charset of the specified character sets, based on the requests Accept-Charset HTTP header field
```go ```go
// Function signature // Function signature
c.AcceptsCharsets(charsets ...string) string c.AcceptsCharsets(charsets ...string) string
@ -50,9 +55,10 @@ app.Get("/", func(c *fiber.Ctx) {
}) })
``` ```
#### AcceptsEncodings #### AcceptsEncodings
Returns the first accepted encoding of the specified encodings, based on the requests Accept-Encoding HTTP header field. Returns the first accepted encoding of the specified encodings, based on the requests Accept-Encoding HTTP header field.
```go ```go
// Function signature // Function signature
c.AcceptsEncodings(encodings ...string) string c.AcceptsEncodings(encodings ...string) string
@ -72,7 +78,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### AcceptsLanguages #### AcceptsLanguages
Returns the first accepted language of the specified languages, based on the requests Accept-Language HTTP header field. Returns the first accepted language of the specified languages, based on the requests Accept-Language HTTP header field.
```go ```go
// Function signature // Function signature
c.AcceptsLanguages(languages ...string) string c.AcceptsLanguages(languages ...string) string
@ -92,7 +100,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Append #### Append
Appends the specified value to the HTTP response header field. If the header is not already set, it creates the header with the specified value. The value parameter must be a string. Appends the specified value to the HTTP response header field. If the header is not already set, it creates the header with the specified value. The value parameter must be a string.
```go ```go
// Function signature // Function signature
c.Append(field, values ...string) c.Append(field, values ...string)
@ -113,7 +123,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Attachment #### Attachment
Sets the HTTP response [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) header field to “attachment”. If a filename is given, then it sets the Content-Type based on the extension name via (Type)[#type], and sets the Content-Disposition “filename=” parameter.
Sets the HTTP response [Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition) header field to “attachment”. If a filename is given, then it sets the Content-Type based on the extension name via [Type](#type), and sets the Content-Disposition “filename=” parameter.
```go ```go
// Function signature // Function signature
c.Attachment(file ...string) c.Attachment(file ...string)
@ -129,24 +141,28 @@ app.Get("/", func(c *fiber.Ctx) {
}) })
``` ```
#### BaseUrl #### BaseURL
#### AcceptsLanguages #### AcceptsLanguages
Returns the base URL, protocol and hostname combined. Returns the base URL, protocol and hostname combined.
```go ```go
// Function signature // Function signature
c.BaseUrl() bool c.BaseURL() bool
// Example // Example
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
// http://webtech.oregonstate.edu/faq/page/2?sort=date // http://webtech.oregonstate.edu/faq/page/2?sort=date
c.BaseUrl() c.BaseURL()
// => "http://webtech.oregonstate.edu" // => "http://webtech.oregonstate.edu"
}) })
``` ```
#### BasicAuth #### BasicAuth
BasicAuth returns the username and password provided in the request's Authorization header, if the request uses [HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). BasicAuth returns the username and password provided in the request's Authorization header, if the request uses [HTTP Basic Authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
```go ```go
// Function signature // Function signature
c.BasicAuth() (user, pass string, ok bool) c.BasicAuth() (user, pass string, ok bool)
@ -167,10 +183,12 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Body #### Body
Contains the raw post body submitted in the request. Contains the raw post body submitted in the request.
Calling a key in body returns a string value if exist or you loop trough the body params using a key value function callback. Calling a key in body returns a string value if exist or you loop trough the body params using a key value function callback.
The following example shows how to use the body function. The following example shows how to use the body function.
```go ```go
// Function signature // Function signature
c.Body() string c.Body() string
@ -190,14 +208,16 @@ app.Post("/", func(c *fiber.Ctx) {
// Loop trough all body params // Loop trough all body params
c.Body(func(key string, val string) { c.Body(func(key string, val string) {
fmt.Printl(key, val) fmt.Printl(key, val)
// => "user" "john" // => "user" "john"
}) })
}) })
``` ```
#### ClearCookie #### ClearCookie
Clears all client cookies or a specific cookie by name by setting the expire date in the past. Clears all client cookies or a specific cookie by name by setting the expire date in the past.
```go ```go
// Function signature // Function signature
c.ClearCookie() c.ClearCookie()
@ -217,7 +237,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Cookie #### Cookie
Sets cookie name to value, the third options parameter is not implemented yet. Sets cookie name to value, the third options parameter is not implemented yet.
```go ```go
// Function signature // Function signature
c.Cookie(name, value string) c.Cookie(name, value string)
@ -259,7 +281,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Cookies #### Cookies
Get cookies Get cookies
```go ```go
// Function signature // Function signature
c.Cookies() string c.Cookies() string
@ -287,7 +311,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Download #### Download
Transfers the file at path as an “attachment”. Typically, browsers will prompt the user for download. By default, the Content-Disposition header “filename=” parameter is path (this typically appears in the browser dialog). Override this default with the filename parameter. Transfers the file at path as an “attachment”. Typically, browsers will prompt the user for download. By default, the Content-Disposition header “filename=” parameter is path (this typically appears in the browser dialog). Override this default with the filename parameter.
```go ```go
// Function signature // Function signature
c.Download(path string) c.Download(path string)
@ -304,11 +330,14 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### !End #### !End
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Fasthttp #### Fasthttp
You can still access and use all Fasthttp methods and properties. You can still access and use all Fasthttp methods and properties.
Please read the [Fasthttp Documentation](https://godoc.org/github.com/valyala/fasthttp) for more information Please read the [Fasthttp Documentation](https://godoc.org/github.com/valyala/fasthttp) for more information
```go ```go
// Function signature // Function signature
c.Fasthttp... c.Fasthttp...
@ -324,6 +353,7 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Format #### Format
Performs content-negotiation on the Accept HTTP header. It uses [Accepts](#accepts) to select a proper format. If the header is not specified or there is no proper format, text/plain is used. Performs content-negotiation on the Accept HTTP header. It uses [Accepts](#accepts) to select a proper format. If the header is not specified or there is no proper format, text/plain is used.
```go ```go
@ -348,7 +378,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### FormFile #### FormFile
MultipartForm files can be retrieved by name, the first file from the given key is returned. MultipartForm files can be retrieved by name, the first file from the given key is returned.
```go ```go
// Function signature // Function signature
c.FormFile(name string) (*multipart.FileHeader, error) c.FormFile(name string) (*multipart.FileHeader, error)
@ -367,7 +399,9 @@ app.Post("/", func(c *fiber.Ctx) {
``` ```
#### FormValue #### FormValue
MultipartForm values can be retrieved by name, the first value from the given key is returned. MultipartForm values can be retrieved by name, the first value from the given key is returned.
```go ```go
// Function signature // Function signature
c.FormValue(name string) string c.FormValue(name string) string
@ -381,10 +415,13 @@ app.Post("/", func(c *fiber.Ctx) {
``` ```
#### !Fresh #### !Fresh
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Get #### Get
Returns the HTTP response header specified by field. The match is case-insensitive. Returns the HTTP response header specified by field. The match is case-insensitive.
```go ```go
// Function signature // Function signature
c.Get(field string) string c.Get(field string) string
@ -403,10 +440,13 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### !HeadersSent #### !HeadersSent
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Hostname #### Hostname
Contains the hostname derived from the Host HTTP header. Contains the hostname derived from the Host HTTP header.
```go ```go
// Function signature // Function signature
c.Hostname() string c.Hostname() string
@ -420,7 +460,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Ip #### Ip
Contains the remote IP address of the request. Contains the remote IP address of the request.
```go ```go
// Function signature // Function signature
c.Ip() string c.Ip() string
@ -433,7 +475,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Ips #### Ips
contains an array of IP addresses specified in the X-Forwarded-For request header. contains an array of IP addresses specified in the X-Forwarded-For request header.
```go ```go
// Function signature // Function signature
c.Ips() []string c.Ips() []string
@ -447,7 +491,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Is #### Is
Returns the matching content type if the incoming requests “Content-Type” HTTP header field matches the MIME type specified by the type parameter. If the request has no body, returns false. Returns the matching content type if the incoming requests “Content-Type” HTTP header field matches the MIME type specified by the type parameter. If the request has no body, returns false.
```go ```go
// Function signature // Function signature
c.Is(typ string) bool c.Is(typ string) bool
@ -455,22 +501,24 @@ c.Is(typ string) bool
// Example // Example
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
// Content-Type: text/html; charset=utf-8 // Content-Type: text/html; charset=utf-8
c.Is("html") c.Is("html")
// => true // => true
c.Is(".html") c.Is(".html")
// => true // => true
c.Is("json") c.Is("json")
// => false // => false
}) })
``` ```
#### Json #### JSON
Converts any interface or string to json using [Jsoniter](https://github.com/json-iterator/go), this function also sets the content header to application/json. Converts any interface or string to json using [Jsoniter](https://github.com/json-iterator/go), this function also sets the content header to application/json.
```go ```go
// Function signature // Function signature
c.Json(v interface{}) error c.JSON(v interface{}) error
// Example // Example
type SomeStruct struct { type SomeStruct struct {
@ -484,90 +532,98 @@ app.Get("/json", func(c *fiber.Ctx) {
Name: "Grame", Name: "Grame",
Age: 20, Age: 20,
} }
c.Json(data) c.JSON(data)
// => "{"Name": "Grame", "Age": 20}" // => "{"Name": "Grame", "Age": 20}"
c.Json("Hello, World!") c.JSON("Hello, World!")
// => "Hello, World!" // => "Hello, World!"
}) })
app.Listen(8080) app.Listen(8080)
``` ```
Or with error checking Or with error checking
```go ```go
app.Get("/json", func(c *fiber.Ctx) { app.Get("/json", func(c *fiber.Ctx) {
data := SomeStruct{ data := SomeStruct{
Name: "Grame", Name: "Grame",
Age: 20, Age: 20,
} }
if err := c.Json(data); err != nil { if err := c.JSON(data); err != nil {
c.Status(500).Send("Bad Request") c.Status(500).Send("Bad Request")
} }
// => "{"Name": "Grame", "Age": 20}" // => "{"Name": "Grame", "Age": 20}"
}) })
``` ```
#### JsonBytes #### JSONBytes
This function accepts raw []byte bodies and sets the content header to application/json. This function is used if you do not need type assertion. This function accepts raw []byte bodies and sets the content header to application/json. This function is used if you do not need type assertion.
```go ```go
// Function signature // Function signature
c.Json(json []byte) c.JSON(json []byte)
// Example // Example
app := fiber.New() app := fiber.New()
app.Get("/json", func(c *fiber.Ctx) { app.Get("/json", func(c *fiber.Ctx) {
c.JsonBytes([]byte(`"{"hello": "world"}"`)) c.JSONBytes([]byte(`"{"hello": "world"}"`))
}) })
app.Listen(8080) app.Listen(8080)
``` ```
#### JSONP
#### Jsonp Sends a JSON response with JSONP support. This method is identical to [JSON()](#json), except that it opts-in to JSONP callback support.
Sends a JSON response with JSONP support. This method is identical to [Json()](#json), except that it opts-in to JSONP callback support.
By default, the JSONP callback name is simply callback. Override this by passing a named string in the function. By default, the JSONP callback name is simply callback. Override this by passing a named string in the function.
```go ```go
// Function signature // Function signature
c.Jsonp(v interface{}) error c.JSONP(v interface{}) error
c.Jsonp(v interface{}, callback string) error c.JSONP(v interface{}, callback string) error
// Example // Example
type JsonStruct struct { type SomeStruct struct {
name string name string
age uint8 age uint8
} }
app := fiber.New() app := fiber.New()
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
data := JsonStruct{ data := SomeStruct{
name: "Grame", name: "Grame",
age: 20, age: 20,
} }
c.Jsonp(data) c.JSONP(data)
// => callback({"name": "Grame", "age": 20}) // => callback({"name": "Grame", "age": 20})
c.Jsonp(data, "customFunc") c.JSONP(data, "customFunc")
// => customFunc({"name": "Grame", "age": 20}) // => customFunc({"name": "Grame", "age": 20})
}) })
app.Listen(8080) app.Listen(8080)
``` ```
#### JsonString #### JSONString
This function accepts raw string body and sets the content header to application/json. This function is used if you do not need type assertion. This function accepts raw string body and sets the content header to application/json. This function is used if you do not need type assertion.
```go ```go
// Function signature // Function signature
c.Json(json string) c.JSON(json string)
// Example // Example
app := fiber.New() app := fiber.New()
app.Get("/json", func(c *fiber.Ctx) { app.Get("/json", func(c *fiber.Ctx) {
c.JsonString(`"{"hello": "world"}"`) c.JSONString(`"{"hello": "world"}"`)
}) })
app.Listen(8080) app.Listen(8080)
``` ```
#### Links #### Links
Joins the links followed by the propery to populate the responses Link HTTP header field. Joins the links followed by the propery to populate the responses Link HTTP header field.
```go ```go
// Function signature // Function signature
c.Links(link ...string) c.Links(link ...string)
@ -584,9 +640,11 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Locals #### Locals
A function that stores string variables scoped to the request, and therefore available only to the routes that match the request.
A function that stores string variables scoped to the request, and therefore available only to the routes that match the request.
This is usefull if you want to pass some specific values to the next middleware. This is usefull if you want to pass some specific values to the next middleware.
```go ```go
// Function signature // Function signature
c.Locals(key string) c.Locals(key string)
@ -608,6 +666,7 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
You can put any type inside the locals, don't forget to convert it back when you are using the variable You can put any type inside the locals, don't forget to convert it back when you are using the variable
```go ```go
type JSON struct { type JSON struct {
Message string `json:"message"` Message string `json:"message"`
@ -627,7 +686,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Location #### Location
Sets the response Location HTTP header to the specified path parameter. Sets the response Location HTTP header to the specified path parameter.
```go ```go
// Function signature // Function signature
c.Location(path string) c.Location(path string)
@ -640,7 +701,9 @@ app.Post("/", func(c *fiber.Ctx) {
``` ```
#### Method #### Method
Contains a string corresponding to the HTTP method of the request: GET, POST, PUT, and so on. Contains a string corresponding to the HTTP method of the request: GET, POST, PUT, and so on.
```go ```go
// Function signature // Function signature
c.Method() string c.Method() string
@ -653,9 +716,11 @@ app.Post("/", func(c *fiber.Ctx) {
``` ```
#### MultipartForm #### MultipartForm
To access multipart form entries, you can parse the binary with .MultipartForm(). To access multipart form entries, you can parse the binary with .MultipartForm().
This returns a map[string][]string, so given a key the value will be a string slice. This returns a map[string][]string, so given a key the value will be a string slice.
So accepting multiple files or values is easy, as shown below! So accepting multiple files or values is easy, as shown below!
```go ```go
// Function signature // Function signature
c.MultipartForm() (*multipart.Form, error) c.MultipartForm() (*multipart.Form, error)
@ -688,7 +753,9 @@ app.Post("/", func(c *fiber.Ctx) {
``` ```
#### Next #### Next
When Next() is called, it executes the next function in the stack that matches the current route. When Next() is called, it executes the next function in the stack that matches the current route.
```go ```go
// Function signature // Function signature
c.Next() c.Next()
@ -708,22 +775,26 @@ app.Get("/", func(c *fiber.Ctx) {
}) })
``` ```
#### OriginalUrl #### OriginalURL
Contains the original request URL. Contains the original request URL.
```go ```go
// Function signature // Function signature
c.OriginalUrl() string c.OriginalURL() string
// Example // Example
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
// GET /search?q=something // GET /search?q=something
c.OriginalUrl() c.OriginalURL()
// => '/search?q=something' // => '/search?q=something'
}) })
``` ```
#### Params #### Params
This method can be used to get the route parameters. For example, if you have the route /user/:name, then the “name” property is available as c.Params("name"). This method defaults "". This method can be used to get the route parameters. For example, if you have the route /user/:name, then the “name” property is available as c.Params("name"). This method defaults "".
```go ```go
// Function signature // Function signature
c.Params(param string) string c.Params(param string) string
@ -737,7 +808,9 @@ app.Get("/user/:name", func(c *fiber.Ctx) {
``` ```
#### Path #### Path
Contains the path part of the request URL. Contains the path part of the request URL.
```go ```go
// Function signature // Function signature
c.Path() string c.Path() string
@ -751,6 +824,7 @@ app.Get("/users", func(c *fiber.Ctx) {
``` ```
#### Protocol #### Protocol
Contains the request protocol string: either http or (for TLS requests) https. Contains the request protocol string: either http or (for TLS requests) https.
```go ```go
@ -763,8 +837,11 @@ app.Get("/", func(c *fiber.Ctx) {
// => "http" // => "http"
}) })
``` ```
#### Query #### Query
This property is an object containing a property for each query string parameter in the route. If there is no query string, it returns an empty string This property is an object containing a property for each query string parameter in the route. If there is no query string, it returns an empty string
```go ```go
// Function signature // Function signature
c.Query(parameter string) string c.Query(parameter string) string
@ -782,10 +859,13 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### !Range #### !Range
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Redirect #### Redirect
Redirects to the URL derived from the specified path, with specified status, a positive integer that corresponds to an HTTP status code . If not specified, status defaults to “302 “Found”. Redirects to the URL derived from the specified path, with specified status, a positive integer that corresponds to an HTTP status code . If not specified, status defaults to “302 “Found”.
```go ```go
// Function signature // Function signature
c.Redirect(path string) c.Redirect(path string)
@ -801,11 +881,14 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### !Render #### !Render
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Route #### Route
Contains the currently-matched route struct, **only use this for debugging**. Contains the currently-matched route struct, **only use this for debugging**.
It returns an anonymous struct as shown below. It returns an anonymous struct as shown below.
```go ```go
// Function signature // Function signature
c.Route() struct { c.Route() struct {
@ -830,8 +913,8 @@ app.Post("/:api?", func(c *fiber.Ctx) {
}) })
``` ```
#### SaveFile #### SaveFile
This function is used to save any multipart file to disk. This function is used to save any multipart file to disk.
You can see a working example here: [Multiple file upload](#multipartform) You can see a working example here: [Multiple file upload](#multipartform)
@ -841,6 +924,7 @@ c.SaveFile(fh *multipart.FileHeader, path string)
``` ```
#### Secure #### Secure
A Boolean property that is true if a TLS connection is established. A Boolean property that is true if a TLS connection is established.
```go ```go
@ -852,9 +936,11 @@ c.Protocol() == "https"
``` ```
#### Send #### Send
Sends the HTTP response. Sends the HTTP response.
The Send parameters can be of any type The Send parameters can be of any type
```go ```go
// Function signature // Function signature
c.Send(body ...interface{}) c.Send(body ...interface{})
@ -873,8 +959,10 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### SendBytes #### SendBytes
Same as Send() but without type assertion. Same as Send() but without type assertion.
I suggest using this in production for optimal performance. I suggest using this in production for optimal performance.
```go ```go
// Function signature // Function signature
c.SendBytes(body []byte) c.SendBytes(body []byte)
@ -886,7 +974,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### SendFile #### SendFile
Transfers the file at the given path. Sets the Content-Type response HTTP header field based on the filenames extension.
Transfers the file at the given path. Sets the Content-Type response HTTP header field based on the filenames extension.
```go ```go
// Function signature // Function signature
c.SendFile(path string) c.SendFile(path string)
@ -902,7 +992,9 @@ app.Get("/not-found", func(c *fiber.Ctx) {
``` ```
#### SendStatus #### SendStatus
Sets the status code, but also the correct status message in the body if the response body is still empty. You can find all status codes and messages in [status.go](https://github.com/gofiber/fiber/blob/master/status.go) Sets the status code, but also the correct status message in the body if the response body is still empty. You can find all status codes and messages in [status.go](https://github.com/gofiber/fiber/blob/master/status.go)
```go ```go
// Function signature // Function signature
c.SendStatus(status int) c.SendStatus(status int)
@ -921,8 +1013,10 @@ app.Get("/not-found", func(c *fiber.Ctx) {
``` ```
#### SendString #### SendString
Same as Send() but without type assertion. Same as Send() but without type assertion.
I suggest using this in production for optimal performance. I suggest using this in production for optimal performance.
```go ```go
// Function signature // Function signature
c.SendString(body string) c.SendString(body string)
@ -934,7 +1028,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Set #### Set
Sets the responses HTTP header field to value. To set multiple fields at once, pass an object as the parameter. Sets the responses HTTP header field to value. To set multiple fields at once, pass an object as the parameter.
```go ```go
// Function signature // Function signature
c.Set(key, value string) c.Set(key, value string)
@ -947,13 +1043,17 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### !SignedCookies #### !SignedCookies
!> Planned for v2.0.0 !> Planned for v2.0.0
#### !Stale #### !Stale
!> Planned for v2.0.0 !> Planned for v2.0.0
#### Status #### Status
Sets the HTTP status for the response. It is a chainable alias of Nodes response.statusCode. Sets the HTTP status for the response. It is a chainable alias of Nodes response.statusCode.
```go ```go
// Function signature // Function signature
c.Status(status int) c.Status(status int)
@ -967,8 +1067,10 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Subdomains #### Subdomains
An array of subdomains in the domain name of the request. An array of subdomains in the domain name of the request.
The application property subdomain offset, which defaults to 2, is used for determining the beginning of the subdomain segments. The application property subdomain offset, which defaults to 2, is used for determining the beginning of the subdomain segments.
```go ```go
// Function signature // Function signature
c.Subdomains() []string c.Subdomains() []string
@ -982,7 +1084,9 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Type #### Type
Sets the Content-Type HTTP header to the MIME type listed [here](https://github.com/nginx/nginx/blob/master/conf/mime.types) specified by the file extension. Sets the Content-Type HTTP header to the MIME type listed [here](https://github.com/nginx/nginx/blob/master/conf/mime.types) specified by the file extension.
```go ```go
// Function signature // Function signature
c.Type(typ string) string c.Type(typ string) string
@ -1004,9 +1108,11 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Vary #### Vary
Adds the given header field to the Vary response header of res. This can be a single field, or multiple fields. Adds the given header field to the Vary response header of res. This can be a single field, or multiple fields.
This will append the header if not already listed, otherwise leaves it listed in the current location. This will append the header if not already listed, otherwise leaves it listed in the current location.
```go ```go
// Function signature // Function signature
c.Vary(field ...string) c.Vary(field ...string)
@ -1033,9 +1139,11 @@ app.Get("/", func(c *fiber.Ctx) {
``` ```
#### Write #### Write
Appends to the HTTP response. Appends to the HTTP response.
The Write parameter can be any type The Write parameter can be any type
```go ```go
// Function signature // Function signature
c.Write(bodies ...interface{}) c.Write(bodies ...interface{})
@ -1056,24 +1164,28 @@ app.Get("/", func(c *fiber.Ctx) {
}) })
``` ```
#### Xhr #### XHR
A Boolean property that is true if the requests **X-Requested-With** header field is **XMLHttpRequest**, indicating that the request was issued by a client library such as [jQuery](https://api.jquery.com/jQuery.ajax/). A Boolean property that is true if the requests **X-Requested-With** header field is **XMLHttpRequest**, indicating that the request was issued by a client library such as [jQuery](https://api.jquery.com/jQuery.ajax/).
```go ```go
// Function signature // Function signature
c.Xhr() bool c.XHR() bool
// Example // Example
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
c.Xhr() c.XHR()
// => true // => true
}) })
``` ```
#### Xml #### XML
Xml sets the header to "application/xml" and marshals your interface to xml.
XML sets the header to "application/xml" and marshals your interface to xml.
```go ```go
// Function signature // Function signature
c.Xml(xml interface{}) error c.XML(xml interface{}) error
// Example // Example
type person struct { type person struct {
@ -1083,7 +1195,7 @@ type person struct {
app := fiber.New() app := fiber.New()
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
c.Xml(person{"John", 50}) c.XML(person{"John", 50})
// => Content-Type: application/xml // => Content-Type: application/xml
// => <person><name>John</name><stars>50</stars></person> // => <person><name>John</name><stars>50</stars></person>
@ -1092,4 +1204,4 @@ app.Listen(8080)
``` ```
*Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/context.md)* _Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/context.md)_

View File

@ -1,8 +1,8 @@
# Examples # Examples
#### Multiple File Upload #### Multiple File Upload
```go
```go
package main package main
import "github.com/fenny/fiber" import "github.com/fenny/fiber"
@ -25,7 +25,9 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
#### 404 Handling #### 404 Handling
```go ```go
package main package main
@ -43,7 +45,9 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
#### Static Caching #### Static Caching
```go ```go
package main package main
@ -61,7 +65,9 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
#### Enable CORS #### Enable CORS
```go ```go
package main package main
@ -82,7 +88,9 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
#### Returning JSON #### Returning JSON
```go ```go
package main package main
@ -101,7 +109,7 @@ func main() {
Name: "John", `json:"name"` Name: "John", `json:"name"`
Age: 20, `json:"age"` Age: 20, `json:"age"`
} }
err := c.Json(data) err := c.JSON(data)
if err != nil { if err != nil {
c.SendStatus(500) c.SendStatus(500)
} }
@ -110,7 +118,9 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
#### TLS/HTTPS #### TLS/HTTPS
```go ```go
package main package main
@ -127,4 +137,4 @@ func main() {
} }
``` ```
*Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/examples.md)* _Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/examples.md)_

View File

@ -4,7 +4,7 @@ AcceptsEncodings
AcceptsLanguages AcceptsLanguages
Append Append
Attachment Attachment
BaseUrl BaseURL
BasicAuth BasicAuth
Body Body
ClearCookie ClearCookie
@ -19,18 +19,20 @@ Fresh
Get Get
HeadersSent HeadersSent
Hostname Hostname
Ip IP
Ips Ips
Is Is
Json JSON
Jsonp JSONP
JSONString
JSONBytes
Links Links
Locals Locals
Location Location
Method Method
MultipartForm MultipartForm
Next Next
OriginalUrl OriginalURL
Params Params
Path Path
Protocol Protocol
@ -54,5 +56,5 @@ Status
Subdomains Subdomains
Type Type
Vary Vary
Xhr XHR
Xml XML

View File

@ -1,27 +1,35 @@
<img src="static/logo.jpg" width="150" alt="accessibility text"><br><br> <img src="static/logo.jpg" width="150" alt="accessibility text"><br><br>
[![Latest Release](https://img.shields.io/github/release/gofiber/fiber.svg)](https://github.com/gofiber/fiber/releases/latest) [![Latest Release](https://img.shields.io/github/release/gofiber/fiber.svg)](https://github.com/gofiber/fiber/releases/latest)
[![GoDoc](https://godoc.org/github.com/gofiber/fiber?status.svg)](http://godoc.org/github.com/gofiber/fiber) [![GoDoc](https://godoc.org/github.com/gofiber/fiber?status.svg)](http://godoc.org/github.com/gofiber/fiber)
[![Go Report](https://goreportcard.com/badge/github.com/gofiber/fiber)](https://goreportcard.com/report/github.com/gofiber/fiber) [![Go Report](https://goreportcard.com/badge/github.com/gofiber/fiber)](https://goreportcard.com/report/github.com/gofiber/fiber)
[![GitHub license](https://img.shields.io/github/license/gofiber/fiber.svg)](https://github.com/gofiber/fiber/blob/master/LICENSE) [![GitHub license](https://img.shields.io/github/license/gofiber/fiber.svg)](https://github.com/gofiber/fiber/blob/master/LICENSE)
[![Join the chat at https://gitter.im/FiberGo/community](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/FiberGo/community) [![Join the chat at https://gitter.im/FiberGo/community](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/FiberGo/community)
<br> <br>
# Getting started # Getting started
!>**IMPORTANT: Always use versioning control using [go.mod](https://blog.golang.org/using-go-modules) to avoid breaking API changes!**
!>**IMPORTANT: Always use versioning control using [go.mod](https://blog.golang.org/using-go-modules) to avoid breaking API changes!**
**[Fiber](https://github.com/gofiber/fiber)** is a router framework build on top of [FastHTTP](https://github.com/valyala/fasthttp), the fastest HTTP package for **[Go](https://golang.org/doc/)**.<br> **[Fiber](https://github.com/gofiber/fiber)** is a router framework build on top of [FastHTTP](https://github.com/valyala/fasthttp), the fastest HTTP package for **[Go](https://golang.org/doc/)**.<br>
This library is inspired by [Express](https://expressjs.com/en/4x/api.html), one of the most populair and well known web framework for **[Nodejs](https://nodejs.org/en/about/)**. This library is inspired by [Express](https://expressjs.com/en/4x/api.html), one of the most populair and well known web framework for **[Nodejs](https://nodejs.org/en/about/)**.
#### Installing #### Installing
Assuming youve already installed [Go](https://golang.org/doc/), install the [Fiber](https://github.com/gofiber/fiber) package by calling the following command: Assuming youve already installed [Go](https://golang.org/doc/), install the [Fiber](https://github.com/gofiber/fiber) package by calling the following command:
```shell ```shell
$ go get -u github.com/gofiber/fiber go get -u github.com/gofiber/fiber
``` ```
#### Hello world #### Hello world
Embedded below is essentially the simplest Fiber app you can create. Embedded below is essentially the simplest Fiber app you can create.
```shell ```shell
$ create server.go create server.go
``` ```
```go ```go
package main package main
@ -37,12 +45,15 @@ func main() {
app.Listen(8080) app.Listen(8080)
} }
``` ```
```shell ```shell
$ go run server.go go run server.go
``` ```
Browse to http://localhost:8080 and you should see Hello, World! on the page. Browse to http://localhost:8080 and you should see Hello, World! on the page.
#### Basic routing #### Basic routing
Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on). Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, and so on).
Each route can have one handler function, that is executed when the route is matched. Each route can have one handler function, that is executed when the route is matched.
@ -55,14 +66,15 @@ app.Method(func(*fiber.Ctx))
app.Method(path string, func(*fiber.Ctx)) app.Method(path string, func(*fiber.Ctx))
``` ```
* **app** is an instance of **[Fiber](#hello-world)**. - **app** is an instance of **[Fiber](#hello-world)**.
* **Method** is an [HTTP request method](application?id=methods), in capitalization: Get, Put, Post etc - **Method** is an [HTTP request method](application?id=methods), in capitalization: Get, Put, Post etc
* **path string** is a path on the server. - **path string** is a path on the server.
* **func(*fiber.Ctx)** is a function containing the [Context](/context) executed when the route is matched. - **func(\*fiber.Ctx)** is a function containing the [Context](/context) executed when the route is matched.
This tutorial assumes that an instance of fiber named app is created and the server is running. If you are not familiar with creating an app and starting it, see the [Hello world](#hello-world) example. This tutorial assumes that an instance of fiber named app is created and the server is running. If you are not familiar with creating an app and starting it, see the [Hello world](#hello-world) example.
The following examples illustrate defining simple routes. The following examples illustrate defining simple routes.
```go ```go
// Respond with Hello, World! on the homepage: // Respond with Hello, World! on the homepage:
app.Get("/", func(c *fiber.Ctx) { app.Get("/", func(c *fiber.Ctx) {
@ -95,22 +107,27 @@ app.Get("/api/*", func(c *fiber.Ctx) {
``` ```
#### Static files #### Static files
To serve static files such as images, CSS files, and JavaScript files, replace your function handler with a file or directory string. To serve static files such as images, CSS files, and JavaScript files, replace your function handler with a file or directory string.
```go ```go
// Function signature // Function signature
app.Static(root string) app.Static(root string)
app.Static(prefix, root string) app.Static(prefix, root string)
``` ```
For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public: For example, use the following code to serve images, CSS files, and JavaScript files in a directory named public:
```go ```go
app.Static("./public") app.Static("./public")
``` ```
Now, you can load the files that are in the public directory: Now, you can load the files that are in the public directory:
```shell ```shell
http://localhost:8080/hello.html http://localhost:8080/hello.html
http://localhost:8080/js/jquery.js http://localhost:8080/js/jquery.js
http://localhost:8080/css/style.css http://localhost:8080/css/style.css
``` ```
*Caught a mistake? [Edit this page on GitHub!](https://github.com/gofiber/fiber/blob/master/docs/getting_started.md)* _Caught a mistake? [Edit this page on GitHub!](https://github.com/gofiber/fiber/blob/master/docs/getting_started.md)_

View File

@ -1,5 +1,6 @@
# License & Thanks # License & Thanks
Special thanks to some amazing people and organizations:
Special thanks to some amazing people and organizations:
[@fenny](https://github.com/fenny) / [Fiber](https://github.com/gofiber/fiber/blob/master/LICENSE) [@fenny](https://github.com/fenny) / [Fiber](https://github.com/gofiber/fiber/blob/master/LICENSE)
[@valyala](https://github.com/valyala) / [Fasthttp](https://github.com/valyala/fasthttp/blob/master/LICENSE) [@valyala](https://github.com/valyala) / [Fasthttp](https://github.com/valyala/fasthttp/blob/master/LICENSE)
@ -8,7 +9,6 @@ Special thanks to some amazing people and organizations:
[@vincentLiuxiang](https://github.com/vincentLiuxiang) / [Lu](https://github.com/vincentLiuxiang/lu/blob/master/LICENSE) [@vincentLiuxiang](https://github.com/vincentLiuxiang) / [Lu](https://github.com/vincentLiuxiang/lu/blob/master/LICENSE)
[@tj](https://github.com/tj) / [Expressjs](https://github.com/expressjs/express) [@tj](https://github.com/tj) / [Expressjs](https://github.com/expressjs/express)
[@pillarjs](https://github.com/pillarjs) / [Path-to-regexp](https://github.com/pillarjs/path-to-regexp/blob/master/LICENSE) [@pillarjs](https://github.com/pillarjs) / [Path-to-regexp](https://github.com/pillarjs/path-to-regexp/blob/master/LICENSE)
[@techempower](https://github.com/TechEmpower) / [FrameworkBenchmarks](https://github.com/TechEmpower/FrameworkBenchmarks) [@techempower](https://github.com/TechEmpower) / [FrameworkBenchmarks](https://github.com/TechEmpower/FrameworkBenchmarks)
_Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/license.md)_
*Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/license.md)*

View File

@ -1,7 +1,7 @@
# Routing # Routing
#### Paths #### Paths
Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expressions. Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expressions.
The characters ?, +, "8", and () are subsets of their regular expression counterparts. The hyphen (-) and the dot (.) are interpreted literally by string-based paths. The characters ?, +, "8", and () are subsets of their regular expression counterparts. The hyphen (-) and the dot (.) are interpreted literally by string-based paths.
@ -24,7 +24,9 @@ app.Get("/random.text", func(c *fiber.Ctx) {
c.Send("random.text") c.Send("random.text")
}) })
``` ```
Here are some examples of route paths based on string patterns. Here are some examples of route paths based on string patterns.
```go ```go
// This route path will match acd and abcd. // This route path will match acd and abcd.
app.Get("/ab?cd", func(c *fiber.Ctx) { app.Get("/ab?cd", func(c *fiber.Ctx) {
@ -48,6 +50,7 @@ app.Get("/ab(cd)?e", func(c *fiber.Ctx) {
``` ```
#### Parameters #### Parameters
Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values can be retrieved using the [Params](context#params) function, with the name of the route parameter specified in the path as their respective keys. Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values can be retrieved using the [Params](context#params) function, with the name of the route parameter specified in the path as their respective keys.
To define routes with route parameters, simply specify the route parameters in the path of the route as shown below. To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.
@ -66,11 +69,13 @@ app.Get("/user/:name?", func(c *fiber.Ctx) {
c.Send(c.Params("name")) c.Send(c.Params("name"))
}) })
``` ```
?>The name of route parameters must be made up of “word characters” ([A-Za-z0-9_]). ?>The name of route parameters must be made up of “word characters” ([A-Za-z0-9_]).
!> The hyphen (-) and the dot (.) are not interpreted literally yet, planned for V2 !> The hyphen (-) and the dot (.) are not interpreted literally yet, planned for V2
#### Middleware #### Middleware
The [Next](context#next) function is a function in the [Fiber](https://github.com/fenny/fiber) router which, when called, executes the next function that matches the current route. The [Next](context#next) function is a function in the [Fiber](https://github.com/fenny/fiber) router which, when called, executes the next function that matches the current route.
Functions that are designed to make changes to the request or response are called middleware functions. Functions that are designed to make changes to the request or response are called middleware functions.
@ -99,4 +104,4 @@ app.Get("/", func(c *fiber.Ctx) {
app.Listen(8080) app.Listen(8080)
``` ```
*Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/routing.md)* _Caught a mistake? [Edit this page on GitHub!](https://github.com/Fenny/fiber/blob/master/docs/routing.md)_

51
docs/static/flags/en.svg vendored Normal file
View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512.001 512.001" style="enable-background:new 0 0 512.001 512.001;" xml:space="preserve">
<path style="fill:#41479B;" d="M503.172,423.725H8.828c-4.875,0-8.828-3.953-8.828-8.828V97.104c0-4.875,3.953-8.828,8.828-8.828
h494.345c4.875,0,8.828,3.953,8.828,8.828v317.793C512,419.772,508.047,423.725,503.172,423.725z"/>
<path style="fill:#F5F5F5;" d="M512,97.104c0-4.875-3.953-8.828-8.828-8.828h-39.495l-163.54,107.147V88.276h-88.276v107.147
L48.322,88.276H8.828C3.953,88.276,0,92.229,0,97.104v22.831l140.309,91.927H0v88.276h140.309L0,392.066v22.831
c0,4.875,3.953,8.828,8.828,8.828h39.495l163.54-107.147v107.147h88.276V316.578l163.54,107.147h39.495
c4.875,0,8.828-3.953,8.828-8.828v-22.831l-140.309-91.927H512v-88.276H371.691L512,119.935V97.104z"/>
<g>
<polygon style="fill:#FF4B55;" points="512,229.518 282.483,229.518 282.483,88.276 229.517,88.276 229.517,229.518 0,229.518
0,282.483 229.517,282.483 229.517,423.725 282.483,423.725 282.483,282.483 512,282.483 "/>
<path style="fill:#FF4B55;" d="M178.948,300.138L0.25,416.135c0.625,4.263,4.14,7.59,8.577,7.59h12.159l190.39-123.586H178.948z"/>
<path style="fill:#FF4B55;" d="M346.388,300.138H313.96l190.113,123.404c4.431-0.472,7.928-4.09,7.928-8.646v-7.258
L346.388,300.138z"/>
<path style="fill:#FF4B55;" d="M0,106.849l161.779,105.014h32.428L5.143,89.137C2.123,90.54,0,93.555,0,97.104V106.849z"/>
<path style="fill:#FF4B55;" d="M332.566,211.863L511.693,95.586c-0.744-4.122-4.184-7.309-8.521-7.309h-12.647L300.138,211.863
H332.566z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

40
docs/static/flags/ru.svg vendored Normal file
View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
<path style="fill:#F5F5F5;" d="M512,200.092H0V97.103c0-4.875,3.953-8.828,8.828-8.828h494.345c4.875,0,8.828,3.953,8.828,8.828
V200.092z"/>
<path style="fill:#FF4B55;" d="M503.172,423.724H8.828c-4.875,0-8.828-3.953-8.828-8.828V311.908h512v102.988
C512,419.772,508.047,423.724,503.172,423.724z"/>
<rect y="200.088" style="fill:#41479B;" width="512" height="111.812"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 863 B

BIN
docs/static/logo.jpg vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 43 KiB

BIN
docs/static/logo_320px_trans.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
docs/static/logo_750px_trans.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

3
go.sum
View File

@ -1,4 +1,5 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
@ -11,8 +12,10 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -67,20 +67,24 @@ func (r *Fiber) Listen(address interface{}, tls ...string) {
} }
r.prefork(server, host, tls...) r.prefork(server, host, tls...)
} }
// Prefork disabled // Prefork disabled
if r.Banner { if r.Banner {
fmt.Printf(banner, Version, "", "Express on steriods", host) fmt.Printf(banner, Version, "", "Express on steriods", host)
} }
ln, err := net.Listen("tcp4", host) ln, err := net.Listen("tcp4", host)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// enable TLS/HTTPS // enable TLS/HTTPS
if len(tls) > 1 { if len(tls) > 1 {
if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil { if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil {
panic(err) panic(err)
} }
} }
if err := server.Serve(ln); err != nil { if err := server.Serve(ln); err != nil {
panic(err) panic(err)
} }
@ -92,6 +96,7 @@ func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) {
if !r.child { if !r.child {
// Create babies // Create babies
childs := make([]*exec.Cmd, runtime.NumCPU()) childs := make([]*exec.Cmd, runtime.NumCPU())
for i := range childs { for i := range childs {
childs[i] = exec.Command(os.Args[0], "-prefork", "-child") childs[i] = exec.Command(os.Args[0], "-prefork", "-child")
childs[i].Stdout = os.Stdout childs[i].Stdout = os.Stdout
@ -100,26 +105,32 @@ func (r *Fiber) prefork(server *fasthttp.Server, host string, tls ...string) {
panic(err) panic(err)
} }
} }
for _, child := range childs { for _, child := range childs {
if err := child.Wait(); err != nil { if err := child.Wait(); err != nil {
panic(err) panic(err)
} }
} }
os.Exit(0) os.Exit(0)
} }
// Child proc // Child proc
runtime.GOMAXPROCS(1) runtime.GOMAXPROCS(1)
ln, err := reuseport.Listen("tcp4", host) ln, err := reuseport.Listen("tcp4", host)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// enable TLS/HTTPS // enable TLS/HTTPS
if len(tls) > 1 { if len(tls) > 1 {
if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil { if err := server.ServeTLS(ln, tls[0], tls[1]); err != nil {
panic(err) panic(err)
} }
} }
if err := server.Serve(ln); err != nil { if err := server.Serve(ln); err != nil {
panic(err) panic(err)
} }

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber

View File

@ -1,13 +1,10 @@
package middleware package middleware
import ( import "github.com/gofiber/fiber"
"fmt"
"github.com/gofiber/fiber"
)
// Cors : Enable cross-origin resource sharing (CORS) with various options. // Cors : Enable cross-origin resource sharing (CORS) with various options.
func Cors(c *fiber.Ctx) { func Cors(c *fiber.Ctx, d string) {
fmt.Println("Cors is still under development, disable until v1.0.0") c.Set("Access-Control-Allow-Origin", d) // Set d to "*" for allow all domains
c.Set("Access-Control-Allow-Headers", "X-Requested-With")
c.Next() c.Next()
} }

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -9,6 +9,7 @@ package fiber
import ( import (
"encoding/base64" "encoding/base64"
"log"
"mime" "mime"
"mime/multipart" "mime/multipart"
"strings" "strings"
@ -21,10 +22,12 @@ func (ctx *Ctx) Accepts(offers ...string) string {
if len(offers) == 0 { if len(offers) == 0 {
panic("You must provide atleast one content type string") panic("You must provide atleast one content type string")
} }
h := ctx.Get(fasthttp.HeaderAccept) h := ctx.Get(fasthttp.HeaderAccept)
if h == "" { if h == "" {
return offers[0] return offers[0]
} }
specs := strings.Split(h, ",") specs := strings.Split(h, ",")
for _, offer := range offers { for _, offer := range offers {
mimetype := getType(offer) mimetype := getType(offer)
@ -38,9 +41,11 @@ func (ctx *Ctx) Accepts(offers ...string) string {
if strings.HasPrefix(spec, "*/*") { if strings.HasPrefix(spec, "*/*") {
return offer return offer
} }
if strings.HasPrefix(spec, mimetype) { if strings.HasPrefix(spec, mimetype) {
return offer return offer
} }
if strings.Contains(spec, "/*") { if strings.Contains(spec, "/*") {
if strings.HasPrefix(spec, strings.Split(mimetype, "/")[0]) { if strings.HasPrefix(spec, strings.Split(mimetype, "/")[0]) {
return offer return offer
@ -56,10 +61,12 @@ func (ctx *Ctx) AcceptsCharsets(offers ...string) string {
if len(offers) == 0 { if len(offers) == 0 {
panic("You must provide atleast one content type string") panic("You must provide atleast one content type string")
} }
h := ctx.Get(fasthttp.HeaderAcceptCharset) h := ctx.Get(fasthttp.HeaderAcceptCharset)
if h == "" { if h == "" {
return offers[0] return offers[0]
} }
specs := strings.Split(h, ",") specs := strings.Split(h, ",")
for _, offer := range offers { for _, offer := range offers {
for _, spec := range specs { for _, spec := range specs {
@ -80,10 +87,12 @@ func (ctx *Ctx) AcceptsEncodings(offers ...string) string {
if len(offers) == 0 { if len(offers) == 0 {
panic("You must provide atleast one content type string") panic("You must provide atleast one content type string")
} }
h := ctx.Get(fasthttp.HeaderAcceptEncoding) h := ctx.Get(fasthttp.HeaderAcceptEncoding)
if h == "" { if h == "" {
return offers[0] return offers[0]
} }
specs := strings.Split(h, ",") specs := strings.Split(h, ",")
for _, offer := range offers { for _, offer := range offers {
for _, spec := range specs { for _, spec := range specs {
@ -104,10 +113,12 @@ func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
if len(offers) == 0 { if len(offers) == 0 {
panic("You must provide atleast one content type string") panic("You must provide atleast one content type string")
} }
h := ctx.Get(fasthttp.HeaderAcceptLanguage) h := ctx.Get(fasthttp.HeaderAcceptLanguage)
if h == "" { if h == "" {
return offers[0] return offers[0]
} }
specs := strings.Split(h, ",") specs := strings.Split(h, ",")
for _, offer := range offers { for _, offer := range offers {
for _, spec := range specs { for _, spec := range specs {
@ -123,8 +134,8 @@ func (ctx *Ctx) AcceptsLanguages(offers ...string) string {
return "" return ""
} }
// BaseUrl : https://gofiber.github.io/fiber/#/context?id=baseurl // BaseURL : https://gofiber.github.io/fiber/#/context?id=baseurl
func (ctx *Ctx) BaseUrl() string { func (ctx *Ctx) BaseURL() string {
return ctx.Protocol() + "://" + ctx.Hostname() return ctx.Protocol() + "://" + ctx.Hostname()
} }
@ -134,20 +145,25 @@ func (ctx *Ctx) BasicAuth() (user, pass string, ok bool) {
if auth == "" { if auth == "" {
return return
} }
const prefix = "Basic " const prefix = "Basic "
// Case insensitive prefix match. // Case insensitive prefix match.
if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) { if len(auth) < len(prefix) || !strings.EqualFold(auth[:len(prefix)], prefix) {
return return
} }
c, err := base64.StdEncoding.DecodeString(auth[len(prefix):]) c, err := base64.StdEncoding.DecodeString(auth[len(prefix):])
if err != nil { if err != nil {
return return
} }
cs := getString(c) cs := getString(c)
s := strings.IndexByte(cs, ':') s := strings.IndexByte(cs, ':')
if s < 0 { if s < 0 {
return return
} }
return cs[:s], cs[s+1:], true return cs[:s], cs[s+1:], true
} }
@ -156,6 +172,7 @@ func (ctx *Ctx) Body(args ...interface{}) string {
if len(args) == 0 { if len(args) == 0 {
return getString(ctx.Fasthttp.Request.Body()) return getString(ctx.Fasthttp.Request.Body())
} }
if len(args) == 1 { if len(args) == 1 {
switch arg := args[0].(type) { switch arg := args[0].(type) {
case string: case string:
@ -176,6 +193,7 @@ func (ctx *Ctx) Cookies(args ...interface{}) string {
if len(args) == 0 { if len(args) == 0 {
return ctx.Get(fasthttp.HeaderCookie) return ctx.Get(fasthttp.HeaderCookie)
} }
switch arg := args[0].(type) { switch arg := args[0].(type) {
case string: case string:
return getString(ctx.Fasthttp.Request.Header.Cookie(arg)) return getString(ctx.Fasthttp.Request.Header.Cookie(arg))
@ -188,6 +206,7 @@ func (ctx *Ctx) Cookies(args ...interface{}) string {
default: default:
return ctx.Get(fasthttp.HeaderCookie) return ctx.Get(fasthttp.HeaderCookie)
} }
return "" return ""
} }
@ -220,8 +239,8 @@ func (ctx *Ctx) Hostname() string {
return getString(ctx.Fasthttp.URI().Host()) return getString(ctx.Fasthttp.URI().Host())
} }
// Ip : https://gofiber.github.io/fiber/#/context?id=Ip // IP : https://gofiber.github.io/fiber/#/context?id=Ip
func (ctx *Ctx) Ip() string { func (ctx *Ctx) IP() string {
return ctx.Fasthttp.RemoteIP().String() return ctx.Fasthttp.RemoteIP().String()
} }
@ -239,6 +258,7 @@ func (ctx *Ctx) Is(ext string) bool {
if ext[0] != '.' { if ext[0] != '.' {
ext = "." + ext ext = "." + ext
} }
exts, _ := mime.ExtensionsByType(ctx.Get(fasthttp.HeaderContentType)) exts, _ := mime.ExtensionsByType(ctx.Get(fasthttp.HeaderContentType))
if len(exts) > 0 { if len(exts) > 0 {
for _, item := range exts { for _, item := range exts {
@ -254,9 +274,9 @@ func (ctx *Ctx) Is(ext string) bool {
func (ctx *Ctx) Locals(key string, val ...interface{}) interface{} { func (ctx *Ctx) Locals(key string, val ...interface{}) interface{} {
if len(val) == 0 { if len(val) == 0 {
return ctx.Fasthttp.UserValue(key) return ctx.Fasthttp.UserValue(key)
} else {
ctx.Fasthttp.SetUserValue(key, val[0])
} }
ctx.Fasthttp.SetUserValue(key, val[0])
return nil return nil
} }
@ -270,8 +290,8 @@ func (ctx *Ctx) MultipartForm() (*multipart.Form, error) {
return ctx.Fasthttp.MultipartForm() return ctx.Fasthttp.MultipartForm()
} }
// OriginalUrl : https://gofiber.github.io/fiber/#/context?id=originalurl // OriginalURL : https://gofiber.github.io/fiber/#/context?id=originalurl
func (ctx *Ctx) OriginalUrl() string { func (ctx *Ctx) OriginalURL() string {
return getString(ctx.Fasthttp.Request.Header.RequestURI()) return getString(ctx.Fasthttp.Request.Header.RequestURI())
} }
@ -280,6 +300,7 @@ func (ctx *Ctx) Params(key string) string {
if ctx.params == nil { if ctx.params == nil {
return "" return ""
} }
for i := 0; i < len(*ctx.params); i++ { for i := 0; i < len(*ctx.params); i++ {
if (*ctx.params)[i] == key { if (*ctx.params)[i] == key {
return ctx.values[i] return ctx.values[i]
@ -312,13 +333,15 @@ func (ctx *Ctx) Range() {
} }
// Route : https://gofiber.github.io/fiber/#/context?id=route // Route : https://gofiber.github.io/fiber/#/context?id=route
func (ctx *Ctx) Route() *route { func (ctx *Ctx) Route() *Route {
return ctx.route return ctx.route
} }
// SaveFile : https://gofiber.github.io/fiber/#/context?id=secure // SaveFile : https://gofiber.github.io/fiber/#/context?id=secure
func (ctx *Ctx) SaveFile(fh *multipart.FileHeader, path string) { func (ctx *Ctx) SaveFile(fh *multipart.FileHeader, path string) {
fasthttp.SaveMultipartFile(fh, path) if err := fasthttp.SaveMultipartFile(fh, path); err != nil {
log.Fatal(err)
}
} }
// Secure : https://gofiber.github.io/fiber/#/context?id=secure // Secure : https://gofiber.github.io/fiber/#/context?id=secure
@ -343,7 +366,7 @@ func (ctx *Ctx) Subdomains() (subs []string) {
return subs return subs
} }
// Xhr : https://gofiber.github.io/fiber/#/context?id=xhr // XHR : https://gofiber.github.io/fiber/#/context?id=xhr
func (ctx *Ctx) Xhr() bool { func (ctx *Ctx) XHR() bool {
return ctx.Get("X-Requested-With") == "XMLHttpRequest" return ctx.Get("X-Requested-With") == "XMLHttpRequest"
} }

View File

@ -1,14 +1,16 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
// 🦸 Not all heroes wear capes, thank you to some amazing people // 🦸 Not all heroes wear capes, thank you to some amazing people
// 💖 @valyala, @dgrr, @erikdubbelboer, @savsgio, @julienschmidt // 💖 @valyala, @dgrr, @erikdubbelboer, @savsgio, @julienschmidt
package fiber package fiber
import ( import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"log"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
@ -22,6 +24,7 @@ func (ctx *Ctx) Append(field string, values ...string) {
if len(values) == 0 { if len(values) == 0 {
return return
} }
h := ctx.Get(field) h := ctx.Get(field)
for i := range values { for i := range values {
h += h + "," + values[i] h += h + "," + values[i]
@ -48,6 +51,7 @@ func (ctx *Ctx) ClearCookie(name ...string) {
} }
return return
} }
ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) { ctx.Fasthttp.Request.Header.VisitAllCookie(func(k, v []byte) {
ctx.Fasthttp.Response.Header.DelClientCookie(getString(k)) ctx.Fasthttp.Response.Header.DelClientCookie(getString(k))
}) })
@ -56,8 +60,10 @@ func (ctx *Ctx) ClearCookie(name ...string) {
// Cookie : https://gofiber.github.io/fiber/#/context?id=cookie // Cookie : https://gofiber.github.io/fiber/#/context?id=cookie
func (ctx *Ctx) Cookie(key, value string, options ...interface{}) { func (ctx *Ctx) Cookie(key, value string, options ...interface{}) {
cook := &fasthttp.Cookie{} cook := &fasthttp.Cookie{}
cook.SetKey(key) cook.SetKey(key)
cook.SetValue(value) cook.SetValue(value)
if len(options) > 0 { if len(options) > 0 {
switch opt := options[0].(type) { switch opt := options[0].(type) {
case *Cookie: case *Cookie:
@ -73,8 +79,8 @@ func (ctx *Ctx) Cookie(key, value string, options ...interface{}) {
if opt.Path != "" { if opt.Path != "" {
cook.SetPath(opt.Path) cook.SetPath(opt.Path)
} }
if opt.HttpOnly { if opt.HTTPOnly {
cook.SetHTTPOnly(opt.HttpOnly) cook.SetHTTPOnly(opt.HTTPOnly)
} }
if opt.Secure { if opt.Secure {
cook.SetSecure(opt.Secure) cook.SetSecure(opt.Secure)
@ -96,15 +102,18 @@ func (ctx *Ctx) Cookie(key, value string, options ...interface{}) {
panic("Invalid cookie options") panic("Invalid cookie options")
} }
} }
ctx.Fasthttp.Response.Header.SetCookie(cook) ctx.Fasthttp.Response.Header.SetCookie(cook)
} }
// Download : https://gofiber.github.io/fiber/#/context?id=download // Download : https://gofiber.github.io/fiber/#/context?id=download
func (ctx *Ctx) Download(file string, name ...string) { func (ctx *Ctx) Download(file string, name ...string) {
filename := filepath.Base(file) filename := filepath.Base(file)
if len(name) > 0 { if len(name) > 0 {
filename = name[0] filename = name[0]
} }
ctx.Set(fasthttp.HeaderContentDisposition, "attachment; filename="+filename) ctx.Set(fasthttp.HeaderContentDisposition, "attachment; filename="+filename)
ctx.SendFile(file) ctx.SendFile(file)
} }
@ -117,7 +126,9 @@ func (ctx *Ctx) End() {
// Format : https://gofiber.github.io/fiber/#/context?id=format // Format : https://gofiber.github.io/fiber/#/context?id=format
func (ctx *Ctx) Format(args ...interface{}) { func (ctx *Ctx) Format(args ...interface{}) {
var body string var body string
accept := ctx.Accepts("html", "json") accept := ctx.Accepts("html", "json")
for i := range args { for i := range args {
switch arg := args[i].(type) { switch arg := args[i].(type) {
case string: case string:
@ -131,7 +142,9 @@ func (ctx *Ctx) Format(args ...interface{}) {
case "html": case "html":
ctx.SendString("<p>" + body + "</p>") ctx.SendString("<p>" + body + "</p>")
case "json": case "json":
ctx.Json(body) if err := ctx.JSON(body); err != nil {
log.Fatal(err)
}
default: default:
ctx.SendString(body) ctx.SendString(body)
} }
@ -143,29 +156,32 @@ func (ctx *Ctx) HeadersSent() {
} }
// Json : https://gofiber.github.io/fiber/#/context?id=json // JSON : https://gofiber.github.io/fiber/#/context?id=json
func (ctx *Ctx) Json(v interface{}) error { func (ctx *Ctx) JSON(v interface{}) error {
raw, err := jsoniter.Marshal(&v) raw, err := jsoniter.Marshal(&v)
if err != nil { if err != nil {
return err return err
} }
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJson)
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJSON)
ctx.Fasthttp.Response.SetBodyString(getString(raw)) ctx.Fasthttp.Response.SetBodyString(getString(raw))
return nil return nil
} }
// JsonBytes : https://gofiber.github.io/fiber/#/context?id=jsonbytes // JSONBytes : https://gofiber.github.io/fiber/#/context?id=jsonbytes
func (ctx *Ctx) JsonBytes(raw []byte) { func (ctx *Ctx) JSONBytes(raw []byte) {
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJson) ctx.Fasthttp.Response.Header.SetContentType(contentTypeJSON)
ctx.Fasthttp.Response.SetBodyString(getString(raw)) ctx.Fasthttp.Response.SetBodyString(getString(raw))
} }
// Jsonp : https://gofiber.github.io/fiber/#/context?id=jsonp // JSONP : https://gofiber.github.io/fiber/#/context?id=jsonp
func (ctx *Ctx) Jsonp(v interface{}, cb ...string) error { func (ctx *Ctx) JSONP(v interface{}, cb ...string) error {
raw, err := jsoniter.Marshal(&v) raw, err := jsoniter.Marshal(&v)
if err != nil { if err != nil {
return err return err
} }
str := "callback(" str := "callback("
if len(cb) > 0 { if len(cb) > 0 {
str = cb[0] + "(" str = cb[0] + "("
@ -175,12 +191,13 @@ func (ctx *Ctx) Jsonp(v interface{}, cb ...string) error {
ctx.Set(fasthttp.HeaderXContentTypeOptions, "nosniff") ctx.Set(fasthttp.HeaderXContentTypeOptions, "nosniff")
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJs) ctx.Fasthttp.Response.Header.SetContentType(contentTypeJs)
ctx.Fasthttp.Response.SetBodyString(str) ctx.Fasthttp.Response.SetBodyString(str)
return nil return nil
} }
// JsonString : https://gofiber.github.io/fiber/#/context?id=jsonstring // JSONString : https://gofiber.github.io/fiber/#/context?id=jsonstring
func (ctx *Ctx) JsonString(raw string) { func (ctx *Ctx) JSONString(raw string) {
ctx.Fasthttp.Response.Header.SetContentType(contentTypeJson) ctx.Fasthttp.Response.Header.SetContentType(contentTypeJSON)
ctx.Fasthttp.Response.SetBodyString(raw) ctx.Fasthttp.Response.SetBodyString(raw)
} }
@ -194,6 +211,7 @@ func (ctx *Ctx) Links(link ...string) {
h += `; rel="` + l + `",` h += `; rel="` + l + `",`
} }
} }
if len(link) > 0 { if len(link) > 0 {
h = strings.TrimSuffix(h, ",") h = strings.TrimSuffix(h, ",")
ctx.Set(fasthttp.HeaderLink, h) ctx.Set(fasthttp.HeaderLink, h)
@ -219,6 +237,7 @@ func (ctx *Ctx) Redirect(path string, status ...int) {
if len(status) > 0 { if len(status) > 0 {
code = status[0] code = status[0]
} }
ctx.Set(fasthttp.HeaderLocation, path) ctx.Set(fasthttp.HeaderLocation, path)
ctx.Fasthttp.Response.SetStatusCode(code) ctx.Fasthttp.Response.SetStatusCode(code)
} }
@ -233,6 +252,7 @@ func (ctx *Ctx) Send(args ...interface{}) {
if len(args) == 0 { if len(args) == 0 {
return return
} }
switch body := args[0].(type) { switch body := args[0].(type) {
case string: case string:
ctx.Fasthttp.Response.SetBodyString(body) ctx.Fasthttp.Response.SetBodyString(body)
@ -255,6 +275,7 @@ func (ctx *Ctx) SendFile(file string, gzip ...bool) {
fasthttp.ServeFileUncompressed(ctx.Fasthttp, file) fasthttp.ServeFileUncompressed(ctx.Fasthttp, file)
return return
} }
fasthttp.ServeFile(ctx.Fasthttp, file) fasthttp.ServeFile(ctx.Fasthttp, file)
// https://github.com/valyala/fasthttp/blob/master/fs.go#L81 // https://github.com/valyala/fasthttp/blob/master/fs.go#L81
//ctx.Type(filepath.Ext(path)) //ctx.Type(filepath.Ext(path))
@ -264,6 +285,7 @@ func (ctx *Ctx) SendFile(file string, gzip ...bool) {
// SendStatus : https://gofiber.github.io/fiber/#/context?id=sendstatus // SendStatus : https://gofiber.github.io/fiber/#/context?id=sendstatus
func (ctx *Ctx) SendStatus(status int) { func (ctx *Ctx) SendStatus(status int) {
ctx.Fasthttp.Response.SetStatusCode(status) ctx.Fasthttp.Response.SetStatusCode(status)
// Only set status body when there is no response body // Only set status body when there is no response body
if len(ctx.Fasthttp.Response.Body()) == 0 { if len(ctx.Fasthttp.Response.Body()) == 0 {
msg := getStatus(status) msg := getStatus(status)
@ -300,12 +322,14 @@ func (ctx *Ctx) Vary(fields ...string) {
if len(fields) == 0 { if len(fields) == 0 {
return return
} }
vary := ctx.Get(fasthttp.HeaderVary) vary := ctx.Get(fasthttp.HeaderVary)
for _, field := range fields { for _, field := range fields {
if !strings.Contains(vary, field) { if !strings.Contains(vary, field) {
vary += ", " + field vary += ", " + field
} }
} }
ctx.Set(fasthttp.HeaderVary, vary) ctx.Set(fasthttp.HeaderVary, vary)
} }
@ -323,13 +347,15 @@ func (ctx *Ctx) Write(args ...interface{}) {
} }
} }
// Xml : https://gofiber.github.io/fiber/#/context?id=xml // XML : https://gofiber.github.io/fiber/#/context?id=xml
func (ctx *Ctx) Xml(v interface{}) error { func (ctx *Ctx) XML(v interface{}) error {
raw, err := xml.Marshal(v) raw, err := xml.Marshal(v)
if err != nil { if err != nil {
return err return err
} }
ctx.Fasthttp.Response.Header.SetContentType(contentTypeXml)
ctx.Fasthttp.Response.Header.SetContentType(contentTypeXML)
ctx.Fasthttp.Response.SetBody(raw) ctx.Fasthttp.Response.SetBody(raw)
return nil return nil
} }

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -14,10 +14,11 @@ import (
"github.com/valyala/fasthttp" "github.com/valyala/fasthttp"
) )
type route struct { // Route : struct
type Route struct {
// HTTP method in uppercase, can be a * for Use() & All() // HTTP method in uppercase, can be a * for Use() & All()
Method string Method string
// Stores the orignal path // Stores the original path
Path string Path string
// Bool that defines if the route is a Use() middleware // Bool that defines if the route is a Use() middleware
Midware bool Midware bool
@ -35,13 +36,16 @@ type route struct {
func (r *Fiber) register(method string, args ...interface{}) { func (r *Fiber) register(method string, args ...interface{}) {
// Set if method is Use() midware // Set if method is Use() midware
var midware = method == "MIDWARE" var midware = method == "MIDWARE"
// Match any method // Match any method
if method == "ALL" || midware { if method == "ALL" || midware {
method = "*" method = "*"
} }
// Prepare possible variables // Prepare possible variables
var path string // We could have a path/prefix var path string // We could have a path/prefix
var handler func(*Ctx) // We could have a ctx handler var handler func(*Ctx) // We could have a ctx handler
// Only 1 argument, so no path/prefix // Only 1 argument, so no path/prefix
if len(args) == 1 { if len(args) == 1 {
handler = args[0].(func(*Ctx)) handler = args[0].(func(*Ctx))
@ -52,49 +56,59 @@ func (r *Fiber) register(method string, args ...interface{}) {
panic("Invalid path, must begin with slash '/' or wildcard '*'") panic("Invalid path, must begin with slash '/' or wildcard '*'")
} }
} }
if midware && strings.Contains(path, "/:") { if midware && strings.Contains(path, "/:") {
panic("You cannot use :params in Use()") panic("You cannot use :params in Use()")
} }
// If Use() path == "/", match anything aka * // If Use() path == "/", match anything aka *
if midware && path == "/" { if midware && path == "/" {
path = "*" path = "*"
} }
// If the route needs to match any path // If the route needs to match any path
if path == "" || path == "*" || path == "/*" { if path == "" || path == "*" || path == "/*" {
r.routes = append(r.routes, &route{method, path, midware, true, nil, nil, handler}) r.routes = append(r.routes, &Route{method, path, midware, true, nil, nil, handler})
return
}
// Get params from path
params := getParams(path)
// If path has no params (simple path), we dont need regex (also for use())
if midware || len(params) == 0 {
r.routes = append(r.routes, &route{method, path, midware, false, nil, nil, handler})
return return
} }
// We have parametes, so we need to compile regix from the path // Get params from path
params := getParams(path)
// If path has no params (simple path), we don't need regex (also for use())
if midware || len(params) == 0 {
r.routes = append(r.routes, &Route{method, path, midware, false, nil, nil, handler})
return
}
// We have parametes, so we need to compile regex from the path
regex, err := getRegex(path) regex, err := getRegex(path)
if err != nil { if err != nil {
panic("Invalid url pattern: " + path) panic("Invalid url pattern: " + path)
} }
// Add regex + params to route // Add regex + params to route
r.routes = append(r.routes, &route{method, path, midware, false, regex, params, handler}) r.routes = append(r.routes, &Route{method, path, midware, false, regex, params, handler})
} }
// then try to match a route as efficient as possible. // then try to match a route as efficient as possible.
func (r *Fiber) handler(fctx *fasthttp.RequestCtx) { func (r *Fiber) handler(fctx *fasthttp.RequestCtx) {
found := false found := false
// get custom context from sync pool // get custom context from sync pool
ctx := acquireCtx(fctx) ctx := acquireCtx(fctx)
// get path and method from main context // get path and method from main context
path := ctx.Path() path := ctx.Path()
method := ctx.Method() method := ctx.Method()
// loop trough routes // loop trough routes
for _, route := range r.routes { for _, route := range r.routes {
// Skip route if method is not allowed // Skip route if method is not allowed
if route.Method != "*" && route.Method != method { if route.Method != "*" && route.Method != method {
continue continue
} }
// First check if we match a wildcard or static path // First check if we match a wildcard or static path
if route.Wildcard || route.Path == path { if route.Wildcard || route.Path == path {
// if route.wildcard || (route.path == path && route.params == nil) { // if route.wildcard || (route.path == path && route.params == nil) {
@ -117,6 +131,7 @@ func (r *Fiber) handler(fctx *fasthttp.RequestCtx) {
// continue to go to the next route // continue to go to the next route
continue continue
} }
// If route is Use() and path starts with route.path // If route is Use() and path starts with route.path
// aka strings.HasPrefix(route.path, path) // aka strings.HasPrefix(route.path, path)
if route.Midware && strings.HasPrefix(path, route.Path) { if route.Midware && strings.HasPrefix(path, route.Path) {
@ -129,14 +144,17 @@ func (r *Fiber) handler(fctx *fasthttp.RequestCtx) {
ctx.next = false ctx.next = false
continue continue
} }
// Skip route if regex does not exist // Skip route if regex does not exist
if route.Regex == nil { if route.Regex == nil {
continue continue
} }
// Skip route if regex does not match // Skip route if regex does not match
if !route.Regex.MatchString(path) { if !route.Regex.MatchString(path) {
continue continue
} }
// If we have parameters, lets find the matches // If we have parameters, lets find the matches
if len(route.Params) > 0 { if len(route.Params) > 0 {
matches := route.Regex.FindAllStringSubmatch(path, -1) matches := route.Regex.FindAllStringSubmatch(path, -1)
@ -146,23 +164,30 @@ func (r *Fiber) handler(fctx *fasthttp.RequestCtx) {
ctx.values = matches[0][1:len(matches[0])] ctx.values = matches[0][1:len(matches[0])]
} }
} }
found = true found = true
// Set route pointer if user wants to call .Route() // Set route pointer if user wants to call .Route()
ctx.route = route ctx.route = route
// Execute handler with context // Execute handler with context
route.Handler(ctx) route.Handler(ctx)
// if next is not set, leave loop and release ctx // if next is not set, leave loop and release ctx
if !ctx.next { if !ctx.next {
break break
} }
// set next to false for next iteration // set next to false for next iteration
ctx.next = false ctx.next = false
} }
// No routes found // No routes found
if !found { if !found {
// Custom 404 handler? // Custom 404 handler?
ctx.Status(404).Send("Not Found") ctx.Status(404).Send("Not Found")
} }
// release context back into sync pool // release context back into sync pool
releaseCtx(ctx) releaseCtx(ctx)
} }

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -19,6 +19,7 @@ func (r *Fiber) Static(args ...string) {
wildcard := false wildcard := false
// enable / disable gzipping somewhere? // enable / disable gzipping somewhere?
gzip := true gzip := true
if len(args) == 1 { if len(args) == 1 {
root = args[0] root = args[0]
} else if len(args) == 2 { } else if len(args) == 2 {
@ -28,36 +29,44 @@ func (r *Fiber) Static(args ...string) {
prefix = "/" + prefix prefix = "/" + prefix
} }
} }
// Check if wildcard for single files // Check if wildcard for single files
if prefix == "*" || prefix == "/*" { if prefix == "*" || prefix == "/*" {
wildcard = true wildcard = true
} }
// Lets get all files from root // Lets get all files from root
files, _, err := getFiles(root) files, _, err := getFiles(root)
if err != nil { if err != nil {
panic(err) panic(err)
} }
// ./static/compiled => static/compiled // ./static/compiled => static/compiled
mount := filepath.Clean(root) mount := filepath.Clean(root)
// Loop over all files // Loop over all files
for _, file := range files { for _, file := range files {
// Ignore the .gzipped files by fasthttp // Ignore the .gzipped files by fasthttp
if strings.Contains(file, ".fasthttp.gz") { if strings.Contains(file, ".fasthttp.gz") {
continue continue
} }
// Time to create a fake path for the route match // Time to create a fake path for the route match
// static/index.html => /index.html // static/index.html => /index.html
path := filepath.Join(prefix, strings.Replace(file, mount, "", 1)) path := filepath.Join(prefix, strings.Replace(file, mount, "", 1))
// Store original file path to use in ctx handler // Store original file path to use in ctx handler
filePath := file filePath := file
// If the file is an index.html, bind the prefix to index.html directly // 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" { 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) { r.routes = append(r.routes, &Route{"GET", prefix, wildcard, false, nil, nil, func(c *Ctx) {
c.SendFile(filePath, gzip) c.SendFile(filePath, gzip)
}}) }})
} }
// Add the route + SendFile(filepath) to routes // Add the route + SendFile(filepath) to routes
r.routes = append(r.routes, &route{"GET", path, wildcard, false, nil, nil, func(c *Ctx) { r.routes = append(r.routes, &Route{"GET", path, wildcard, false, nil, nil, func(c *Ctx) {
c.SendFile(filePath, gzip) c.SendFile(filePath, gzip)
}}) }})
} }

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -9,9 +9,9 @@ package fiber
// common content types // common content types
const ( const (
contentTypeJson = "application/json" contentTypeJSON = "application/json"
contentTypeJs = "application/javascript" contentTypeJs = "application/javascript"
contentTypeXml = "application/xml" contentTypeXML = "application/xml"
contentTypeOctetStream = "application/octet-stream" contentTypeOctetStream = "application/octet-stream"
) )

View File

@ -1,4 +1,4 @@
// 🔌 Fiber is an Expressjs inspired web framework build on 🚀 Fasthttp. // 🔌 Fiber is an Express.js inspired web framework build on 🚀 Fasthttp.
// 📌 Please open an issue if you got suggestions or found a bug! // 📌 Please open an issue if you got suggestions or found a bug!
// 🖥 https://github.com/gofiber/fiber // 🖥 https://github.com/gofiber/fiber
@ -29,6 +29,7 @@ func getParams(path string) (params []string) {
} }
return params return params
} }
func getRegex(path string) (*regexp.Regexp, error) { func getRegex(path string) (*regexp.Regexp, error) {
pattern := "^" pattern := "^"
segments := strings.Split(path, "/") segments := strings.Split(path, "/")
@ -49,6 +50,7 @@ func getRegex(path string) (*regexp.Regexp, error) {
regex, err := regexp.Compile(pattern) regex, err := regexp.Compile(pattern)
return regex, err return regex, err
} }
func getFiles(root string) (files []string, isDir bool, err error) { func getFiles(root string) (files []string, isDir bool, err error) {
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error { err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() { if !info.IsDir() {
@ -60,6 +62,7 @@ func getFiles(root string) (files []string, isDir bool, err error) {
}) })
return files, isDir, err return files, isDir, err
} }
func getType(ext string) (mime string) { func getType(ext string) (mime string) {
if ext[0] == '.' { if ext[0] == '.' {
ext = ext[1:] ext = ext[1:]
@ -70,12 +73,15 @@ func getType(ext string) (mime string) {
} }
return mime return mime
} }
func getStatus(status int) (msg string) { func getStatus(status int) (msg string) {
return statusMessages[status] return statusMessages[status]
} }
func getString(b []byte) string { func getString(b []byte) string {
return *(*string)(unsafe.Pointer(&b)) return *(*string)(unsafe.Pointer(&b))
} }
func getBytes(s string) []byte { func getBytes(s string) []byte {
return *(*[]byte)(unsafe.Pointer(&s)) return *(*[]byte)(unsafe.Pointer(&s))
} }