Update to version 8.5.6 | Read HISTORY.md

Former-commit-id: 3c1fb7ad47d54133f68ee0ee8ebe4c3835fe4ce0
This commit is contained in:
kataras 2017-11-05 04:12:18 +02:00
parent ef41e07d4e
commit af9a1f1241
33 changed files with 587 additions and 307 deletions

3
.gitignore vendored
View File

@ -1 +1,2 @@
.vscode
.vscode
_authortools

View File

@ -17,6 +17,18 @@ 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.
# Su, 05 November 2017 | v8.5.6
- **DEPRECATE** the `app.StaticServe`, use `app.StaticWeb` which does the same thing but better or `iris/app.StaticHandler` which gives you more options to work on.
- add some debug messages for route registrations, to be aligned with the mvc debug messages.
- improve the https://iris-go.com/v8/recipe -- now you can see other files like assets as well -- lexical order of categories instead of "level".
- add [8 more examples](_examples/tree/master/experimental-handlers) to this repository, originally lived at https://github.com/iris-contrib/middleware and https://github.com/iris-contrib/examples/tree/master/experimental-handlers.
_TODO;_
- [ ] give the ability to customize the mvc path-method-and path parameters mapping,
- [ ] make a github bot which will post the monthly usage and even earnings statistics in a public github markdown file, hope that users will love that type of transparency we will introduce here.
# Tu, 02 November 2017 | v8.5.5
- fix [audio/mpeg3 does not appear to be a valid registered mime type#798](https://github.com/kataras/iris/issues/798]) reported by @kryptodev,

View File

@ -42,7 +42,7 @@ If you're coming from [nodejs](https://nodejs.org) world, Iris is the [expressjs
## Table Of Content
* [Installation](#installation)
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#tu-02-november-2017--v855)
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#su-05-november-2017--v856)
* [Getting started](#getting-started)
* [Learn](_examples/)
* [MVC (Model View Controller)](_examples/#mvc) **NEW**
@ -74,7 +74,7 @@ If you're coming from [nodejs](https://nodejs.org) world, Iris is the [expressjs
* [Dockerize](https://github.com/iris-contrib/cloud-native-go)
* [Contributing](CONTRIBUTING.md)
* [FAQ](FAQ.md)
* [What's next?](#you-are-ready-to-move-to-the-next-step-and-get-closer-to-becoming-a-pro-gopher)
* [What's next?](#now-you-are-ready-to-move-to-the-next-step-and-get-closer-to-becoming-a-pro-gopher)
* [People](#people)
## Installation

View File

@ -1 +1 @@
8.5.5:https://github.com/kataras/iris/blob/master/HISTORY.md#tu-02-november-2017--v855
8.5.6:https://github.com/kataras/iris/blob/master/HISTORY.md#su-05-november-2017--v856

View File

@ -263,7 +263,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) files to
- [Basic Authentication](authentication/basicauth/main.go)
- [OAUth2](authentication/oauth2/main.go)
- [JWT](https://github.com/iris-contrib/middleware/blob/master/jwt/_example/main.go)
- [JWT](experimental-handlers/jwt/main.go)
- [Sessions](#sessions)
### File Server
@ -307,6 +307,18 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) files to
- [Internal Application File Logger](miscellaneous/file-logger/main.go)
- [Google reCAPTCHA](miscellaneous/recaptcha/main.go)
### Experimental Handlers
* [Casbin wrapper](experimental-handlers/casbin/wrapper/main.go)
* [Casbin middleware](experimental-handlers/casbin/middleware/main.go)
* [Cloudwatch](experimental-handlers/cloudwatch/simple/main.go)
* [CORS](experimental-handlers/cors/simple/main.go)
* [JWT](experimental-handlers/jwt/main.go)
* [Newrelic](experimental-handlers/newrelic/simple/main.go)
* [Prometheus](experimental-handlers/prometheus/simple/main.go)
* [Secure](experimental-handlers/secure/simple/main.go)
* [Tollboothic](experimental-handlers/tollboothic/limit-handler/main.go)
#### More
https://github.com/kataras/iris/tree/master/middleware#third-party-handlers

View File

@ -2,7 +2,6 @@ package main
import (
"github.com/kataras/iris"
"github.com/kataras/iris/context"
"github.com/betacraft/yaag/irisyaag"
"github.com/betacraft/yaag/yaag"
@ -27,21 +26,21 @@ func main() {
})
app.Use(irisyaag.New()) // <- IMPORTANT, register the middleware.
app.Get("/json", func(ctx context.Context) {
ctx.JSON(context.Map{"result": "Hello World!"})
app.Get("/json", func(ctx iris.Context) {
ctx.JSON(iris.Map{"result": "Hello World!"})
})
app.Get("/plain", func(ctx context.Context) {
app.Get("/plain", func(ctx iris.Context) {
ctx.Text("Hello World!")
})
app.Get("/xml", func(ctx context.Context) {
app.Get("/xml", func(ctx iris.Context) {
ctx.XML(myXML{Result: "Hello World!"})
})
app.Get("/complex", func(ctx context.Context) {
app.Get("/complex", func(ctx iris.Context) {
value := ctx.URLParam("key")
ctx.JSON(context.Map{"value": value})
ctx.JSON(iris.Map{"value": value})
})
// Run our HTTP Server.

View File

@ -2,5 +2,5 @@
- [Basic Authentication](basicauth/main.go)
- [OAUth2](oauth2/main.go)
- [JWT](https://github.com/iris-contrib/middleware/blob/master/jwt/_example/main.go)
- [JWT](https://github.com/kataras/iris/blob/master/_examples/experimental-handlers/jwt/main.go)
- [Sessions](https://github.com/kataras/iris/tree/master/_examples/#sessions)

View File

@ -0,0 +1,5 @@
# Install iris-contrib/middleware
```sh
$ go get -u github.com/iris-contrib/middleware/...
```

View File

@ -0,0 +1,14 @@
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

View File

@ -0,0 +1,5 @@
p, alice, /dataset1/*, GET
p, alice, /dataset1/resource1, POST
p, bob, /dataset2/resource1, *
p, bob, /dataset2/resource2, GET
p, bob, /dataset2/folder1/*, POST
1 p alice /dataset1/* GET
2 p alice /dataset1/resource1 POST
3 p bob /dataset2/resource1 *
4 p bob /dataset2/resource2 GET
5 p bob /dataset2/folder1/* POST

View File

@ -0,0 +1,43 @@
package main
import (
"github.com/kataras/iris"
"github.com/casbin/casbin"
cm "github.com/iris-contrib/middleware/casbin"
)
// $ go get github.com/casbin/casbin
// $ go run main.go
// Enforcer maps the model and the policy for the casbin service, we use this variable on the main_test too.
var Enforcer = casbin.NewEnforcer("casbinmodel.conf", "casbinpolicy.csv")
func newApp() *iris.Application {
casbinMiddleware := cm.New(Enforcer)
app := iris.New()
app.Use(casbinMiddleware.ServeHTTP)
app.Get("/", hi)
app.Get("/dataset1/{p:path}", hi) // p, alice, /dataset1/*, GET
app.Post("/dataset1/resource1", hi)
app.Get("/dataset2/resource2", hi)
app.Post("/dataset2/folder1/{p:path}", hi)
app.Any("/dataset2/resource1", hi)
return app
}
func main() {
app := newApp()
app.Run(iris.Addr(":8080"))
}
func hi(ctx iris.Context) {
ctx.Writef("Hello %s", cm.Username(ctx.Request()))
}

View File

@ -0,0 +1,49 @@
package main
import (
"testing"
"github.com/iris-contrib/httpexpect"
"github.com/kataras/iris/httptest"
)
func TestCasbinMiddleware(t *testing.T) {
app := newApp()
e := httptest.New(t, app, httptest.Debug(true))
type ttcasbin struct {
username string
path string
method string
status int
}
tt := []ttcasbin{
{"alice", "/dataset1/resource1", "GET", 200},
{"alice", "/dataset1/resource1", "POST", 200},
{"alice", "/dataset1/resource2", "GET", 200},
{"alice", "/dataset1/resource2", "POST", 404},
{"bob", "/dataset2/resource1", "GET", 200},
{"bob", "/dataset2/resource1", "POST", 200},
{"bob", "/dataset2/resource1", "DELETE", 200},
{"bob", "/dataset2/resource2", "GET", 200},
{"bob", "/dataset2/resource2", "POST", 404},
{"bob", "/dataset2/resource2", "DELETE", 404},
{"bob", "/dataset2/folder1/item1", "GET", 404},
{"bob", "/dataset2/folder1/item1", "POST", 200},
{"bob", "/dataset2/folder1/item1", "DELETE", 404},
{"bob", "/dataset2/folder1/item2", "GET", 404},
{"bob", "/dataset2/folder1/item2", "POST", 200},
{"bob", "/dataset2/folder1/item2", "DELETE", 404},
}
for _, tt := range tt {
check(e, tt.method, tt.path, tt.username, tt.status)
}
}
func check(e *httpexpect.Expect, method, path, username string, status int) {
e.Request(method, path).WithBasicAuth(username, "password").Expect().Status(status)
}

View File

@ -0,0 +1,14 @@
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.obj, p.obj) && (r.act == p.act || p.act == "*")

View File

@ -0,0 +1,7 @@
p, alice, /dataset1/*, GET
p, alice, /dataset1/resource1, POST
p, bob, /dataset2/resource1, *
p, bob, /dataset2/resource2, GET
p, bob, /dataset2/folder1/*, POST
p, dataset1_admin, /dataset1/*, *
g, cathrin, dataset1_admin
1 p, alice, /dataset1/*, GET
2 p, alice, /dataset1/resource1, POST
3 p, bob, /dataset2/resource1, *
4 p, bob, /dataset2/resource2, GET
5 p, bob, /dataset2/folder1/*, POST
6 p, dataset1_admin, /dataset1/*, *
7 g, cathrin, dataset1_admin

View File

@ -0,0 +1,43 @@
package main
import (
"github.com/kataras/iris"
"github.com/casbin/casbin"
cm "github.com/iris-contrib/middleware/casbin"
)
// $ go get github.com/casbin/casbin
// $ go run main.go
// Enforcer maps the model and the policy for the casbin service, we use this variable on the main_test too.
var Enforcer = casbin.NewEnforcer("casbinmodel.conf", "casbinpolicy.csv")
func newApp() *iris.Application {
casbinMiddleware := cm.New(Enforcer)
app := iris.New()
app.WrapRouter(casbinMiddleware.Wrapper())
app.Get("/", hi)
app.Any("/dataset1/{p:path}", hi) // p, dataset1_admin, /dataset1/*, * && p, alice, /dataset1/*, GET
app.Post("/dataset1/resource1", hi)
app.Get("/dataset2/resource2", hi)
app.Post("/dataset2/folder1/{p:path}", hi)
app.Any("/dataset2/resource1", hi)
return app
}
func main() {
app := newApp()
app.Run(iris.Addr(":8080"))
}
func hi(ctx iris.Context) {
ctx.Writef("Hello %s", cm.Username(ctx.Request()))
}

View File

@ -0,0 +1,80 @@
package main
import (
"testing"
"github.com/iris-contrib/httpexpect"
"github.com/kataras/iris/httptest"
)
func TestCasbinWrapper(t *testing.T) {
app := newApp()
e := httptest.New(t, app, httptest.Debug(true))
type ttcasbin struct {
username string
path string
method string
status int
}
tt := []ttcasbin{
{"alice", "/dataset1/resource1", "GET", 200},
{"alice", "/dataset1/resource1", "POST", 200},
{"alice", "/dataset1/resource2", "GET", 200},
{"alice", "/dataset1/resource2", "POST", 403},
{"bob", "/dataset2/resource1", "GET", 200},
{"bob", "/dataset2/resource1", "POST", 200},
{"bob", "/dataset2/resource1", "DELETE", 200},
{"bob", "/dataset2/resource2", "GET", 200},
{"bob", "/dataset2/resource2", "POST", 403},
{"bob", "/dataset2/resource2", "DELETE", 403},
{"bob", "/dataset2/folder1/item1", "GET", 403},
{"bob", "/dataset2/folder1/item1", "POST", 200},
{"bob", "/dataset2/folder1/item1", "DELETE", 403},
{"bob", "/dataset2/folder1/item2", "GET", 403},
{"bob", "/dataset2/folder1/item2", "POST", 200},
{"bob", "/dataset2/folder1/item2", "DELETE", 403},
}
for _, tt := range tt {
check(e, tt.method, tt.path, tt.username, tt.status)
}
println("ADMIN ROLES")
ttAdmin := []ttcasbin{
{"cathrin", "/dataset1/item", "GET", 200},
{"cathrin", "/dataset1/item", "POST", 200},
{"cathrin", "/dataset1/item", "DELETE", 200},
{"cathrin", "/dataset2/item", "GET", 403},
{"cathrin", "/dataset2/item", "POST", 403},
{"cathrin", "/dataset2/item", "DELETE", 403},
}
for _, tt := range ttAdmin {
check(e, tt.method, tt.path, tt.username, tt.status)
}
println("ADMIN ROLE FOR cathrin DELETED")
Enforcer.DeleteRolesForUser("cathrin")
ttAdminDeleted := []ttcasbin{
{"cathrin", "/dataset1/item", "GET", 403},
{"cathrin", "/dataset1/item", "POST", 403},
{"cathrin", "/dataset1/item", "DELETE", 403},
{"cathrin", "/dataset2/item", "GET", 403},
{"cathrin", "/dataset2/item", "POST", 403},
{"cathrin", "/dataset2/item", "DELETE", 403},
}
for _, tt := range ttAdminDeleted {
check(e, tt.method, tt.path, tt.username, tt.status)
}
}
func check(e *httpexpect.Expect, method, path, username string, status int) {
e.Request(method, path).WithBasicAuth(username, "password").Expect().Status(status)
}

View File

@ -0,0 +1,50 @@
package main
import (
"time"
"github.com/kataras/iris"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudwatch"
cw "github.com/iris-contrib/middleware/cloudwatch"
)
// $ go get github.com/aws/aws-sdk-go/...
// $ go run main.go
func main() {
app := iris.New()
app.Use(cw.New("us-east-1", "test").ServeHTTP)
app.Get("/", func(ctx iris.Context) {
put := cw.GetPutFunc(ctx)
put([]*cloudwatch.MetricDatum{
{
MetricName: aws.String("MyMetric"),
Dimensions: []*cloudwatch.Dimension{
{
Name: aws.String("ThingOne"),
Value: aws.String("something"),
},
{
Name: aws.String("ThingTwo"),
Value: aws.String("other"),
},
},
Timestamp: aws.Time(time.Now()),
Unit: aws.String("Count"),
Value: aws.Float64(42),
},
})
ctx.StatusCode(iris.StatusOK)
ctx.Text("success!\n")
})
// http://localhost:8080
// should give: NoCredentialProviders
// which is correct, you have to authorize your aws, we asumme that you know how to.
app.Run(iris.Addr(":8080"))
}

View File

@ -0,0 +1,43 @@
package main
// $ go get github.com/rs/cors
// $ go run main.go
import (
"github.com/kataras/iris"
"github.com/iris-contrib/middleware/cors"
)
func main() {
app := iris.New()
crs := cors.New(cors.Options{
AllowedOrigins: []string{"*"}, // allows everything, use that to change the hosts.
AllowCredentials: true,
})
v1 := app.Party("/api/v1")
v1.Use(crs)
{
v1.Get("/home", func(ctx iris.Context) {
ctx.WriteString("Hello from /home")
})
v1.Get("/about", func(ctx iris.Context) {
ctx.WriteString("Hello from /about")
})
v1.Post("/send", func(ctx iris.Context) {
ctx.WriteString("sent")
})
}
// or use that to wrap the entire router
// even before the path and method matching
// this should work better and with all cors' features.
// Use that instead, if suits you.
// app.WrapRouter(cors.WrapNext(cors.Options{
// AllowedOrigins: []string{"*"},
// AllowCredentials: true,
// }))
app.Run(iris.Addr("localhost:8080"))
}

View File

@ -0,0 +1,46 @@
// iris provides some basic middleware, most for your learning courve.
// You can use any net/http compatible middleware with iris.FromStd wrapper.
//
// JWT net/http video tutorial for golang newcomers: https://www.youtube.com/watch?v=dgJFeqeXVKw
//
// This middleware is the only one cloned from external source: https://github.com/auth0/go-jwt-middleware
// (because it used "context" to define the user but we don't need that so a simple iris.FromStd wouldn't work as expected.)
package main
// $ go get -u github.com/dgrijalva/jwt-go
// $ go run main.go
import (
"github.com/kataras/iris"
"github.com/dgrijalva/jwt-go"
jwtmiddleware "github.com/iris-contrib/middleware/jwt"
)
func myHandler(ctx iris.Context) {
user := ctx.Values().Get("jwt").(*jwt.Token)
ctx.Writef("This is an authenticated request\n")
ctx.Writef("Claim content:\n")
ctx.Writef("%s", user.Signature)
}
func main() {
app := iris.New()
jwtHandler := jwtmiddleware.New(jwtmiddleware.Config{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return []byte("My Secret"), nil
},
// When set, the middleware verifies that tokens are signed with the specific signing algorithm
// If the signing method is not constant the ValidationKeyGetter callback can be used to implement additional checks
// Important to avoid security issues described here: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/
SigningMethod: jwt.SigningMethodHS256,
})
app.Use(jwtHandler.Serve)
app.Get("/ping", myHandler)
app.Run(iris.Addr("localhost:3001"))
} // don't forget to look ../jwt_test.go to seee how to set your own custom claims

View File

@ -0,0 +1,24 @@
package main
import (
"github.com/kataras/iris"
"github.com/iris-contrib/middleware/newrelic"
)
func main() {
app := iris.New()
config := newrelic.Config("APP_SERVER_NAME", "NEWRELIC_LICENSE_KEY")
config.Enabled = true
m, err := newrelic.New(config)
if err != nil {
app.Logger().Fatal(err)
}
app.Use(m.ServeHTTP)
app.Get("/", func(ctx iris.Context) {
ctx.Writef("success!\n")
})
app.Run(iris.Addr(":8080"))
}

View File

@ -0,0 +1,40 @@
package main
import (
"math/rand"
"time"
"github.com/kataras/iris"
prometheusMiddleware "github.com/iris-contrib/middleware/prometheus"
"github.com/prometheus/client_golang/prometheus"
)
func main() {
app := iris.New()
m := prometheusMiddleware.New("serviceName", 300, 1200, 5000)
app.Use(m.ServeHTTP)
app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
// error code handlers are not sharing the same middleware as other routes, so we have
// to call them inside their body.
m.ServeHTTP(ctx)
ctx.Writef("Not Found")
})
app.Get("/", func(ctx iris.Context) {
sleep := rand.Intn(4999) + 1
time.Sleep(time.Duration(sleep) * time.Millisecond)
ctx.Writef("Slept for %d milliseconds", sleep)
})
app.Get("/metrics", iris.FromStd(prometheus.Handler()))
// http://localhost:8080/
// http://localhost:8080/anotfound
// http://localhost:8080/metrics
app.Run(iris.Addr(":8080"))
}

View File

@ -0,0 +1,38 @@
package main
import (
"github.com/kataras/iris"
"github.com/iris-contrib/middleware/secure"
)
func main() {
s := secure.New(secure.Options{
AllowedHosts: []string{"ssl.example.com"}, // AllowedHosts is a list of fully qualified domain names that are allowed. Default is empty list, which allows any and all host names.
SSLRedirect: true, // If SSLRedirect is set to true, then only allow HTTPS requests. Default is false.
SSLTemporaryRedirect: false, // If SSLTemporaryRedirect is true, the a 302 will be used while redirecting. Default is false (301).
SSLHost: "ssl.example.com", // SSLHost is the host name that is used to redirect HTTP requests to HTTPS. Default is "", which indicates to use the same host.
SSLProxyHeaders: map[string]string{"X-Forwarded-Proto": "https"}, // SSLProxyHeaders is set of header keys with associated values that would indicate a valid HTTPS request. Useful when using Nginx: `map[string]string{"X-Forwarded-Proto": "https"}`. Default is blank map.
STSSeconds: 315360000, // STSSeconds is the max-age of the Strict-Transport-Security header. Default is 0, which would NOT include the header.
STSIncludeSubdomains: true, // If STSIncludeSubdomains is set to true, the `includeSubdomains` will be appended to the Strict-Transport-Security header. Default is false.
STSPreload: true, // If STSPreload is set to true, the `preload` flag will be appended to the Strict-Transport-Security header. Default is false.
ForceSTSHeader: false, // STS header is only included when the connection is HTTPS. If you want to force it to always be added, set to true. `IsDevelopment` still overrides this. Default is false.
FrameDeny: true, // If FrameDeny is set to true, adds the X-Frame-Options header with the value of `DENY`. Default is false.
CustomFrameOptionsValue: "SAMEORIGIN", // CustomFrameOptionsValue allows the X-Frame-Options header value to be set with a custom value. This overrides the FrameDeny option.
ContentTypeNosniff: true, // If ContentTypeNosniff is true, adds the X-Content-Type-Options header with the value `nosniff`. Default is false.
BrowserXSSFilter: true, // If BrowserXssFilter is true, adds the X-XSS-Protection header with the value `1; mode=block`. Default is false.
ContentSecurityPolicy: "default-src 'self'", // ContentSecurityPolicy allows the Content-Security-Policy header value to be set with a custom value. Default is "".
PublicKey: `pin-sha256="base64+primary=="; pin-sha256="base64+backup=="; max-age=5184000; includeSubdomains; report-uri="https://www.example.com/hpkp-report"`, // PublicKey implements HPKP to prevent MITM attacks with forged certificates. Default is "".
IsDevelopment: true, // This will cause the AllowedHosts, SSLRedirect, and STSSeconds/STSIncludeSubdomains options to be ignored during development. When deploying to production, be sure to set this to false.
})
app := iris.New()
app.Use(s.Serve)
app.Get("/home", func(ctx iris.Context) {
ctx.Writef("Hello from /home")
})
app.Run(iris.Addr(":8080"))
}

View File

@ -0,0 +1,31 @@
package main
import (
"github.com/kataras/iris"
"github.com/didip/tollbooth"
"github.com/iris-contrib/middleware/tollboothic"
)
// $ go get github.com/didip/tollbooth
// $ go run main.go
func main() {
app := iris.New()
limiter := tollbooth.NewLimiter(1, nil)
//
// or create a limiter with expirable token buckets
// This setting means:
// create a 1 request/second limiter and
// every token bucket in it will expire 1 hour after it was initially set.
// limiter := tollbooth.NewLimiter(1, &limiter.ExpirableOptions{DefaultExpirationTTL: time.Hour})
app.Get("/", tollboothic.LimitHandler(limiter), func(ctx iris.Context) {
ctx.HTML("<b>Hello, world!</b>")
})
app.Run(iris.Addr(":8080"))
}
// Read more at: https://github.com/didip/tollbooth

View File

@ -1,128 +0,0 @@
// This file is automatically generated by qtc from "base.qtpl".
// See https://github.com/valyala/quicktemplate for details.
// This is our templates' base implementation.
//
//line base.qtpl:3
package templates
//line base.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line base.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line base.qtpl:4
type Partial interface {
//line base.qtpl:4
Body() string
//line base.qtpl:4
StreamBody(qw422016 *qt422016.Writer)
//line base.qtpl:4
WriteBody(qq422016 qtio422016.Writer)
//line base.qtpl:4
}
// Template writes a template implementing the Partial interface.
//line base.qtpl:11
func StreamTemplate(qw422016 *qt422016.Writer, p Partial) {
//line base.qtpl:11
qw422016.N().S(`
<html>
<head>
<title>Quicktemplate integration with Iris</title>
</head>
<body>
<div>
Header contents here...
</div>
<div style="margin:10px;">
`)
//line base.qtpl:22
p.StreamBody(qw422016)
//line base.qtpl:22
qw422016.N().S(`
</div>
</body>
<footer>
Footer contents here...
</footer>
</html>
`)
//line base.qtpl:30
}
//line base.qtpl:30
func WriteTemplate(qq422016 qtio422016.Writer, p Partial) {
//line base.qtpl:30
qw422016 := qt422016.AcquireWriter(qq422016)
//line base.qtpl:30
StreamTemplate(qw422016, p)
//line base.qtpl:30
qt422016.ReleaseWriter(qw422016)
//line base.qtpl:30
}
//line base.qtpl:30
func Template(p Partial) string {
//line base.qtpl:30
qb422016 := qt422016.AcquireByteBuffer()
//line base.qtpl:30
WriteTemplate(qb422016, p)
//line base.qtpl:30
qs422016 := string(qb422016.B)
//line base.qtpl:30
qt422016.ReleaseByteBuffer(qb422016)
//line base.qtpl:30
return qs422016
//line base.qtpl:30
}
// Base template implementation. Other pages may inherit from it if they need
// overriding only certain Partial methods.
//line base.qtpl:35
type Base struct{}
//line base.qtpl:36
func (b *Base) StreamBody(qw422016 *qt422016.Writer) {
//line base.qtpl:36
qw422016.N().S(`This is the base body`) }
//line base.qtpl:36
//line base.qtpl:36
func (b *Base) WriteBody(qq422016 qtio422016.Writer) {
//line base.qtpl:36
qw422016 := qt422016.AcquireWriter(qq422016)
//line base.qtpl:36
b.StreamBody(qw422016)
//line base.qtpl:36
qt422016.ReleaseWriter(qw422016)
//line base.qtpl:36
}
//line base.qtpl:36
func (b *Base) Body() string {
//line base.qtpl:36
qb422016 := qt422016.AcquireByteBuffer()
//line base.qtpl:36
b.WriteBody(qb422016)
//line base.qtpl:36
qs422016 := string(qb422016.B)
//line base.qtpl:36
qt422016.ReleaseByteBuffer(qb422016)
//line base.qtpl:36
return qs422016
//line base.qtpl:36
}

View File

@ -1,72 +0,0 @@
// This file is automatically generated by qtc from "hello.qtpl".
// See https://github.com/valyala/quicktemplate for details.
// Hello template, implements the Partial's methods.
//
//line hello.qtpl:3
package templates
//line hello.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line hello.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line hello.qtpl:4
type Hello struct {
Vars map[string]interface{}
}
//line hello.qtpl:9
func (h *Hello) StreamBody(qw422016 *qt422016.Writer) {
//line hello.qtpl:9
qw422016.N().S(`
<h1>`)
//line hello.qtpl:10
qw422016.E().V(h.Vars["message"])
//line hello.qtpl:10
qw422016.N().S(`</h1>
<div>
Hello <b>`)
//line hello.qtpl:12
qw422016.E().V(h.Vars["name"])
//line hello.qtpl:12
qw422016.N().S(`!</b>
</div>
`)
//line hello.qtpl:14
}
//line hello.qtpl:14
func (h *Hello) WriteBody(qq422016 qtio422016.Writer) {
//line hello.qtpl:14
qw422016 := qt422016.AcquireWriter(qq422016)
//line hello.qtpl:14
h.StreamBody(qw422016)
//line hello.qtpl:14
qt422016.ReleaseWriter(qw422016)
//line hello.qtpl:14
}
//line hello.qtpl:14
func (h *Hello) Body() string {
//line hello.qtpl:14
qb422016 := qt422016.AcquireByteBuffer()
//line hello.qtpl:14
h.WriteBody(qb422016)
//line hello.qtpl:14
qs422016 := string(qb422016.B)
//line hello.qtpl:14
qt422016.ReleaseByteBuffer(qb422016)
//line hello.qtpl:14
return qs422016
//line hello.qtpl:14
}

View File

@ -1,62 +0,0 @@
// This file is automatically generated by qtc from "index.qtpl".
// See https://github.com/valyala/quicktemplate for details.
// Index template, implements the Partial's methods.
//
//line index.qtpl:3
package templates
//line index.qtpl:3
import (
qtio422016 "io"
qt422016 "github.com/valyala/quicktemplate"
)
//line index.qtpl:3
var (
_ = qtio422016.Copy
_ = qt422016.AcquireByteBuffer
)
//line index.qtpl:4
type Index struct{}
//line index.qtpl:7
func (i *Index) StreamBody(qw422016 *qt422016.Writer) {
//line index.qtpl:7
qw422016.N().S(`
<h1>Index Page</h1>
<div>
This is our index page's body.
</div>
`)
//line index.qtpl:12
}
//line index.qtpl:12
func (i *Index) WriteBody(qq422016 qtio422016.Writer) {
//line index.qtpl:12
qw422016 := qt422016.AcquireWriter(qq422016)
//line index.qtpl:12
i.StreamBody(qw422016)
//line index.qtpl:12
qt422016.ReleaseWriter(qw422016)
//line index.qtpl:12
}
//line index.qtpl:12
func (i *Index) Body() string {
//line index.qtpl:12
qb422016 := qt422016.AcquireByteBuffer()
//line index.qtpl:12
i.WriteBody(qb422016)
//line index.qtpl:12
qs422016 := string(qb422016.B)
//line index.qtpl:12
qt422016.ReleaseByteBuffer(qb422016)
//line index.qtpl:12
return qs422016
//line index.qtpl:12
}

View File

@ -1,7 +1,7 @@
# Articles
- [How to build a file upload form using DropzoneJS and Go](https://dev.to/kataras/dropzonejs--go-series---part-1-474)
- [How to display existing files on server using DropzoneJS and Go](https://dev.to/kataras/dropzonejs--go-series---part-2-4n1)
* [How to build a file upload form using DropzoneJS and Go](https://hackernoon.com/how-to-build-a-file-upload-form-using-dropzonejs-and-go-8fb9f258a991)
* [How to display existing files on server using DropzoneJS and Go](https://hackernoon.com/how-to-display-existing-files-on-server-using-dropzonejs-and-go-53e24b57ba19)
# Content

View File

@ -1,7 +1,7 @@
# Articles
- [How to build a file upload form using DropzoneJS and Go](https://dev.to/kataras/dropzonejs--go-series---part-1-474)
- [How to display existing files on server using DropzoneJS and Go](https://dev.to/kataras/dropzonejs--go-series---part-2-4n1)
* [How to build a file upload form using DropzoneJS and Go](https://hackernoon.com/how-to-build-a-file-upload-form-using-dropzonejs-and-go-8fb9f258a991)
* [How to display existing files on server using DropzoneJS and Go](https://hackernoon.com/how-to-display-existing-files-on-server-using-dropzonejs-and-go-53e24b57ba19)
# Content

View File

@ -0,0 +1,8 @@
Name: DropzoneJS
Articles:
- Title: How to build a file upload form using DropzoneJS and Go
Source: https://hackernoon.com/how-to-build-a-file-upload-form-using-dropzonejs-and-go-8fb9f258a991
Author: https://twitter.com/@kataras
- Title: How to display existing files on server using DropzoneJS and Go
Source: https://hackernoon.com/how-to-display-existing-files-on-server-using-dropzonejs-and-go-53e24b57ba19
Author: https://twitter.com/@kataras

View File

@ -1 +0,0 @@
3c9dbd9acb1d553cc63940c72f212a880e8a8073

View File

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

View File

@ -599,15 +599,9 @@ func (api *APIBuilder) StaticHandler(systemPath string, showList bool, gzip bool
return StaticHandler(systemPath, showList, gzip)
}
// StaticServe serves a directory as web resource
// it's the simpliest form of the Static* functions
// Almost same usage as StaticWeb
// accepts only one required parameter which is the systemPath,
// the same path will be used to register the GET and HEAD method routes.
// If second parameter is empty, otherwise the requestPath is the second parameter
// it uses gzip compression (compression on each request, no file cache).
//
// Returns the GET *Route.
// StaticServe serves a directory as web resource.
// Same as `StaticWeb`.
// DEPRECATED; use `StaticWeb` or `StaticHandler` (for more options) instead.
func (api *APIBuilder) StaticServe(systemPath string, requestPath ...string) *Route {
var reqPath string
@ -619,22 +613,7 @@ func (api *APIBuilder) StaticServe(systemPath string, requestPath ...string) *Ro
reqPath = requestPath[0]
}
return api.Get(joinPath(reqPath, WildcardParam("file")), func(ctx context.Context) {
filepath := ctx.Params().Get("file")
spath := strings.Replace(filepath, "/", string(os.PathSeparator), -1)
spath = path.Join(systemPath, spath)
if !DirectoryExists(spath) {
ctx.NotFound()
return
}
if err := ctx.ServeFile(spath, true); err != nil {
ctx.Application().Logger().Warnf("while trying to serve static file: '%v' on IP: '%s'", err, ctx.RemoteAddr())
ctx.StatusCode(http.StatusInternalServerError)
}
})
return api.StaticWeb(reqPath, systemPath)
}
// StaticContent registers a GET and HEAD method routes to the requestPath

2
doc.go
View File

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