Release of version 10.4.0 - x8 faster embedded file server | Star and Read HISTORY.md

Former-commit-id: 4f8b8c95c1b107a9be3b1ef6835ece949a75ceb6
This commit is contained in:
Gerasimos Maropoulos 2018-03-14 07:17:35 +02:00
parent 1e0c707366
commit 56215eeb71
28 changed files with 20453 additions and 67 deletions

2
Gopkg.lock generated
View File

@ -89,7 +89,7 @@
branch = "master" branch = "master"
name = "github.com/iris-contrib/httpexpect" name = "github.com/iris-contrib/httpexpect"
packages = ["."] packages = ["."]
revision = "65e93247e7071782e760f82086e8b677cca0c78a" revision = "ebe99fcebbcedf6e7916320cce24c3e1832766ac"
[[projects]] [[projects]]
branch = "master" branch = "master"

View File

@ -17,6 +17,33 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris` or let the automatic updater do that for you. **How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris` or let the automatic updater do that for you.
# We, 14 March 2018 | v10.4.0
- fix `APIBuilder, Party#StaticWeb` and `APIBuilder, Party#StaticEmbedded` wrong strip prefix inside children parties
- keep the `iris, core/router#StaticEmbeddedHandler` and remove the `core/router/APIBuilder#StaticEmbeddedHandler`, (note the `Handler` suffix) it's global and has nothing to do with the `Party` or the `APIBuilder`
- fix high path cleaning between `{}` (we already escape those contents at the [interpreter](core/router/macro/interpreter) level but some symbols are still removed by the higher-level api builder) , i.e `\\` from the string's macro function `regex` contents as reported at [927](https://github.com/kataras/iris/issues/927) by [commit e85b113476eeefffbc7823297cc63cd152ebddfd](https://github.com/kataras/iris/commit/e85b113476eeefffbc7823297cc63cd152ebddfd)
- sync the `golang.org/x/sys/unix` vendor
## The most important
We've made static files served up to 8 times faster using the new tool, <https://github.com/kataras/bindata> which is a fork of your beloved `go-bindata`, some unnecessary things for us were removed there and contains some additions for performance boost.
## Reqs/sec with [shuLhan/go-bindata](https://github.com/shuLhan/go-bindata) and alternatives
![go-bindata](https://github.com/kataras/bindata/raw/master/go-bindata-benchmark.png)
## Reqs/sec with [kataras/bindata](https://github.com/kataras/bindata)
![bindata](https://github.com/kataras/bindata/raw/master/bindata-benchmark.png)
A **new** function `Party#StaticEmbeddedGzip` which has the same input arguments as the `Party#StaticEmbedded` added. The difference is that the **new** `StaticEmbeddedGzip` accepts the `GzipAsset` and `GzipAssetNames` from the `bindata` (go get -u github.com/kataras/bindata/cmd/bindata).
You can still use both `bindata` and `go-bindata` tools in the same folder, the first for embedding the rest of the static files (javascript, css, ...) and the second for embedding the templates!
A full example can be found at: [_examples/file-server/embedding-gziped-files-into-app/main.go](_examples/file-server/embedding-gziped-files-into-app/main.go).
_Happy Coding!_
# Sa, 10 March 2018 | v10.3.0 # Sa, 10 March 2018 | v10.3.0
- The only one API Change is the [Application/Context/Router#RouteExists](https://godoc.org/github.com/kataras/iris/core/router#Router.RouteExists), it accepts the `Context` as its first argument instead of last now. - The only one API Change is the [Application/Context/Router#RouteExists](https://godoc.org/github.com/kataras/iris/core/router#Router.RouteExists), it accepts the `Context` as its first argument instead of last now.

View File

@ -17,9 +17,13 @@
**Πώς να αναβαθμίσετε**: Ανοίξτε την γραμμή εντολών σας και εκτελέστε αυτήν την εντολή: `go get -u github.com/kataras/iris` ή αφήστε το αυτόματο updater να το κάνει αυτό για σας. **Πώς να αναβαθμίσετε**: Ανοίξτε την γραμμή εντολών σας και εκτελέστε αυτήν την εντολή: `go get -u github.com/kataras/iris` ή αφήστε το αυτόματο updater να το κάνει αυτό για σας.
# We, 14 March 2018 | v10.4.0
This history entry is not translated yet to the Greek language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#we-14-march-2018--v1040) instead.
# Sa, 10 March 2018 | v10.3.0 # Sa, 10 March 2018 | v10.3.0
This history entry is not translated yet to the Greek language yet, please refer to the original [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#sa-10-march-2018--v1030) instead. This history entry is not translated yet to the Greek language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#sa-10-march-2018--v1030) instead.
# Th, 15 February 2018 | v10.2.1 # Th, 15 February 2018 | v10.2.1

View File

@ -17,6 +17,10 @@
**如何升级**: 打开命令行执行以下命令: `go get -u github.com/kataras/iris` 或者等待自动更新。 **如何升级**: 打开命令行执行以下命令: `go get -u github.com/kataras/iris` 或者等待自动更新。
# We, 14 March 2018 | v10.4.0
This history entry is not translated yet to the Chinese language yet, please refer to the english version of the [HISTORY entry](https://github.com/kataras/iris/blob/master/HISTORY.md#we-14-march-2018--v1040) instead.
# 2018 3月10号 | v10.3.0 版本更新 # 2018 3月10号 | v10.3.0 版本更新
- 只有一项 API 更改 [Application/Context/Router#RouteExists](https://godoc.org/github.com/kataras/iris/core/router#Router.RouteExists), 将 `Context` 作为第一参数,而不是最后一个。 - 只有一项 API 更改 [Application/Context/Router#RouteExists](https://godoc.org/github.com/kataras/iris/core/router#Router.RouteExists), 将 `Context` 作为第一参数,而不是最后一个。

View File

@ -2,7 +2,7 @@
<a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a> <a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a>
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.3-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) [![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.4-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases)
Iris is a fast, simple yet fully featured and very efficient web framework for Go. Iris is a fast, simple yet fully featured and very efficient web framework for Go.
@ -106,7 +106,7 @@ _Updated at: [Tuesday, 21 November 2017](_benchmarks/README_UNIX.md)_
## Support ## Support
- [HISTORY](HISTORY.md#sa-10-march-2018--v1030) file is your best friend, it contains information about the latest features and changes - [HISTORY](HISTORY.md#we-14-march-2018--v1040) file is your best friend, it contains information about the latest features and changes
- Did you happen to find a bug? Post it at [github issues](https://github.com/kataras/iris/issues) - Did you happen to find a bug? Post it at [github issues](https://github.com/kataras/iris/issues)
- Do you have any questions or need to speak with someone experienced to solve a problem at real-time? Join us to the [community chat](https://chat.iris-go.com) - Do you have any questions or need to speak with someone experienced to solve a problem at real-time? Join us to the [community chat](https://chat.iris-go.com)
- Complete our form-based user experience report by clicking [here](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link) - Complete our form-based user experience report by clicking [here](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link)

View File

@ -2,7 +2,7 @@
<a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a> <a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a>
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.3-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) [![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.4-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases)
Το Iris είναι ένα γρήγορο, απλό αλλά και πλήρως λειτουργικό και πολύ αποδοτικό web framework για τη Go. Το Iris είναι ένα γρήγορο, απλό αλλά και πλήρως λειτουργικό και πολύ αποδοτικό web framework για τη Go.
@ -108,7 +108,7 @@ _Η τελευταία ενημέρωση έγινε την [Τρίτη, 21 Νο
## Υποστήριξη ## Υποστήριξη
- To [HISTORY](HISTORY_GR.md#sa-10-march-2018--v1030) αρχείο είναι ο καλύτερος σας φίλος, περιέχει πληροφορίες σχετικά με τις τελευταίες λειτουργίες(features) και αλλαγές - To [HISTORY](HISTORY_GR.md#we-14-march-2018--v1040) αρχείο είναι ο καλύτερος σας φίλος, περιέχει πληροφορίες σχετικά με τις τελευταίες λειτουργίες(features) και αλλαγές
- Μήπως τυχαίνει να βρήκατε κάποιο bug; Δημοσιεύστε το στα [github issues](https://github.com/kataras/iris/issues) - Μήπως τυχαίνει να βρήκατε κάποιο bug; Δημοσιεύστε το στα [github issues](https://github.com/kataras/iris/issues)
- Έχετε οποιεσδήποτε ερωτήσεις ή πρέπει να μιλήσετε με κάποιον έμπειρο για την επίλυση ενός προβλήματος σε πραγματικό χρόνο; Ελάτε μαζί μας στην [συνομιλία κοινότητας](https://chat.iris-go.com) - Έχετε οποιεσδήποτε ερωτήσεις ή πρέπει να μιλήσετε με κάποιον έμπειρο για την επίλυση ενός προβλήματος σε πραγματικό χρόνο; Ελάτε μαζί μας στην [συνομιλία κοινότητας](https://chat.iris-go.com)
- Συμπληρώστε την αναφορά εμπειρίας χρήστη κάνοντας κλικ [εδώ](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link) - Συμπληρώστε την αναφορά εμπειρίας χρήστη κάνοντας κλικ [εδώ](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link)

View File

@ -2,7 +2,7 @@
<a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a> <a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a>
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.3-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) [![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.4-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases)
Iris - это быстрая, простая, но полнофункциональная и очень эффективная веб-платформа для Go. Iris - это быстрая, простая, но полнофункциональная и очень эффективная веб-платформа для Go.
@ -106,7 +106,7 @@ _Обновлено: [Вторник, 21 ноября 2017 г.](_benchmarks/READ
## Поддержка ## Поддержка
- Файл [HISTORY](HISTORY.md#sa-10-march-2018--v1030) - ваш лучший друг, он содержит информацию о последних особенностях и всех изменениях - Файл [HISTORY](HISTORY.md#we-14-march-2018--v1040) - ваш лучший друг, он содержит информацию о последних особенностях и всех изменениях
- Вы случайно обнаружили ошибку? Опубликуйте ее на [Github вопросы](https://github.com/kataras/iris/issues) - Вы случайно обнаружили ошибку? Опубликуйте ее на [Github вопросы](https://github.com/kataras/iris/issues)
- У Вас есть какие-либо вопросы или Вам нужно поговорить с кем-то, кто бы смог решить Вашу проблему в режиме реального времени? Присоединяйтесь к нам в [чате сообщества](https://chat.iris-go.com) - У Вас есть какие-либо вопросы или Вам нужно поговорить с кем-то, кто бы смог решить Вашу проблему в режиме реального времени? Присоединяйтесь к нам в [чате сообщества](https://chat.iris-go.com)
- Заполните наш отчет о пользовательском опыте на основе формы, нажав [здесь](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link) - Заполните наш отчет о пользовательском опыте на основе формы, нажав [здесь](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link)

View File

@ -2,7 +2,7 @@
<a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a> <a href="https://iris-go.com"> <img align="right" width="169px" src="https://iris-go.com/images/icon.svg?v=a" title="logo created by @merry.dii" /> </a>
[![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.3-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases) [![build status](https://img.shields.io/travis/kataras/iris/master.svg?style=flat-square)](https://travis-ci.org/kataras/iris)<!-- [![release](https://img.shields.io/github/release/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/releases)--> [![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=flat-square)](http://goreportcard.com/report/kataras/iris) [![vscode-iris](https://img.shields.io/badge/ext%20-vscode-0c77e3.svg?style=flat-square)](https://marketplace.visualstudio.com/items?itemName=kataras2006.iris)<!--[![github closed issues](https://img.shields.io/github/issues-closed-raw/kataras/iris.svg?style=flat-square)](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aclosed)--> [![chat](https://img.shields.io/badge/community-%20chat-00BCD4.svg?style=flat-square)](https://kataras.rocket.chat/channel/iris) [![view examples](https://img.shields.io/badge/learn%20by-examples-0077b3.svg?style=flat-square)](https://iris-go.com/v10/recipe) [![release](https://img.shields.io/badge/release%20-v10.4-0077b3.svg?style=flat-square)](https://github.com/kataras/iris/releases)
Iris 是一款超快、简洁高效的 Go 语言 Web开发框架。 Iris 是一款超快、简洁高效的 Go 语言 Web开发框架。
@ -102,7 +102,7 @@ _更新于: [2017年11月21日星期二](_benchmarks/README_UNIX.md)_
## 支持 ## 支持
- [更新记录](HISTORY_ZH.md#sa-10-march-2018--v1030) 是您最好的朋友,它包含有关最新功能和更改的信息 - [更新记录](HISTORY_ZH.md#we-14-march-2018--v1040) 是您最好的朋友,它包含有关最新功能和更改的信息
- 你碰巧找到了一个错误? 请提交 [github issues](https://github.com/kataras/iris/issues) - 你碰巧找到了一个错误? 请提交 [github issues](https://github.com/kataras/iris/issues)
- 您是否有任何疑问或需要与有经验的人士交谈以实时解决问题? [加入我们的聊天](https://chat.iris-go.com) - 您是否有任何疑问或需要与有经验的人士交谈以实时解决问题? [加入我们的聊天](https://chat.iris-go.com)
- [点击这里完成我们基于表单的用户体验报告](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link) - [点击这里完成我们基于表单的用户体验报告](https://docs.google.com/forms/d/e/1FAIpQLSdCxZXPANg_xHWil4kVAdhmh7EBBHQZ_4_xSZVDL-oCC_z5pA/viewform?usp=sf_link)

View File

@ -1 +1 @@
10.3.0:https://github.com/kataras/iris/blob/master/HISTORY.md#sa-10-march-2018--v1030 10.4.0:https://github.com/kataras/iris/blob/master/HISTORY.md#we-14-march-2018--v1040

View File

@ -310,6 +310,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
- [Favicon](file-server/favicon/main.go) - [Favicon](file-server/favicon/main.go)
- [Basic](file-server/basic/main.go) - [Basic](file-server/basic/main.go)
- [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go) - [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go)
- [Embedding Gziped Files Into App Executable File](file-server/embedding-gziped-files-into-app/main.go) **NEW**
- [Send/Force-Download Files](file-server/send-files/main.go) - [Send/Force-Download Files](file-server/send-files/main.go)
- Single Page Applications - Single Page Applications
* [single Page Application](file-server/single-page-application/basic/main.go) * [single Page Application](file-server/single-page-application/basic/main.go)

View File

@ -10,7 +10,8 @@ import (
// $ go build // $ go build
// $ ./embedding-files-into-app // $ ./embedding-files-into-app
// "physical" files are not used, you can delete the "assets" folder and run the example. // "physical" files are not used, you can delete the "assets" folder and run the example.
//
// See `file-server/embedding-gziped-files-into-app` example as well.
func newApp() *iris.Application { func newApp() *iris.Application {
app := iris.New() app := iris.New()

View File

@ -34,6 +34,7 @@ func (r resource) loadFromBase(dir string) string {
} }
result := string(b) result := string(b)
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
result = strings.Replace(result, "\n", "\r\n", -1) result = strings.Replace(result, "\n", "\r\n", -1)
} }

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,35 @@
package main
import (
"github.com/kataras/iris"
)
// NOTE: need different tool than the "embedding-files-into-app" example.
//
// Follow these steps first:
// $ go get -u github.com/kataras/bindata/cmd/bindata
// $ bindata ./assets/...
// $ go build
// $ ./embedding-gziped-files-into-app
// "physical" files are not used, you can delete the "assets" folder and run the example.
func newApp() *iris.Application {
app := iris.New()
// Note the `GzipAsset` and `GzipAssetNames` are different from `go-bindata`'s `Asset` and `AssetNames,
// that means that you can use both `go-bindata` and `bindata` tools,
// the `go-bindata` can be used for the view engine's `Binary` method
// and the `bindata` with the `StaticEmbeddedGzip` (x8 times faster than the StaticEmbeded with `go-bindata`).
app.StaticEmbeddedGzip("/static", "./assets", GzipAsset, GzipAssetNames)
return app
}
func main() {
app := newApp()
// http://localhost:8080/static/css/bootstrap.min.css
// http://localhost:8080/static/js/jquery-2.1.1.js
// http://localhost:8080/static/favicon.ico
app.Run(iris.Addr(":8080"))
}

View File

@ -0,0 +1,87 @@
package main
import (
"bytes"
"io/ioutil"
"path/filepath"
"runtime"
"strings"
"testing"
"github.com/kataras/iris/httptest"
"github.com/klauspost/compress/gzip"
)
type resource string
func (r resource) String() string {
return string(r)
}
func (r resource) strip(strip string) string {
s := r.String()
return strings.TrimPrefix(s, strip)
}
func (r resource) loadFromBase(dir string) string {
filename := r.String()
filename = r.strip("/static")
fullpath := filepath.Join(dir, filename)
b, err := ioutil.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
result := string(b)
if runtime.GOOS != "windows" {
result = strings.Replace(result, "\n", "\r\n", -1)
}
return result
}
var urls = []resource{
"/static/css/bootstrap.min.css",
"/static/js/jquery-2.1.1.js",
"/static/favicon.ico",
}
// if bindata's values matches with the assets/... contents
// and secondly if the StaticEmbedded had successfully registered
// the routes and gave the correct response.
func TestEmbeddingGzipFilesIntoApp(t *testing.T) {
app := newApp()
e := httptest.New(t, app)
if runtime.GOOS != "windows" {
// remove the embedded static favicon for !windows,
// it should be built for unix-specific in order to be work
urls = urls[0 : len(urls)-1]
}
for i, u := range urls {
url := u.String()
rawContents := u.loadFromBase("./assets")
response := e.GET(url).Expect()
if expected, got := response.Raw().StatusCode, httptest.StatusOK; expected != got {
t.Fatalf("[%d] of '%s': expected %d status code but got %d", i, url, expected, got)
}
func() {
reader, err := gzip.NewReader(bytes.NewBuffer(response.Content))
defer reader.Close()
if err != nil {
t.Fatalf("[%d] of '%s': %v", i, url, err)
}
buf := new(bytes.Buffer)
reader.WriteTo(buf)
if rawContents != buf.String() {
t.Fatalf("[%d] of '%s': expected body:\n%s but got:\n%s", i, url, rawContents, buf.String())
}
}()
}
}

View File

@ -22,7 +22,7 @@ func newApp() *iris.Application {
ctx.View("index.html") ctx.View("index.html")
}) })
assetHandler := app.StaticEmbeddedHandler("./public", Asset, AssetNames) assetHandler := iris.StaticEmbeddedHandler("./public", Asset, AssetNames, false) // keep that false if you use the `go-bindata` tool.
// as an alternative of SPA you can take a look at the /routing/dynamic-path/root-wildcard // as an alternative of SPA you can take a look at the /routing/dynamic-path/root-wildcard
// example too // example too
// or // or

View File

@ -2208,6 +2208,7 @@ var (
contentDispositionHeaderKey = "Content-Disposition" contentDispositionHeaderKey = "Content-Disposition"
cacheControlHeaderKey = "Cache-Control" cacheControlHeaderKey = "Cache-Control"
contentEncodingHeaderKey = "Content-Encoding" contentEncodingHeaderKey = "Content-Encoding"
gzipHeaderValue = "gzip"
acceptEncodingHeaderKey = "Accept-Encoding" acceptEncodingHeaderKey = "Accept-Encoding"
varyHeaderKey = "Vary" varyHeaderKey = "Vary"
) )
@ -2360,7 +2361,7 @@ func (ctx *context) StreamWriter(writer func(w io.Writer) bool) {
func (ctx *context) ClientSupportsGzip() bool { func (ctx *context) ClientSupportsGzip() bool {
if h := ctx.GetHeader(acceptEncodingHeaderKey); h != "" { if h := ctx.GetHeader(acceptEncodingHeaderKey); h != "" {
for _, v := range strings.Split(h, ";") { for _, v := range strings.Split(h, ";") {
if strings.Contains(v, "gzip") { // we do Contains because sometimes browsers has the q=, we don't use it atm. || strings.Contains(v,"deflate"){ if strings.Contains(v, gzipHeaderValue) { // we do Contains because sometimes browsers has the q=, we don't use it atm. || strings.Contains(v,"deflate"){
return true return true
} }
} }
@ -2915,8 +2916,10 @@ func (ctx *context) ServeContent(content io.ReadSeeker, filename string, modtime
ctx.SetLastModified(modtime) ctx.SetLastModified(modtime)
var out io.Writer var out io.Writer
if gzipCompression && ctx.ClientSupportsGzip() { if gzipCompression && ctx.ClientSupportsGzip() {
ctx.writer.Header().Add(varyHeaderKey, acceptEncodingHeaderKey) AddGzipHeaders(ctx.writer)
ctx.Header(contentEncodingHeaderKey, "gzip")
// ctx.writer.Header().Add(varyHeaderKey, acceptEncodingHeaderKey)
// ctx.Header(contentEncodingHeaderKey,gzipHeaderValue)
gzipWriter := acquireGzipWriter(ctx.writer) gzipWriter := acquireGzipWriter(ctx.writer)
defer releaseGzipWriter(gzipWriter) defer releaseGzipWriter(gzipWriter)
@ -3191,7 +3194,6 @@ func (ctx *context) Exec(method string, path string) {
req.RequestURI = path req.RequestURI = path
req.URL.Path = path req.URL.Path = path
req.Method = method req.Method = method
req.Host = req.Host
// execute the route from the (internal) context router // execute the route from the (internal) context router
// this way we keep the sessions and the values // this way we keep the sessions and the values

View File

@ -165,12 +165,11 @@ func (w *GzipResponseWriter) WriteNow(contents []byte) (int, error) {
// Or a better idea, acquire and adapt the gzip writer on-time when is not disabled. // Or a better idea, acquire and adapt the gzip writer on-time when is not disabled.
// So that is not needed any more: // So that is not needed any more:
// w.gzipWriter.Reset(noop) // w.gzipWriter.Reset(noop)
return w.ResponseWriter.Write(contents) return w.ResponseWriter.Write(contents)
} }
w.ResponseWriter.Header().Add(varyHeaderKey, "Accept-Encoding") AddGzipHeaders(w.ResponseWriter)
w.ResponseWriter.Header().Add(contentEncodingHeaderKey, "gzip")
// if not `WriteNow` but "Content-Length" header // if not `WriteNow` but "Content-Length" header
// is exists, then delete it before `.Write` // is exists, then delete it before `.Write`
// Content-Length should not be there. // Content-Length should not be there.
@ -178,6 +177,13 @@ func (w *GzipResponseWriter) WriteNow(contents []byte) (int, error) {
return writeGzip(w.ResponseWriter, contents) return writeGzip(w.ResponseWriter, contents)
} }
// AddGzipHeaders just adds the headers "Vary" to "Accept-Encoding"
// and "Content-Encoding" to "gzip".
func AddGzipHeaders(w ResponseWriter) {
w.Header().Add(varyHeaderKey, acceptEncodingHeaderKey)
w.Header().Add(contentEncodingHeaderKey, gzipHeaderValue)
}
// FlushResponse validates the response headers in order to be compatible with the gzip written data // FlushResponse validates the response headers in order to be compatible with the gzip written data
// and writes the data to the underline ResponseWriter. // and writes the data to the underline ResponseWriter.
func (w *GzipResponseWriter) FlushResponse() { func (w *GzipResponseWriter) FlushResponse() {

View File

@ -13,7 +13,7 @@ import (
const ( const (
// Version is the string representation of the current local Iris Web Framework version. // Version is the string representation of the current local Iris Web Framework version.
Version = "10.3.0" Version = "10.4.0"
) )
// CheckForUpdates checks for any available updates // CheckForUpdates checks for any available updates

View File

@ -627,18 +627,6 @@ func (api *APIBuilder) StaticContent(reqPath string, cType string, content []byt
return api.registerResourceRoute(reqPath, h) return api.registerResourceRoute(reqPath, h)
} }
// StaticEmbeddedHandler returns a Handler which can serve
// embedded into executable files.
//
//
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
func (api *APIBuilder) StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler {
// Notes:
// This doesn't need to be APIBuilder's scope,
// but we'll keep it here for consistently.
return StaticEmbeddedHandler(vdir, assetFn, namesFn)
}
// StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly // StaticEmbedded used when files are distributed inside the app executable, using go-bindata mostly
// First parameter is the request path, the path which the files in the vdir will be served to, for example "/static" // First parameter is the request path, the path which the files in the vdir will be served to, for example "/static"
// Second parameter is the (virtual) directory path, for example "./assets" // Second parameter is the (virtual) directory path, for example "./assets"
@ -647,8 +635,25 @@ func (api *APIBuilder) StaticEmbeddedHandler(vdir string, assetFn func(name stri
// //
// Returns the GET *Route. // Returns the GET *Route.
// //
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server // Example: https://github.com/kataras/iris/tree/master/_examples/file-server/embedding-files-into-app
func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) *Route { func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) *Route {
return api.staticEmbedded(requestPath, vdir, assetFn, namesFn, false)
}
// StaticEmbeddedGzip registers a route which can serve embedded gziped files
// that are embedded using the https://github.com/kataras/bindata tool and only.
// It's 8 times faster than the `StaticEmbeddedHandler` with `go-bindata` but
// it sends gzip response only, so the client must be aware that is expecting a gzip body
// (browsers and most modern browsers do that, so you can use it without fair).
//
//
// Example: https://github.com/kataras/iris/tree/master/_examples/file-server/embedding-gziped-files-into-app
func (api *APIBuilder) StaticEmbeddedGzip(requestPath string, vdir string, gzipAssetFn func(name string) ([]byte, error), gzipNamesFn func() []string) *Route {
return api.staticEmbedded(requestPath, vdir, gzipAssetFn, gzipNamesFn, true)
}
// look fs.go#StaticEmbeddedHandler
func (api *APIBuilder) staticEmbedded(requestPath string, vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string, assetsGziped bool) *Route {
fullpath := joinPath(api.relativePath, requestPath) fullpath := joinPath(api.relativePath, requestPath)
// if subdomain, // if subdomain,
// here we get the full path of the path only, // here we get the full path of the path only,
@ -656,9 +661,10 @@ func (api *APIBuilder) StaticEmbedded(requestPath string, vdir string, assetFn f
// and we need that path to call the `StripPrefix`. // and we need that path to call the `StripPrefix`.
_, fullpath = splitSubdomainAndPath(fullpath) _, fullpath = splitSubdomainAndPath(fullpath)
requestPath = joinPath(fullpath, WildcardParam("file")) paramName := "file"
requestPath = joinPath(requestPath, WildcardParam(paramName))
h := api.StaticEmbeddedHandler(vdir, assetFn, namesFn) h := StaticEmbeddedHandler(vdir, assetFn, namesFn, assetsGziped)
if fullpath != "/" { if fullpath != "/" {
h = StripPrefix(fullpath, h) h = StripPrefix(fullpath, h)
@ -745,16 +751,17 @@ func (api *APIBuilder) Favicon(favPath string, requestPath ...string) *Route {
// //
// Returns the GET *Route. // Returns the GET *Route.
func (api *APIBuilder) StaticWeb(requestPath string, systemPath string) *Route { func (api *APIBuilder) StaticWeb(requestPath string, systemPath string) *Route {
paramName := "file"
fullpath := joinPath(api.relativePath, requestPath) fullpath := joinPath(api.relativePath, requestPath)
// if subdomain, // if subdomain,
// here we get the full path of the path only, // here we get the full path of the path only,
// because a subdomain can have parties as well // because a subdomain can have parties as well
// and we need that path to call the `StripPrefix`. // and we need that path to call the `StripPrefix`.
_, fullpath = splitSubdomainAndPath(fullpath) _, fullpath = splitSubdomainAndPath(fullpath)
requestPath = joinPath(fullpath, WildcardParam(paramName)) paramName := "file"
requestPath = joinPath(requestPath, WildcardParam(paramName))
h := NewStaticHandlerBuilder(systemPath).Listing(false).Build() h := NewStaticHandlerBuilder(systemPath).Listing(false).Build()
if fullpath != "/" { if fullpath != "/" {

View File

@ -21,12 +21,11 @@ import (
"github.com/kataras/iris/context" "github.com/kataras/iris/context"
) )
// StaticEmbeddedHandler returns a Handler which can serve // StaticEmbeddedHandler returns a Handler which can serve embedded files
// embedded into executable files. // that are embedded using the go-bindata tool(assetsGziped = false) or the kataras/bindata tool (assetsGziped = true).
//
// //
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server // Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string) context.Handler { func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error), namesFn func() []string, assetsGziped bool) context.Handler {
// Depends on the command the user gave to the go-bindata // Depends on the command the user gave to the go-bindata
// the assset path (names) may be or may not be prepended with a slash. // the assset path (names) may be or may not be prepended with a slash.
// What we do: we remove the ./ from the vdir which should be // What we do: we remove the ./ from the vdir which should be
@ -63,6 +62,7 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
modtime := time.Now() modtime := time.Now()
h := func(ctx context.Context) { h := func(ctx context.Context) {
reqPath := strings.TrimPrefix(ctx.Request().URL.Path, "/"+vdir) reqPath := strings.TrimPrefix(ctx.Request().URL.Path, "/"+vdir)
// i.e : /css/main.css // i.e : /css/main.css
@ -80,9 +80,17 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
buf, err := assetFn(path) // remove the first slash buf, err := assetFn(path) // remove the first slash
if assetsGziped {
// this will add the "Vary" : "Accept-Encoding"
// and "Content-Encoding": "gzip"
// headers.
context.AddGzipHeaders(ctx.ResponseWriter())
}
if err != nil { if err != nil {
continue continue
} }
ctx.ContentType(cType) ctx.ContentType(cType)
if _, err := ctx.WriteWithExpiration(buf, modtime); err != nil { if _, err := ctx.WriteWithExpiration(buf, modtime); err != nil {
ctx.StatusCode(http.StatusInternalServerError) ctx.StatusCode(http.StatusInternalServerError)
@ -93,7 +101,6 @@ func StaticEmbeddedHandler(vdir string, assetFn func(name string) ([]byte, error
// not found or error // not found or error
ctx.NotFound() ctx.NotFound()
} }
return h return h
@ -140,6 +147,7 @@ type fsHandler struct {
// user options, only directory is required. // user options, only directory is required.
directory http.Dir directory http.Dir
listDirectories bool listDirectories bool
gzip bool
// these are init on the Build() call // these are init on the Build() call
filesystem http.FileSystem filesystem http.FileSystem
once sync.Once once sync.Once
@ -183,18 +191,17 @@ func NewStaticHandlerBuilder(dir string) StaticHandlerBuilder {
} }
} }
// Gzip if enable is true then gzip compression is enabled for this static directory // Gzip if enable is true then gzip compression is enabled for this static directory.
// Defaults to false //
// Defaults to false.
func (w *fsHandler) Gzip(enable bool) StaticHandlerBuilder { func (w *fsHandler) Gzip(enable bool) StaticHandlerBuilder {
w.begin = append(w.begin, func(ctx context.Context) { w.gzip = enable
ctx.Gzip(true)
ctx.Next()
})
return w return w
} }
// Listing turn on/off the 'show files and directories'. // Listing turn on/off the 'show files and directories'.
// Defaults to false //
// Defaults to false.
func (w *fsHandler) Listing(listDirectoriesOnOff bool) StaticHandlerBuilder { func (w *fsHandler) Listing(listDirectoriesOnOff bool) StaticHandlerBuilder {
w.listDirectories = listDirectoriesOnOff w.listDirectories = listDirectoriesOnOff
return w return w
@ -243,9 +250,15 @@ func (w *fsHandler) Build() context.Handler {
// Note the request.url.path is changed but request.RequestURI is not // Note the request.url.path is changed but request.RequestURI is not
// so on custom errors we use the requesturi instead. // so on custom errors we use the requesturi instead.
// this can be changed // this can be changed.
// take the gzip setting.
gzipEnabled := w.gzip
if !gzipEnabled {
// if false then check if the dev did something like `ctx.Gzip(true)`.
_, gzipEnabled = ctx.ResponseWriter().(*context.GzipResponseWriter)
}
_, gzipEnabled := ctx.ResponseWriter().(*context.GzipResponseWriter)
_, prevStatusCode := serveFile(ctx, _, prevStatusCode := serveFile(ctx,
w.filesystem, w.filesystem,
path.Clean(upath), path.Clean(upath),
@ -272,15 +285,10 @@ func (w *fsHandler) Build() context.Handler {
return return
} }
// go to the next middleware // go to the next middleware, if any.
ctx.Next() ctx.Next()
} }
if len(w.begin) > 0 {
handlers := append(w.begin[0:], fileserver)
w.handler = func(ctx context.Context) {
ctx.Do(handlers)
}
}
w.handler = fileserver w.handler = fileserver
}) })
@ -294,10 +302,10 @@ func (w *fsHandler) Build() context.Handler {
// replying with an HTTP 404 not found error. // replying with an HTTP 404 not found error.
// //
// Usage: // Usage:
// fileserver := iris.StaticHandler("./static_files", false, false) // fileserver := Party#StaticHandler("./static_files", false, false)
// h := router.StripPrefix("/static", fileserver) // h := router.StripPrefix("/static", fileserver)
// app.Get("/static", h) // app.Get("/static/{f:path}", h)
// // app.Head("/static/{f:path}", h)
func StripPrefix(prefix string, h context.Handler) context.Handler { func StripPrefix(prefix string, h context.Handler) context.Handler {
if prefix == "" { if prefix == "" {
return h return h
@ -821,7 +829,7 @@ func serveFile(ctx context.Context, fs http.FileSystem, name string, redirect bo
// try to find and send the correct content type based on the filename // try to find and send the correct content type based on the filename
// and the binary data inside "f". // and the binary data inside "f".
detectOrWriteContentType(ctx, d.Name(), f) // detectOrWriteContentType(ctx, d.Name(), f)
return "", http.StatusOK return "", http.StatusOK
} }

View File

@ -73,7 +73,7 @@ func joinPath(path1 string, path2 string) string {
// cleanPath applies the following rules // cleanPath applies the following rules
// iteratively until no further processing can be done: // iteratively until no further processing can be done:
// //
// 1. Replace multiple slashes with a single slash. // 1. Replace multiple slashes with a single slash.
// 2. Replace '\' with '/' // 2. Replace '\' with '/'
// 3. Replace "\\" with '/' // 3. Replace "\\" with '/'
// 4. Ignore anything inside '{' and '}' // 4. Ignore anything inside '{' and '}'
@ -87,7 +87,7 @@ func cleanPath(s string) string {
return "/" return "/"
} }
// remove suffix "/". // remove suffix "/", if it's root "/" then it will add it as a prefix below.
if lidx := len(s) - 1; s[lidx] == '/' { if lidx := len(s) - 1; s[lidx] == '/' {
s = s[:lidx] s = s[:lidx]
} }

View File

@ -9,6 +9,8 @@ func TestCleanPath(t *testing.T) {
path string path string
expected string expected string
}{ }{
{"/",
"/"},
{"noslashPrefix", {"noslashPrefix",
"/noslashPrefix"}, "/noslashPrefix"},
{"slashSuffix/", {"slashSuffix/",

2
doc.go
View File

@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub:
Current Version Current Version
10.3.0 10.4.0
Installation Installation

12
iris.go
View File

@ -346,6 +346,18 @@ var (
// //
// Examples: https://github.com/kataras/iris/tree/master/_examples/file-server // Examples: https://github.com/kataras/iris/tree/master/_examples/file-server
StaticEmbeddedHandler = router.StaticEmbeddedHandler StaticEmbeddedHandler = router.StaticEmbeddedHandler
// StripPrefix returns a handler that serves HTTP requests
// by removing the given prefix from the request URL's Path
// and invoking the handler h. StripPrefix handles a
// request for a path that doesn't begin with prefix by
// replying with an HTTP 404 not found error.
//
// Usage:
// fileserver := Party#StaticHandler("./static_files", false, false)
// h := iris.StripPrefix("/static", fileserver)
// app.Get("/static/{f:path}", h)
// app.Head("/static/{f:path}", h)
StripPrefix = router.StripPrefix
// Gzip is a middleware which enables writing // Gzip is a middleware which enables writing
// using gzip compression, if client supports. // using gzip compression, if client supports.
// //