mirror of
https://github.com/kataras/iris.git
synced 2026-05-11 08:33:47 +00:00
create the new FileServer and HandleDir, deprecate the rest APIBuilder/Party static methods and more
relative: https://github.com/kataras/iris/issues/1283 and removing pongo2 from vendor: https://github.com/kataras/iris/issues/1284 Former-commit-id: 3ec57b349f99faca2b8e36d9f7252db0b6ea080d
This commit is contained in:
@@ -149,7 +149,7 @@ Navigate through examples for a better understanding.
|
||||
- [Write your own custom parameter types](routing/macros/main.go)
|
||||
- [Reverse routing](routing/reverse/main.go)
|
||||
- [Custom Router (high-level)](routing/custom-high-level-router/main.go)
|
||||
- [Custom Wrapper](routing/custom-wrapper/main.go)
|
||||
- [Custom Wrapper](routing/custom-wrapper/main.go) **UPDATED**
|
||||
- Custom Context
|
||||
* [method overriding](routing/custom-context/method-overriding/main.go)
|
||||
* [new implementation](routing/custom-context/new-implementation/main.go)
|
||||
@@ -366,14 +366,14 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
|
||||
### File Server
|
||||
|
||||
- [Favicon](file-server/favicon/main.go)
|
||||
- [Basic](file-server/basic/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)
|
||||
- [Basic](file-server/basic/main.go) **UPDATED**
|
||||
- [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go) **UPDATED**
|
||||
- [Embedding Gziped Files Into App Executable File](file-server/embedding-gziped-files-into-app/main.go) **UPDATED**
|
||||
- [Send/Force-Download Files](file-server/send-files/main.go)
|
||||
- Single Page Applications
|
||||
* [single Page Application](file-server/single-page-application/basic/main.go)
|
||||
* [embedded Single Page Application](file-server/single-page-application/embedded-single-page-application/main.go)
|
||||
* [embedded Single Page Application with other routes](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go)
|
||||
* [single Page Application](file-server/single-page-application/basic/main.go) **UPDATED**
|
||||
* [embedded Single Page Application](file-server/single-page-application/embedded-single-page-application/main.go) **UPDATED**
|
||||
* [embedded Single Page Application with other routes](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go) **UPDATED**
|
||||
|
||||
### How to Read from `context.Request() *http.Request`
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
### 概览
|
||||
|
||||
- [Hello world!](hello-world/main.go)
|
||||
- [Hello WebAssemply!](webassembly/basic/main.go) **NEW**
|
||||
- [Hello WebAssemply!](webassembly/basic/main.go)
|
||||
- [基础](overview/main.go)
|
||||
- [教程: 在线人数](tutorial/online-visitors/main.go)
|
||||
- [教程: 一个“待完成”MVC Application基于Iris和Vue.js](https://hackernoon.com/a-todo-mvc-application-using-iris-and-vue-js-5019ff870064)
|
||||
@@ -21,7 +21,7 @@
|
||||
- [教程: DropzoneJS 上传](tutorial/dropzonejs)
|
||||
- [教程: Caddy 服务器使用](tutorial/caddy)
|
||||
- [教程: Iris + MongoDB](https://medium.com/go-language/iris-go-framework-mongodb-552e349eab9c)
|
||||
- [教程: Apache Kafka的API](tutorial/api-for-apache-kafka) **NEW**
|
||||
- [教程: Apache Kafka的API](tutorial/api-for-apache-kafka)
|
||||
|
||||
### 目录结构
|
||||
|
||||
@@ -105,10 +105,10 @@ app.Get("{root:path}", rootWildcardHandler)
|
||||
- [自定义 HTTP 错误](routing/http-errors/main.go)
|
||||
- [动态路径](routing/dynamic-path/main.go)
|
||||
* [根级通配符路径](routing/dynamic-path/root-wildcard/main.go)
|
||||
- [编写你自己的参数类型](routing/macros/main.go) **NEW**
|
||||
- [编写你自己的参数类型](routing/macros/main.go)
|
||||
- [反向路由](routing/reverse/main.go)
|
||||
- [自定义路由(高层级)](routing/custom-high-level-router/main.go) **NEW**
|
||||
- [自定义包装](routing/custom-wrapper/main.go)
|
||||
- [自定义路由(高层级)](routing/custom-high-level-router/main.go)
|
||||
- [自定义包装](routing/custom-wrapper/main.go) **更新**
|
||||
- 自定义上下文
|
||||
* [方法重写](routing/custom-context/method-overriding/main.go)
|
||||
* [新实现方式](routing/custom-context/new-implementation/main.go)
|
||||
@@ -121,8 +121,8 @@ app.Get("{root:path}", rootWildcardHandler)
|
||||
|
||||
- [基础](hero/basic/main.go)
|
||||
- [概览](hero/overview)
|
||||
- [Sessions](hero/sessions) **NEW**
|
||||
- [另一种依赖注入的例子和通常的较好实践](hero/smart-contract/main.go) **NEW**
|
||||
- [Sessions](hero/sessions)
|
||||
- [另一种依赖注入的例子和通常的较好实践](hero/smart-contract/main.go) **新**
|
||||
|
||||
### MVC 模式
|
||||
|
||||
@@ -255,14 +255,14 @@ func(c *ExampleController) Get() string |
|
||||
|
||||
参考下面的示例
|
||||
|
||||
- [Hello world](mvc/hello-world/main.go) **UPDATED**
|
||||
- [Session Controller](mvc/session-controller/main.go) **UPDATED**
|
||||
- [Overview - Plus Repository and Service layers](mvc/overview) **UPDATED**
|
||||
- [Login showcase - Plus Repository and Service layers](mvc/login) **UPDATED**
|
||||
- [Singleton](mvc/singleton) **NEW**
|
||||
- [Websocket Controller](mvc/websocket) **NEW**
|
||||
- [Register Middleware](mvc/middleware) **NEW**
|
||||
- [Vue.js Todo MVC](tutorial/vuejs-todo-mvc) **NEW**
|
||||
- [Hello world](mvc/hello-world/main.go) **更新**
|
||||
- [Session Controller](mvc/session-controller/main.go) **更新**
|
||||
- [Overview - Plus Repository and Service layers](mvc/overview) **更新**
|
||||
- [Login showcase - Plus Repository and Service layers](mvc/login) **更新**
|
||||
- [Singleton](mvc/singleton) **新**
|
||||
- [Websocket Controller](mvc/websocket) **新**
|
||||
- [Register Middleware](mvc/middleware) **新**
|
||||
- [Vue.js Todo MVC](tutorial/vuejs-todo-mvc) **新**
|
||||
|
||||
### 子域名
|
||||
|
||||
@@ -316,14 +316,14 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
|
||||
### 文件服务器
|
||||
|
||||
- [Favicon](file-server/favicon/main.go)
|
||||
- [基础操作](file-server/basic/main.go)
|
||||
- [把文件嵌入应用的可执行文件](file-server/embedding-files-into-app/main.go)
|
||||
- [嵌入Gzip压缩的文件到可咨询文件](file-server/embedding-gziped-files-into-app/main.go) **NEW**
|
||||
- [基础操作](file-server/basic/main.go) **更新**
|
||||
- [把文件嵌入应用的可执行文件](file-server/embedding-files-into-app/main.go) **更新**
|
||||
- [嵌入Gzip压缩的文件到可咨询文件](file-server/embedding-gziped-files-into-app/main.go) **更新**
|
||||
- [上传/(强制)下载文件](file-server/send-files/main.go)
|
||||
- 单页面应用(Single Page Applications)
|
||||
* [单页面应用](file-server/single-page-application/basic/main.go)
|
||||
* [嵌入式(embedded)单页面应用](file-server/single-page-application/embedded-single-page-application/main.go)
|
||||
* [使用额外路由的嵌入式单页面应用](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go)
|
||||
* [单页面应用](file-server/single-page-application/basic/main.go) **更新**
|
||||
* [嵌入式(embedded)单页面应用](file-server/single-page-application/embedded-single-page-application/main.go) **更新**
|
||||
* [使用额外路由的嵌入式单页面应用](file-server/single-page-application/embedded-single-page-application-with-other-routes/main.go) **更新**
|
||||
|
||||
### 如何读取`context.Request() *http.Request`
|
||||
|
||||
@@ -346,7 +346,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
|
||||
- [写入Gzip压缩](http_responsewriter/write-gzip/main.go)
|
||||
- [流输出Stream Writer](http_responsewriter/stream-writer/main.go)
|
||||
- [数据传递Transactions](http_responsewriter/transactions/main.go)
|
||||
- [SSE](http_responsewriter/sse/main.go) **NEW**
|
||||
- [SSE](http_responsewriter/sse/main.go)
|
||||
- [SSE (third-party package usage for server sent events第三方库SSE)](http_responsewriter/sse-third-party/main.go)
|
||||
|
||||
> The `context/context#ResponseWriter()` returns an enchament version of a http.ResponseWriter, these examples show some places where the Context uses this object. Besides that you can use it as you did before iris.
|
||||
@@ -430,7 +430,7 @@ iris websocket库依赖于它自己的[包](https://github.com/kataras/iris/tree
|
||||
设计这个包的目的是处理原始websockets,虽然它的API和著名的[socket.io](https://socket.io)很像。我最近读了一片文章,并且对我
|
||||
决定给iris设计一个**快速的**websocket**限定**包并且不是一个向后传递类socket.io的包。你可以阅读这个链接里的文章https://medium.com/@ivanderbyl/why-you-don-t-need-socket-io-6848f1c871cd。
|
||||
|
||||
- [Basic](websocket/basic) **NEW**
|
||||
- [Basic](websocket/basic) **新**
|
||||
* [Server](websocket/basic/server.go)
|
||||
* [Go Client](websocket/basic/go-client/client.go)
|
||||
* [Browser Client](websocket/basic/browser/index.html)
|
||||
|
||||
4
_examples/cache/simple/main.go
vendored
4
_examples/cache/simple/main.go
vendored
@@ -74,7 +74,7 @@ func writeMarkdown(ctx iris.Context) {
|
||||
ctx.Markdown(markdownContents)
|
||||
}
|
||||
|
||||
/* Note that `StaticWeb` does use the browser's disk caching by-default
|
||||
therefore, register the cache handler AFTER any StaticWeb calls,
|
||||
/* Note that `HandleDir` does use the browser's disk caching by-default
|
||||
therefore, register the cache handler AFTER any HandleDir calls,
|
||||
for a faster solution that server doesn't need to keep track of the response
|
||||
navigate to https://github.com/kataras/iris/blob/master/_examples/cache/client-side/main.go */
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
just a text.
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Hello App2App3 index</h1>
|
||||
1
_examples/file-server/basic/assets/app2/index.html
Normal file
1
_examples/file-server/basic/assets/app2/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Hello App2 index</h1>
|
||||
@@ -4,38 +4,48 @@ import (
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
||||
func main() {
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
|
||||
app.Favicon("./assets/favicon.ico")
|
||||
|
||||
// enable gzip, optionally:
|
||||
// if used before the `StaticXXX` handlers then
|
||||
// the content byte range feature is gone.
|
||||
// recommend: turn off for large files especially
|
||||
// when server has low memory,
|
||||
// turn on for medium-sized files
|
||||
// or for large-sized files if they are zipped already,
|
||||
// i.e "zippedDir/file.gz"
|
||||
//
|
||||
// app.Use(iris.Gzip)
|
||||
|
||||
// first parameter is the request path
|
||||
// second is the system directory
|
||||
//
|
||||
// app.StaticWeb("/css", "./assets/css")
|
||||
// app.StaticWeb("/js", "./assets/js")
|
||||
//
|
||||
app.StaticWeb("/static", "./assets")
|
||||
// app.HandleDir("/css", "./assets/css")
|
||||
// app.HandleDir("/js", "./assets/js")
|
||||
|
||||
app.HandleDir("/static", "./assets", iris.DirOptions{
|
||||
// Defaults to "/index.html", if request path is ending with **/*/$IndexName
|
||||
// then it redirects to **/*(/) which another handler is handling it,
|
||||
// that another handler, called index handler, is auto-registered by the framework
|
||||
// if end developer does not managed to handle it by hand.
|
||||
IndexName: "/index.html",
|
||||
// When files should served under compression.
|
||||
Gzip: false,
|
||||
// List the files inside the current requested directory if `IndexName` not found.
|
||||
ShowList: false,
|
||||
// If `ShowList` is true then this function will be used instead of the default one to show the list of files of a current requested directory(dir).
|
||||
// DirList: func(ctx context.Context, dirName string, dir http.File) error { ... }
|
||||
//
|
||||
// Optional validator that loops through each requested resource.
|
||||
// AssetValidator: func(ctx iris.Context, name string) bool { ... }
|
||||
})
|
||||
|
||||
// You can also register any index handler manually, order of registration does not matter:
|
||||
// app.Get("/static", [...custom middleware...], func(ctx iris.Context) {
|
||||
// [...custom code...]
|
||||
// ctx.ServeFile("./assets/index.html", false)
|
||||
// })
|
||||
|
||||
// http://localhost:8080/static
|
||||
// http://localhost:8080/static/css/main.css
|
||||
// http://localhost:8080/static/js/jquery-2.1.1.js
|
||||
// http://localhost:8080/static/favicon.ico
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
// Note:
|
||||
// Routing doesn't allows something .StaticWeb("/", "./assets")
|
||||
//
|
||||
// To see how you can wrap the router in order to achieve
|
||||
// wildcard on root path, see "single-page-application".
|
||||
return app
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := newApp()
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
93
_examples/file-server/basic/main_test.go
Normal file
93
_examples/file-server/basic/main_test.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
type resource string
|
||||
|
||||
func (r resource) contentType() string {
|
||||
switch filepath.Ext(r.String()) {
|
||||
case ".js":
|
||||
return "application/javascript"
|
||||
case ".css":
|
||||
return "text/css"
|
||||
case ".ico":
|
||||
return "image/x-icon"
|
||||
case ".html", "":
|
||||
return "text/html"
|
||||
default:
|
||||
return "text/plain"
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
if filepath.Ext(filename) == "" {
|
||||
// root /.
|
||||
filename = filename + "/index.html"
|
||||
}
|
||||
|
||||
fullpath := filepath.Join(dir, filename)
|
||||
|
||||
b, err := ioutil.ReadFile(fullpath)
|
||||
if err != nil {
|
||||
panic(fullpath + " failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
result := string(b)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func TestFileServerBasic(t *testing.T) {
|
||||
var urls = []resource{
|
||||
"/static/css/main.css",
|
||||
"/static/js/jquery-2.1.1.js",
|
||||
"/static/favicon.ico",
|
||||
"/static/app2",
|
||||
"/static/app2/app2app3",
|
||||
"/static",
|
||||
}
|
||||
|
||||
app := newApp()
|
||||
// route := app.GetRouteReadOnly("GET/{file:path}")
|
||||
// if route == nil {
|
||||
// app.Logger().Fatalf("expected a route to serve files")
|
||||
// }
|
||||
|
||||
// if expected, got := "./assets", route.StaticDir(); expected != got {
|
||||
// app.Logger().Fatalf("expected route's static directory to be: '%s' but got: '%s'", expected, got)
|
||||
// }
|
||||
|
||||
// if !route.StaticDirContainsIndex() {
|
||||
// app.Logger().Fatalf("epxected ./assets to contain an %s file", "/index.html")
|
||||
// }
|
||||
|
||||
e := httptest.New(t, app)
|
||||
for _, u := range urls {
|
||||
url := u.String()
|
||||
contents := u.loadFromBase("./assets")
|
||||
|
||||
e.GET(url).Expect().
|
||||
Status(httptest.StatusOK).
|
||||
ContentType(u.contentType(), app.ConfigurationReadOnly().GetCharset()).
|
||||
Body().Equal(contents)
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,14 @@ import (
|
||||
// See `file-server/embedding-gziped-files-into-app` example as well.
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
app.Logger().SetLevel("debug")
|
||||
|
||||
app.StaticEmbedded("/static", "./assets", Asset, AssetNames)
|
||||
app.HandleDir("/static", "./assets", iris.DirOptions{
|
||||
Asset: Asset,
|
||||
AssetInfo: AssetInfo,
|
||||
AssetNames: AssetNames,
|
||||
ShowList: true,
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -66,12 +66,21 @@ var urls = []resource{
|
||||
}
|
||||
|
||||
// if bindata's values matches with the assets/... contents
|
||||
// and secondly if the StaticEmbedded had successfully registered
|
||||
// and secondly if the HandleDir had successfully registered
|
||||
// the routes and gave the correct response.
|
||||
func TestEmbeddingFilesIntoApp(t *testing.T) {
|
||||
app := newApp()
|
||||
e := httptest.New(t, app)
|
||||
|
||||
route := app.GetRouteReadOnly("GET/static/{file:path}")
|
||||
if route == nil {
|
||||
t.Fatalf("expected a route to serve embedded files")
|
||||
}
|
||||
|
||||
if len(route.StaticSites()) > 0 {
|
||||
t.Fatalf("not expected a static site, the ./assets directory or its subdirectories do not contain any index.html")
|
||||
}
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// remove the embedded static favicon for !windows,
|
||||
// it should be built for unix-specific in order to be work
|
||||
|
||||
@@ -16,12 +16,13 @@ import (
|
||||
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)
|
||||
|
||||
// Note the `GzipAsset` and `GzipAssetNames` are different from `go-bindata`'s `Asset`,
|
||||
// do not set the `Gzip` option to true, it's already managed by the kataras/bindata.
|
||||
app.HandleDir("/static", "./assets", iris.DirOptions{
|
||||
Asset: GzipAsset,
|
||||
AssetInfo: GzipAssetInfo,
|
||||
AssetNames: GzipAssetNames,
|
||||
})
|
||||
return app
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ var urls = []resource{
|
||||
}
|
||||
|
||||
// if bindata's values matches with the assets/... contents
|
||||
// and secondly if the StaticEmbedded had successfully registered
|
||||
// and secondly if the HandleDir had successfully registered
|
||||
// the routes and gave the correct response.
|
||||
func TestEmbeddingGzipFilesIntoApp(t *testing.T) {
|
||||
app := newApp()
|
||||
|
||||
@@ -20,15 +20,7 @@ func newApp() *iris.Application {
|
||||
ctx.View("index.html")
|
||||
})
|
||||
|
||||
// or just serve index.html as it is:
|
||||
// app.Get("/{f:path}", func(ctx iris.Context) {
|
||||
// ctx.ServeFile("index.html", false)
|
||||
// })
|
||||
|
||||
assetHandler := app.StaticHandler("./public", false, false)
|
||||
// as an alternative of SPA you can take a look at the /routing/dynamic-path/root-wildcard
|
||||
// example too
|
||||
app.SPA(assetHandler)
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
@@ -9,11 +9,21 @@ import "github.com/kataras/iris"
|
||||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
app.OnErrorCode(404, func(ctx iris.Context) {
|
||||
app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
|
||||
ctx.Writef("404 not found here")
|
||||
})
|
||||
|
||||
app.StaticEmbedded("/", "./public", Asset, AssetNames)
|
||||
app.HandleDir("/", "./public", iris.DirOptions{
|
||||
Asset: Asset,
|
||||
AssetInfo: AssetInfo,
|
||||
AssetNames: AssetNames,
|
||||
// IndexName: "index.html", // default.
|
||||
// If you want to show a list of embedded files when inside a directory without an index file:
|
||||
// ShowList: true,
|
||||
// DirList: func(ctx iris.Context, dirName string, f http.File) error {
|
||||
// // [Optional, custom code to show the html list].
|
||||
// }
|
||||
})
|
||||
|
||||
// Note:
|
||||
// if you want a dynamic index page then see the file-server/embedded-single-page-application
|
||||
|
||||
@@ -22,16 +22,11 @@ func newApp() *iris.Application {
|
||||
ctx.View("index.html")
|
||||
})
|
||||
|
||||
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
|
||||
// example too
|
||||
// or
|
||||
// app.StaticEmbedded if you don't want to redirect on index.html and simple serve your SPA app (recommended).
|
||||
|
||||
// public/index.html is a dynamic view, it's handlded by root,
|
||||
// and we don't want to be visible as a raw data, so we will
|
||||
// the return value of `app.SPA` to modify the `IndexNames` by;
|
||||
app.SPA(assetHandler).AddIndexName("index.html")
|
||||
app.HandleDir("/", "./public", iris.DirOptions{
|
||||
Asset: Asset,
|
||||
AssetInfo: AssetInfo,
|
||||
AssetNames: AssetNames,
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -45,11 +40,3 @@ func main() {
|
||||
// http://localhost:8080/css/main.css
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
// Note that app.Use/UseGlobal/Done will be executed
|
||||
// only to the registered routes like our index (app.Get("/", ..)).
|
||||
// The file server is clean, but you can still add middleware to that by wrapping its "assetHandler".
|
||||
//
|
||||
// With this method, unlike StaticWeb("/" , "./public") which is not working by-design anymore,
|
||||
// all custom http errors and all routes are working fine with a file server that is registered
|
||||
// to the root path of the server.
|
||||
|
||||
@@ -2,19 +2,56 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/middleware/logger"
|
||||
|
||||
"github.com/kataras/golog"
|
||||
)
|
||||
|
||||
const deleteFileOnExit = false
|
||||
|
||||
func newRequestLogger(newWriter io.Writer) iris.Handler {
|
||||
c := logger.Config{}
|
||||
|
||||
// we don't want to use the logger
|
||||
// to log requests to assets and etc
|
||||
c.AddSkipper(func(ctx iris.Context) bool {
|
||||
path := ctx.Path()
|
||||
for _, ext := range excludeExtensions {
|
||||
if strings.HasSuffix(path, ext) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
c.LogFuncCtx = func(ctx iris.Context, latency time.Duration) {
|
||||
datetime := time.Now().Format(ctx.Application().ConfigurationReadOnly().GetTimeFormat())
|
||||
customHandlerMessage := ctx.Values().GetString("log_message")
|
||||
|
||||
file, line := ctx.HandlerFileLine()
|
||||
source := fmt.Sprintf("%s:%d", file, line)
|
||||
|
||||
// this will just append a line without an array of javascript objects, readers of this file should read one line per log javascript object,
|
||||
// however, you can improve it even more, this is just a simple example on how to use the `LogFuncCtx`.
|
||||
jsonStr := fmt.Sprintf(`{"datetime":"%s","level":"%s","source":"%s","latency": "%s","status": %d,"method":"%s","path":"%s","message":"%s"}`,
|
||||
datetime, "INFO", source, latency.String(), ctx.GetStatusCode(), ctx.Method(), ctx.Path(), customHandlerMessage)
|
||||
|
||||
fmt.Fprintln(newWriter, jsonStr)
|
||||
}
|
||||
|
||||
return logger.New(c)
|
||||
}
|
||||
|
||||
func h(ctx iris.Context) {
|
||||
ctx.Values().Set("log_message", "something to give more info to the request logger")
|
||||
|
||||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
@@ -26,56 +63,21 @@ func main() {
|
||||
}
|
||||
}()
|
||||
|
||||
// Handle the logs by yourself using the `app.Logger#Handle` method.
|
||||
// Return true if that handled, otherwise will print to the screen.
|
||||
// You can also use the `app.Logger#SetOutput/AddOutput` to change or add
|
||||
// multi (io.Writer) outputs if you just want to print the message
|
||||
// somewhere else than the terminal screen.
|
||||
app.Logger().Handle(func(l *golog.Log) bool {
|
||||
_, fn, line, _ := runtime.Caller(5)
|
||||
|
||||
var (
|
||||
// formatted date string based on the `golog#TimeFormat`, which can be customized.
|
||||
// Or use the golog.Log#Time field to get the exact time.Time instance.
|
||||
datetime = l.FormatTime()
|
||||
// the log's message level.
|
||||
level = golog.GetTextForLevel(l.Level, false)
|
||||
// the log's message.
|
||||
message = l.Message
|
||||
// the source code line of where it is called,
|
||||
// this can differ on your app, see runtime.Caller(%d).
|
||||
source = fmt.Sprintf("%s#%d", fn, line)
|
||||
)
|
||||
|
||||
// You can always use a custom json structure and json.Marshal and logFile.Write(its result)
|
||||
// but it is faster to just build your JSON string by yourself as we do below.
|
||||
jsonStr := fmt.Sprintf(`{"datetime":"%s","level":"%s","message":"%s","source":"%s"}`, datetime, level, message, source)
|
||||
fmt.Fprintln(logFile, jsonStr)
|
||||
|
||||
/* Example output:
|
||||
{"datetime":"2018/10/31 13:13","level":"[INFO]","message":"My server started","source":"c:/mygopath/src/github.com/kataras/iris/_examples/http_request/request-logger/request-logger-file-json/main.go#71"}
|
||||
*/
|
||||
return true
|
||||
})
|
||||
|
||||
r := newRequestLogger()
|
||||
r := newRequestLogger(logFile)
|
||||
|
||||
app.Use(r)
|
||||
app.OnAnyErrorCode(r, func(ctx iris.Context) {
|
||||
ctx.HTML("<h1> Error: Please try <a href ='/'> this </a> instead.</h1>")
|
||||
})
|
||||
|
||||
h := func(ctx iris.Context) {
|
||||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
}
|
||||
|
||||
app.Get("/", h)
|
||||
|
||||
app.Get("/1", h)
|
||||
|
||||
app.Get("/2", h)
|
||||
|
||||
app.Logger().Info("My server started")
|
||||
app.Get("/", h)
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/1
|
||||
// http://localhost:8080/2
|
||||
@@ -92,29 +94,6 @@ var excludeExtensions = [...]string{
|
||||
".svg",
|
||||
}
|
||||
|
||||
func newRequestLogger() iris.Handler {
|
||||
c := logger.Config{
|
||||
Status: true,
|
||||
IP: true,
|
||||
Method: true,
|
||||
Path: true,
|
||||
}
|
||||
|
||||
// we don't want to use the logger
|
||||
// to log requests to assets and etc
|
||||
c.AddSkipper(func(ctx iris.Context) bool {
|
||||
path := ctx.Path()
|
||||
for _, ext := range excludeExtensions {
|
||||
if strings.HasSuffix(path, ext) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return logger.New(c)
|
||||
}
|
||||
|
||||
// get a filename based on the date, file logs works that way the most times
|
||||
// but these are just a sugar.
|
||||
func todayFilename() string {
|
||||
|
||||
@@ -85,10 +85,10 @@ func newRequestLogger() (h iris.Handler, close func() error) {
|
||||
return err
|
||||
}
|
||||
|
||||
c.LogFunc = func(now time.Time, latency time.Duration, status, ip, method, path string, message interface{}, headerMessage interface{}) {
|
||||
output := logger.Columnize(now.Format("2006/01/02 - 15:04:05"), latency, status, ip, method, path, message, headerMessage)
|
||||
c.LogFunc = func(endTime time.Time, latency time.Duration, status, ip, method, path string, message interface{}, headerMessage interface{}) {
|
||||
output := logger.Columnize(endTime.Format("2006/01/02 - 15:04:05"), latency, status, ip, method, path, message, headerMessage)
|
||||
logFile.Write([]byte(output))
|
||||
}
|
||||
} // or make use of the `LogFuncCtx`, see the '../request-logger-file-json' example for more.
|
||||
|
||||
// we don't want to use the logger
|
||||
// to log requests to assets and etc
|
||||
|
||||
@@ -28,7 +28,7 @@ func main() {
|
||||
Reload(true)
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.StaticWeb("/public", "./web/public")
|
||||
app.HandleDir("/public", "./web/public")
|
||||
|
||||
app.OnAnyErrorCode(func(ctx iris.Context) {
|
||||
ctx.ViewData("Message", ctx.Values().
|
||||
|
||||
@@ -559,89 +559,72 @@ Example Code:
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
||||
// In this example you'll just see one use case of .WrapRouter.
|
||||
// You can use the .WrapRouter to add custom logic when or when not the router should
|
||||
// be executed in order to execute the registered routes' handlers.
|
||||
//
|
||||
// To see how you can serve files on root "/" without a custom wrapper
|
||||
// just navigate to the "file-server/single-page-application" example.
|
||||
//
|
||||
// This is just for the proof of concept, you can skip this tutorial if it's too much for you.
|
||||
func newApp() *iris.Application {
|
||||
|
||||
app := iris.New()
|
||||
|
||||
app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
|
||||
ctx.HTML("<b>Resource Not found</b>")
|
||||
})
|
||||
|
||||
app.Get("/profile/{username}", func(ctx iris.Context) {
|
||||
ctx.Writef("Hello %s", ctx.Params().Get("username"))
|
||||
})
|
||||
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
myOtherHandler := func(ctx iris.Context) {
|
||||
ctx.Writef("inside a handler which is fired manually by our custom router wrapper")
|
||||
}
|
||||
|
||||
// wrap the router with a native net/http handler.
|
||||
// if url does not contain any "." (i.e: .css, .js...)
|
||||
// (depends on the app , you may need to add more file-server exceptions),
|
||||
// then the handler will execute the router that is responsible for the
|
||||
// registered routes (look "/" and "/profile/{username}")
|
||||
// if not then it will serve the files based on the root "/" path.
|
||||
app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
|
||||
path := r.URL.Path
|
||||
|
||||
if strings.HasPrefix(path, "/other") {
|
||||
// acquire and release a context in order to use it to execute
|
||||
// our custom handler
|
||||
// remember: we use net/http.Handler because here we are in the "low-level", before the router itself.
|
||||
ctx := app.ContextPool.Acquire(w, r)
|
||||
myOtherHandler(ctx)
|
||||
app.ContextPool.Release(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
router.ServeHTTP(w, r) // else continue serving routes as usual.
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app := newApp()
|
||||
|
||||
app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
|
||||
ctx.HTML("<b>Resource Not found</b>")
|
||||
})
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/index.html
|
||||
// http://localhost:8080/app.js
|
||||
// http://localhost:8080/css/main.css
|
||||
// http://localhost:8080/profile/anyusername
|
||||
// http://localhost:8080/other/random
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./public/index.html", false)
|
||||
})
|
||||
|
||||
app.Get("/profile/{username}", func(ctx iris.Context) {
|
||||
ctx.Writef("Hello %s", ctx.Params().Get("username"))
|
||||
})
|
||||
|
||||
// serve files from the root "/", if we used .StaticWeb it could override
|
||||
// all the routes because of the underline need of wildcard.
|
||||
// Here we will see how you can by-pass this behavior
|
||||
// by creating a new file server handler and
|
||||
// setting up a wrapper for the router(like a "low-level" middleware)
|
||||
// in order to manually check if we want to process with the router as normally
|
||||
// or execute the file server handler instead.
|
||||
|
||||
// use of the .StaticHandler
|
||||
// which is the same as StaticWeb but it doesn't
|
||||
// registers the route, it just returns the handler.
|
||||
fileServer := app.StaticHandler("./public", false, false)
|
||||
|
||||
// wrap the router with a native net/http handler.
|
||||
// if url does not contain any "." (i.e: .css, .js...)
|
||||
// (depends on the app , you may need to add more file-server exceptions),
|
||||
// then the handler will execute the router that is responsible for the
|
||||
// registered routes (look "/" and "/profile/{username}")
|
||||
// if not then it will serve the files based on the root "/" path.
|
||||
app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
|
||||
path := r.URL.Path
|
||||
// Note that if path has suffix of "index.html" it will auto-permant redirect to the "/",
|
||||
// so our first handler will be executed instead.
|
||||
|
||||
if !strings.Contains(path, ".") {
|
||||
// if it's not a resource then continue to the router as normally. <-- IMPORTANT
|
||||
router(w, r)
|
||||
return
|
||||
}
|
||||
// acquire and release a context in order to use it to execute
|
||||
// our file server
|
||||
// remember: we use net/http.Handler because here we are in the "low-level", before the router itself.
|
||||
ctx := app.ContextPool.Acquire(w, r)
|
||||
fileServer(ctx)
|
||||
app.ContextPool.Release(ctx)
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/index.html
|
||||
// http://localhost:8080/app.js
|
||||
// http://localhost:8080/css/main.css
|
||||
// http://localhost:8080/profile/anyusername
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
// Note: In this example we just saw one use case,
|
||||
// you may want to .WrapRouter or .Downgrade in order to bypass the iris' default router, i.e:
|
||||
// you can use that method to setup custom proxies too.
|
||||
//
|
||||
// If you just want to serve static files on other path than root
|
||||
// you can just use the StaticWeb, i.e:
|
||||
// .StaticWeb("/static", "./public")
|
||||
// ________________________________requestPath, systemPath
|
||||
// Note: In this example we just saw one use case,
|
||||
// you may want to .WrapRouter or .Downgrade in order to bypass the iris' default router, i.e:
|
||||
// you can use that method to setup custom proxies too.
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1355,7 +1338,7 @@ type Context interface {
|
||||
// You can define your own "Content-Type" with `context#ContentType`, before this function call.
|
||||
//
|
||||
// This function doesn't support resuming (by range),
|
||||
// use ctx.SendFile or router's `StaticWeb` instead.
|
||||
// use ctx.SendFile or router's `HandleDir` instead.
|
||||
ServeContent(content io.ReadSeeker, filename string, modtime time.Time, gzipCompression bool) error
|
||||
// ServeFile serves a file (to send a file, a zip for example to the client you should use the `SendFile` instead)
|
||||
// receives two parameters
|
||||
@@ -1365,7 +1348,7 @@ type Context interface {
|
||||
// You can define your own "Content-Type" with `context#ContentType`, before this function call.
|
||||
//
|
||||
// This function doesn't support resuming (by range),
|
||||
// use ctx.SendFile or router's `StaticWeb` instead.
|
||||
// use ctx.SendFile or router's `HandleDir` instead.
|
||||
//
|
||||
// Use it when you want to serve dynamic files to the client.
|
||||
ServeFile(filename string, gzipCompression bool) error
|
||||
|
||||
@@ -10,11 +10,6 @@ import (
|
||||
// In this example you'll just see one use case of .WrapRouter.
|
||||
// You can use the .WrapRouter to add custom logic when or when not the router should
|
||||
// be executed in order to execute the registered routes' handlers.
|
||||
//
|
||||
// To see how you can serve files on root "/" without a custom wrapper
|
||||
// just navigate to the "file-server/single-page-application" example.
|
||||
//
|
||||
// This is just for the proof of concept, you can skip this tutorial if it's too much for you.
|
||||
func newApp() *iris.Application {
|
||||
|
||||
app := iris.New()
|
||||
@@ -23,26 +18,15 @@ func newApp() *iris.Application {
|
||||
ctx.HTML("<b>Resource Not found</b>")
|
||||
})
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./public/index.html", false)
|
||||
})
|
||||
|
||||
app.Get("/profile/{username}", func(ctx iris.Context) {
|
||||
ctx.Writef("Hello %s", ctx.Params().Get("username"))
|
||||
})
|
||||
|
||||
// serve files from the root "/", if we used .StaticWeb it could override
|
||||
// all the routes because of the underline need of wildcard.
|
||||
// Here we will see how you can by-pass this behavior
|
||||
// by creating a new file server handler and
|
||||
// setting up a wrapper for the router(like a "low-level" middleware)
|
||||
// in order to manually check if we want to process with the router as normally
|
||||
// or execute the file server handler instead.
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
// use of the .StaticHandler
|
||||
// which is the same as StaticWeb but it doesn't
|
||||
// registers the route, it just returns the handler.
|
||||
fileServer := app.StaticHandler("./public", false, false)
|
||||
myOtherHandler := func(ctx iris.Context) {
|
||||
ctx.Writef("inside a handler which is fired manually by our custom router wrapper")
|
||||
}
|
||||
|
||||
// wrap the router with a native net/http handler.
|
||||
// if url does not contain any "." (i.e: .css, .js...)
|
||||
@@ -52,19 +36,18 @@ func newApp() *iris.Application {
|
||||
// if not then it will serve the files based on the root "/" path.
|
||||
app.WrapRouter(func(w http.ResponseWriter, r *http.Request, router http.HandlerFunc) {
|
||||
path := r.URL.Path
|
||||
// Note that if path has suffix of "index.html" it will auto-permant redirect to the "/",
|
||||
// so our first handler will be executed instead.
|
||||
|
||||
if !strings.Contains(path, ".") { // if it's not a resource then continue to the router as normally.
|
||||
router(w, r)
|
||||
if strings.HasPrefix(path, "/other") {
|
||||
// acquire and release a context in order to use it to execute
|
||||
// our custom handler
|
||||
// remember: we use net/http.Handler because here we are in the "low-level", before the router itself.
|
||||
ctx := app.ContextPool.Acquire(w, r)
|
||||
myOtherHandler(ctx)
|
||||
app.ContextPool.Release(ctx)
|
||||
return
|
||||
}
|
||||
// acquire and release a context in order to use it to execute
|
||||
// our file server
|
||||
// remember: we use net/http.Handler because here we are in the "low-level", before the router itself.
|
||||
ctx := app.ContextPool.Acquire(w, r)
|
||||
fileServer(ctx)
|
||||
app.ContextPool.Release(ctx)
|
||||
|
||||
router.ServeHTTP(w, r) // else continue serving routes as usual.
|
||||
})
|
||||
|
||||
return app
|
||||
@@ -78,14 +61,10 @@ func main() {
|
||||
// http://localhost:8080/app.js
|
||||
// http://localhost:8080/css/main.css
|
||||
// http://localhost:8080/profile/anyusername
|
||||
// http://localhost:8080/other/random
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
// Note: In this example we just saw one use case,
|
||||
// you may want to .WrapRouter or .Downgrade in order to bypass the iris' default router, i.e:
|
||||
// you can use that method to setup custom proxies too.
|
||||
//
|
||||
// If you just want to serve static files on other path than root
|
||||
// you can just use the StaticWeb, i.e:
|
||||
// .StaticWeb("/static", "./public")
|
||||
// ________________________________requestPath, systemPath
|
||||
}
|
||||
|
||||
@@ -56,4 +56,6 @@ func TestCustomWrapper(t *testing.T) {
|
||||
Status(httptest.StatusOK).
|
||||
Body().Equal(contents)
|
||||
}
|
||||
|
||||
e.GET("/other/something").Expect().Status(httptest.StatusOK)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Page.Title }}</title>
|
||||
<title>Index Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
@@ -35,17 +35,17 @@ func main() {
|
||||
// maps to ./public/assets/css/bootstrap.min.css file at system location.
|
||||
// GET: http://localhost:8080/assets/js/react.min.js
|
||||
// maps to ./public/assets/js/react.min.js file at system location.
|
||||
app.StaticWeb("/assets", "./public/assets")
|
||||
app.HandleDir("/assets", "./public/assets")
|
||||
|
||||
/* OR
|
||||
|
||||
// GET: http://localhost:8080/js/react.min.js
|
||||
// maps to ./public/assets/js/react.min.js file at system location.
|
||||
app.StaticWeb("/js", "./public/assets/js")
|
||||
app.HandleDir("/js", "./public/assets/js")
|
||||
|
||||
// GET: http://localhost:8080/css/bootstrap.min.css
|
||||
// maps to ./public/assets/css/bootstrap.min.css file at system location.
|
||||
app.StaticWeb("/css", "./public/assets/css")
|
||||
app.HandleDir("/css", "./public/assets/css")
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ func (b *Bootstrapper) Bootstrap() *Bootstrapper {
|
||||
|
||||
// static files
|
||||
b.Favicon(StaticAssets + Favicon)
|
||||
b.StaticWeb(StaticAssets[1:len(StaticAssets)-1], StaticAssets)
|
||||
b.HandleDir(StaticAssets[1:len(StaticAssets)-1], StaticAssets)
|
||||
|
||||
// middleware, after static files
|
||||
b.Use(recover.New())
|
||||
|
||||
@@ -18,7 +18,7 @@ func main() {
|
||||
|
||||
app.RegisterView(iris.HTML("./views", ".html").Layout("shared/layout.html"))
|
||||
|
||||
app.StaticWeb("/public", "./public")
|
||||
app.HandleDir("/public", "./public")
|
||||
|
||||
mvc.Configure(app, configureMVC)
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ func main() {
|
||||
* Setup static files
|
||||
*/
|
||||
|
||||
app.StaticWeb("/assets", "./public/assets")
|
||||
app.StaticWeb("/upload_resources", "./public/upload_resources")
|
||||
app.HandleDir("/assets", "./public/assets")
|
||||
app.HandleDir("/upload_resources", "./public/upload_resources")
|
||||
|
||||
dashboard := app.Party("dashboard.")
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestSubdomainWWW(t *testing.T) {
|
||||
}
|
||||
|
||||
host := "localhost:1111"
|
||||
e := httptest.New(t, app, httptest.URL("http://"+host), httptest.Debug(false))
|
||||
e := httptest.New(t, app, httptest.Debug(false))
|
||||
|
||||
for _, test := range tests {
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ func main() {
|
||||
app.RegisterView(iris.HTML("./views", ".html"))
|
||||
|
||||
// Make the /public route path to statically serve the ./public/... contents
|
||||
app.StaticWeb("/public", "./public")
|
||||
app.HandleDir("/public", "./public")
|
||||
|
||||
// Render the actual form
|
||||
// GET: http://localhost:8080
|
||||
|
||||
@@ -168,7 +168,7 @@ func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.HTML("./views", ".html"))
|
||||
|
||||
app.StaticWeb("/public", "./public")
|
||||
app.HandleDir("/public", "./public")
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.View("upload.html")
|
||||
|
||||
@@ -124,7 +124,7 @@ func main() {
|
||||
app := iris.New()
|
||||
app.RegisterView(iris.HTML("./views", ".html"))
|
||||
|
||||
app.StaticWeb("/public", "./public")
|
||||
app.HandleDir("/public", "./public")
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.View("upload.html")
|
||||
|
||||
@@ -8,7 +8,7 @@ Article is coming soon, follow and stay tuned
|
||||
Read [the fully functional example](main.go).
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/mongodb/mongo-go-driver
|
||||
$ go get -u go.mongodb.org/mongo-driver/...
|
||||
$ go get -u github.com/joho/godotenv
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package main
|
||||
|
||||
// go get -u github.com/mongodb/mongo-go-driver
|
||||
// go get -u go.mongodb.org/mongo-driver
|
||||
// go get -u github.com/joho/godotenv
|
||||
|
||||
import (
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
|
||||
"github.com/kataras/iris"
|
||||
|
||||
"github.com/mongodb/mongo-go-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
const version = "0.0.1"
|
||||
|
||||
@@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/mongodb/mongo-go-driver/bson"
|
||||
"github.com/mongodb/mongo-go-driver/bson/primitive"
|
||||
"github.com/mongodb/mongo-go-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
// up to you:
|
||||
// "github.com/mongodb/mongo-go-driver/mongo/options"
|
||||
// "go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Movie struct {
|
||||
|
||||
@@ -23,7 +23,7 @@ func main() {
|
||||
app.Any("/iris-ws.js", websocket.ClientHandler())
|
||||
|
||||
// register static assets request path and system directory
|
||||
app.StaticWeb("/js", "./static/assets/js")
|
||||
app.HandleDir("/js", "./static/assets/js")
|
||||
|
||||
h := func(ctx iris.Context) {
|
||||
ctx.ViewData("", page{PageID: "index page"})
|
||||
|
||||
@@ -49,7 +49,7 @@ func newApp(db *DB) *iris.Application {
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
// Serve static files (css)
|
||||
app.StaticWeb("/static", "./resources")
|
||||
app.HandleDir("/static", "./resources")
|
||||
|
||||
indexHandler := func(ctx iris.Context) {
|
||||
ctx.ViewData("URL_COUNT", db.Len())
|
||||
|
||||
@@ -500,7 +500,7 @@ func main() {
|
||||
// no need for any server-side template here,
|
||||
// actually if you're going to just use vue without any
|
||||
// back-end services, you can just stop afer this line and start the server.
|
||||
app.StaticWeb("/", "./public")
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
// configure the http sessions.
|
||||
sess := sessions.New(sessions.Config{
|
||||
|
||||
@@ -19,7 +19,7 @@ func main() {
|
||||
// no need for any server-side template here,
|
||||
// actually if you're going to just use vue without any
|
||||
// back-end services, you can just stop afer this line and start the server.
|
||||
app.StaticWeb("/", "./public")
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
// configure the http sessions.
|
||||
sess := sessions.New(sessions.Config{
|
||||
|
||||
44
_examples/view/template_django_0/main.go
Normal file
44
_examples/view/template_django_0/main.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
|
||||
// optionally, registers filters like `timesince`.
|
||||
_ "github.com/flosch/pongo2-addons"
|
||||
)
|
||||
|
||||
var startTime = time.Now()
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
tmpl := iris.Django("./templates", ".html")
|
||||
tmpl.Reload(true) // reload templates on each request (development mode)
|
||||
tmpl.AddFunc("greet", func(s string) string { // {{greet(name)}}
|
||||
return "Greetings " + s + "!"
|
||||
})
|
||||
|
||||
// tmpl.RegisterFilter("myFilter", myFilter) // {{"simple input for filter"|myFilter}}
|
||||
app.RegisterView(tmpl)
|
||||
|
||||
app.Get("/", hi)
|
||||
|
||||
// http://localhost:8080
|
||||
app.Run(iris.Addr(":8080"), iris.WithCharset("UTF-8")) // defaults to that but you can change it.
|
||||
}
|
||||
|
||||
func hi(ctx iris.Context) {
|
||||
// ctx.ViewData("title", "Hi Page")
|
||||
// ctx.ViewData("name", "iris")
|
||||
// ctx.ViewData("serverStartTime", startTime)
|
||||
// or if you set all view data in the same handler you can use the
|
||||
// iris.Map/pongo2.Context/map[string]interface{}, look below:
|
||||
|
||||
ctx.View("hi.html", iris.Map{
|
||||
"title": "Hi Page",
|
||||
"name": "iris",
|
||||
"serverStartTime": startTime,
|
||||
})
|
||||
}
|
||||
12
_examples/view/template_django_0/templates/hi.html
Normal file
12
_examples/view/template_django_0/templates/hi.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>{{title}}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{name|capfirst}} </h1>
|
||||
|
||||
<h2>{{greet(name)}}</h2>
|
||||
|
||||
<h3>Server started about {{serverStartTime|timesince}}. Refresh the page to see different result</h3>
|
||||
</body>
|
||||
</html>
|
||||
@@ -14,7 +14,7 @@ func main() {
|
||||
|
||||
// we could serve your assets like this the shake of the example,
|
||||
// never include the .go files there in production.
|
||||
app.StaticWeb("/", "./client")
|
||||
app.HandleDir("/", "./client")
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./client/hello.html", false) // true for gzip.
|
||||
|
||||
@@ -52,7 +52,7 @@ func main() {
|
||||
})
|
||||
|
||||
// serves the npm browser websocket client usage example.
|
||||
app.StaticWeb("/browserify", "./browserify")
|
||||
app.HandleDir("/browserify", "./browserify")
|
||||
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed))
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ func main() {
|
||||
// see the inline javascript code i the websockets.html, this endpoint is used to connect to the server.
|
||||
app.Get("/my_endpoint", ws.Handler())
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
app.HandleDir("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ViewData("", clientPage{"Client Page", "localhost:8080"})
|
||||
|
||||
@@ -32,7 +32,7 @@ func main() {
|
||||
ctx.Write(websocket.ClientSource)
|
||||
})
|
||||
|
||||
app.StaticWeb("/js", "./static/js")
|
||||
app.HandleDir("/js", "./static/js")
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
// send our custom javascript source file before client really asks for that
|
||||
// using the go v1.8's HTTP/2 Push.
|
||||
|
||||
@@ -38,7 +38,7 @@ func main() {
|
||||
|
||||
// serve the index.html and the javascript libraries at
|
||||
// http://localhost:8080
|
||||
app.StaticWeb("/", "./public")
|
||||
app.HandleDir("/", "./public")
|
||||
|
||||
app.Run(iris.Addr("localhost:8080"), iris.WithoutPathCorrection)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user