diff --git a/HISTORY.md b/HISTORY.md
index 74f6b150..6b331b2d 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -28,6 +28,7 @@ The codebase for Dependency Injection, Internationalization and localization and
## Fixes and Improvements
+- Make the `Context.JSON` method customizable by modifying the `context.WriteJSON` package-level function.
- Add new `iris.NewGuide` which helps you build a simple and nice JSON API with services as dependencies and better design pattern.
- Make `Context.Domain()` customizable by letting developers to modify the `Context.GetDomain` package-level function.
- Remove Request Context-based Transaction feature as its usage can be replaced with just the Iris Context (as of go1.7+) and better [project](_examples/project) structure.
diff --git a/LICENSE b/LICENSE
index 1bc2959b..24efccb8 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,7 @@
-Copyright (c) 2017-2022 The Iris Authors. All rights reserved.
+Copyright (c) 2017-2022, The Iris Authors. All rights reserved.
+
+The Iris Authors:
+ * Gerasimos (Makis) Maropoulos
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/README.md b/README.md
index 9956bbfb..997ac5f2 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,8 @@
Iris is a fast, simple yet fully featured and very efficient web framework for Go.
-It provides a [beautifully](iris_guide.go#L31-L44) expressive and easy to use foundation for your next website or API.
+It provides a beautifully expressive and easy to use foundation for your next website or API.
+
```go
package main
@@ -27,18 +28,18 @@ package main
import "github.com/kataras/iris/v12"
func main() {
- app := iris.New()
- app.Use(iris.Compression)
+ app := iris.New()
+ app.Use(iris.Compression)
- app.Get("/", func(ctx iris.Context) {
- ctx.HTML("Hello %s!", "World")
- })
+ app.Get("/", func(ctx iris.Context) {
+ ctx.HTML("Hello %s!", "World")
+ })
- app.Listen(":8080")
+ app.Listen(":8080")
}
```
-More with simple Handler
+
+
+As one [Go developer](https://twitter.com/dkuye/status/1532087942696554497) once said, **Iris got you covered all-round and standing strong over the years**.
+
+Some of the features Iris offers:
+
+* HTTP/2 (Push, even Embedded data)
+* Middleware (Accesslog, Basicauth, CORS, gRPC, Anti-Bot hCaptcha, JWT, MethodOverride, ModRevision, Monitor, PPROF, Ratelimit, Anti-Bot reCaptcha, Recovery, RequestID, Rewrite)
+* API Versioning
+* Model-View-Controller
+* Websockets
+* gRPC
+* Auto-HTTPS
+* Builtin support for ngrok to put your app on the internet, the fastest way
+* Unique Router with dynamic path as parameter with standard types like :uuid, :string, :int... and the ability to create your own
+* Compression
+* View Engines (HTML, Django, Amber, Handlebars, Pug/Jade and more)
+* Create your own File Server and host your own WebDAV server
+* Cache
+* Localization (i18n, sitemap)
+* Sessions
+* Rich Responses (HTML, Text, Markdown, XML, YAML, Binary, JSON, JSONP, Protocol Buffers, MessagePack, Content Negotiation, Streaming, Server-Sent Events and more)
+* Response Compression (gzip, deflate, brotli, snappy, s2)
+* Rich Requests (Bind URL Query, Headers, Form, Text, XML, YAML, Binary, JSON, Validation, Protocol Buffers, MessagePack and more)
+* Dependency Injection (MVC, Handlers, API Routers)
+* Testing Suite
+* And the most important... you get fast answers and support from the 1st day until now - that's six full years!
+
Learn what [others saying about Iris](https://www.iris-go.com/#review) and **[star](https://github.com/kataras/iris/stargazers)** this open-source project to support its potentials.
[![](https://iris-go.com/images/reviews.gif)](https://iris-go.com/testimonials/)
diff --git a/_examples/auth/jwt/tutorial/go-client/client.go b/_examples/auth/jwt/tutorial/go-client/client.go
index e96b769f..9ca27c9d 100644
--- a/_examples/auth/jwt/tutorial/go-client/client.go
+++ b/_examples/auth/jwt/tutorial/go-client/client.go
@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/url"
"strconv"
@@ -105,5 +104,5 @@ func BindResponse(resp *http.Response, dest interface{}) error {
func RawResponse(resp *http.Response) ([]byte, error) {
defer resp.Body.Close()
- return ioutil.ReadAll(resp.Body)
+ return io.ReadAll(resp.Body)
}
diff --git a/_examples/compression/client-using-iris/main.go b/_examples/compression/client-using-iris/main.go
index 65d97131..0083b571 100644
--- a/_examples/compression/client-using-iris/main.go
+++ b/_examples/compression/client-using-iris/main.go
@@ -4,7 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"github.com/kataras/iris/v12/context"
@@ -51,7 +51,7 @@ func getExample() {
}
defer cr.Close()
- body, err := ioutil.ReadAll(cr)
+ body, err := io.ReadAll(cr)
if err != nil {
panic(err)
}
@@ -103,7 +103,7 @@ func postExample() {
}
defer cr.Close()
- body, err := ioutil.ReadAll(cr)
+ body, err := io.ReadAll(cr)
if err != nil {
panic(err)
}
diff --git a/_examples/compression/client/main.go b/_examples/compression/client/main.go
index 6c39294a..0ee40aa3 100644
--- a/_examples/compression/client/main.go
+++ b/_examples/compression/client/main.go
@@ -5,7 +5,7 @@ import (
"compress/gzip"
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
)
@@ -42,7 +42,7 @@ func getExample() {
}
defer r.Close()
- body, err := ioutil.ReadAll(r)
+ body, err := io.ReadAll(r)
if err != nil {
panic(err)
}
@@ -93,7 +93,7 @@ func postExample() {
}
defer r.Close()
- body, err := ioutil.ReadAll(r)
+ body, err := io.ReadAll(r)
if err != nil {
panic(err)
}
diff --git a/_examples/desktop/blink/main.go b/_examples/desktop/blink/main.go
index e0c3fca6..866bdd7b 100644
--- a/_examples/desktop/blink/main.go
+++ b/_examples/desktop/blink/main.go
@@ -11,8 +11,8 @@ import (
const addr = "127.0.0.1:8080"
/*
- $ go build -mod=mod -ldflags -H=windowsgui -o myapp.exe
- $ ./myapp.exe # run the app
+$ go build -mod=mod -ldflags -H=windowsgui -o myapp.exe
+$ ./myapp.exe # run the app
*/
func main() {
go runServer()
diff --git a/_examples/desktop/lorca/main.go b/_examples/desktop/lorca/main.go
index dfd001dc..a59b9623 100644
--- a/_examples/desktop/lorca/main.go
+++ b/_examples/desktop/lorca/main.go
@@ -8,8 +8,8 @@ import (
const addr = "127.0.0.1:8080"
/*
- $ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows
- $ ./myapp.exe # run
+$ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows
+$ ./myapp.exe # run
*/
func main() {
go runServer()
diff --git a/_examples/desktop/webview/main.go b/_examples/desktop/webview/main.go
index a8bab602..6272860b 100644
--- a/_examples/desktop/webview/main.go
+++ b/_examples/desktop/webview/main.go
@@ -8,21 +8,21 @@ import (
const addr = "127.0.0.1:8080"
/*
- # Windows requires special linker flags for GUI apps.
- # It's also recommended to use TDM-GCC-64 compiler for CGo.
- # http://tdm-gcc.tdragon.net/download
- #
- #
- $ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows
- $ ./myapp.exe # run
- #
- # MacOS uses app bundles for GUI apps
- $ mkdir -p example.app/Contents/MacOS
- $ go build -o example.app/Contents/MacOS/example
- $ open example.app # Or click on the app in Finder
- #
- # Note: if you see "use option -std=c99 or -std=gnu99 to compile your code"
- # please refer to: https://github.com/webview/webview/issues/188
+# Windows requires special linker flags for GUI apps.
+# It's also recommended to use TDM-GCC-64 compiler for CGo.
+# http://tdm-gcc.tdragon.net/download
+#
+#
+$ go build -mod=mod -ldflags="-H windowsgui" -o myapp.exe # build for windows
+$ ./myapp.exe # run
+#
+# MacOS uses app bundles for GUI apps
+$ mkdir -p example.app/Contents/MacOS
+$ go build -o example.app/Contents/MacOS/example
+$ open example.app # Or click on the app in Finder
+#
+# Note: if you see "use option -std=c99 or -std=gnu99 to compile your code"
+# please refer to: https://github.com/webview/webview/issues/188
*/
func main() {
go runServer()
diff --git a/_examples/file-server/basic/main_test.go b/_examples/file-server/basic/main_test.go
index 23db8229..a27067bb 100644
--- a/_examples/file-server/basic/main_test.go
+++ b/_examples/file-server/basic/main_test.go
@@ -1,7 +1,7 @@
package main
import (
- "io/ioutil"
+ "os"
"path/filepath"
"strings"
"testing"
@@ -47,7 +47,7 @@ func (r resource) loadFromBase(dir string, strip string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/file-server/embedding-files-into-app/bindata.go b/_examples/file-server/embedding-files-into-app/bindata.go
index b6f638f4..80b96bf4 100644
--- a/_examples/file-server/embedding-files-into-app/bindata.go
+++ b/_examples/file-server/embedding-files-into-app/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// assets/css/main.css
// assets/favicon.ico
// assets/js/main.js
@@ -11,7 +11,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -288,11 +287,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -348,7 +349,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/embedding-files-into-app/main_test.go b/_examples/file-server/embedding-files-into-app/main_test.go
index 94745c11..aa6eda89 100644
--- a/_examples/file-server/embedding-files-into-app/main_test.go
+++ b/_examples/file-server/embedding-files-into-app/main_test.go
@@ -1,7 +1,7 @@
package main
import (
- "io/ioutil"
+ "os"
"path/filepath"
"runtime"
"strings"
@@ -46,7 +46,7 @@ func (r resource) loadFromBase(dir string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/file-server/embedding-gzipped-files-into-app/bindata.go b/_examples/file-server/embedding-gzipped-files-into-app/bindata.go
index 1c5b2f45..4c8c93b4 100644
--- a/_examples/file-server/embedding-gzipped-files-into-app/bindata.go
+++ b/_examples/file-server/embedding-gzipped-files-into-app/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// ../embedding-files-into-app/assets/css/main.css
// ../embedding-files-into-app/assets/favicon.ico
// ../embedding-files-into-app/assets/js/main.js
@@ -11,7 +11,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -288,11 +287,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -348,7 +349,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/embedding-gzipped-files-into-app/main_test.go b/_examples/file-server/embedding-gzipped-files-into-app/main_test.go
index cf92338b..0e678f0d 100644
--- a/_examples/file-server/embedding-gzipped-files-into-app/main_test.go
+++ b/_examples/file-server/embedding-gzipped-files-into-app/main_test.go
@@ -2,7 +2,7 @@ package main
import (
"bytes"
- "io/ioutil"
+ "os"
"path/filepath"
"runtime"
"strings"
@@ -48,7 +48,7 @@ func (r resource) loadFromBase(dir string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/file-server/http2push-embedded-gzipped/bindata.go b/_examples/file-server/http2push-embedded-gzipped/bindata.go
index 78976fd8..dbea0bd3 100644
--- a/_examples/file-server/http2push-embedded-gzipped/bindata.go
+++ b/_examples/file-server/http2push-embedded-gzipped/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// ../http2push/assets/app2/app2app3/css/main.css
// ../http2push/assets/app2/app2app3/dirs/dir1/text.txt
// ../http2push/assets/app2/app2app3/dirs/dir2/text.txt
@@ -19,7 +19,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -464,11 +463,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -546,7 +547,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/http2push-embedded/bindata.go b/_examples/file-server/http2push-embedded/bindata.go
index 78976fd8..dbea0bd3 100644
--- a/_examples/file-server/http2push-embedded/bindata.go
+++ b/_examples/file-server/http2push-embedded/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// ../http2push/assets/app2/app2app3/css/main.css
// ../http2push/assets/app2/app2app3/dirs/dir1/text.txt
// ../http2push/assets/app2/app2app3/dirs/dir2/text.txt
@@ -19,7 +19,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -464,11 +463,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -546,7 +547,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go b/_examples/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go
index 0fc5312b..e9ad65da 100644
--- a/_examples/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go
+++ b/_examples/file-server/single-page-application/embedded-single-page-application-with-other-routes/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// public/app.js
// public/css/main.css
// public/index.html
@@ -11,7 +11,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -288,11 +287,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -346,7 +347,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/single-page-application/embedded-single-page-application/bindata.go b/_examples/file-server/single-page-application/embedded-single-page-application/bindata.go
index 39ca707a..53ccc9e2 100644
--- a/_examples/file-server/single-page-application/embedded-single-page-application/bindata.go
+++ b/_examples/file-server/single-page-application/embedded-single-page-application/bindata.go
@@ -12,7 +12,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -310,11 +309,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
@@ -377,7 +378,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/file-server/single-page-application/embedded-single-page-application/main_test.go b/_examples/file-server/single-page-application/embedded-single-page-application/main_test.go
index d603c81f..d1b64147 100644
--- a/_examples/file-server/single-page-application/embedded-single-page-application/main_test.go
+++ b/_examples/file-server/single-page-application/embedded-single-page-application/main_test.go
@@ -1,7 +1,7 @@
package main
import (
- "io/ioutil"
+ "os"
"path/filepath"
"runtime"
"strings"
@@ -41,7 +41,7 @@ func (r resource) loadFromBase(dir string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/file-server/subdomain/main_test.go b/_examples/file-server/subdomain/main_test.go
index 96eb882d..8674dd39 100644
--- a/_examples/file-server/subdomain/main_test.go
+++ b/_examples/file-server/subdomain/main_test.go
@@ -1,8 +1,8 @@
package main
import (
- "io/ioutil"
"net"
+ "os"
"path/filepath"
"testing"
@@ -40,7 +40,7 @@ func (r resource) loadFromBase(dir string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/logging/request-logger/accesslog-proxy/main.go b/_examples/logging/request-logger/accesslog-proxy/main.go
index 810c1397..51325504 100644
--- a/_examples/logging/request-logger/accesslog-proxy/main.go
+++ b/_examples/logging/request-logger/accesslog-proxy/main.go
@@ -1,10 +1,12 @@
-/*Package main is a proxy + accesslog example.
+/*
+Package main is a proxy + accesslog example.
In this example we will make a small proxy which listens requests on "/proxy/+path".
With two accesslog instances, one for the main application and one for the /proxy/ requests.
Of cource, you could a single accesslog for the whole application, but for the sake of the example
let's log them separately.
-We will make use of iris.StripPrefix and host.ProxyHandler.*/
+We will make use of iris.StripPrefix and host.ProxyHandler.
+*/
package main
import (
diff --git a/_examples/mvc/grpc-compatible/http-client/main.go b/_examples/mvc/grpc-compatible/http-client/main.go
index f198d398..4766f1fb 100644
--- a/_examples/mvc/grpc-compatible/http-client/main.go
+++ b/_examples/mvc/grpc-compatible/http-client/main.go
@@ -5,15 +5,15 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/json"
- "io/ioutil"
"log"
"net/http"
+ "os"
pb "github.com/kataras/iris/v12/_examples/mvc/grpc-compatible/helloworld"
)
func main() {
- b, err := ioutil.ReadFile("../server.crt")
+ b, err := os.ReadFile("../server.crt")
if err != nil {
log.Fatal(err)
}
diff --git a/_examples/mvc/login/web/controllers/users_controller.go b/_examples/mvc/login/web/controllers/users_controller.go
index 02715c48..24720b41 100644
--- a/_examples/mvc/login/web/controllers/users_controller.go
+++ b/_examples/mvc/login/web/controllers/users_controller.go
@@ -30,14 +30,16 @@ type UsersController struct {
// curl -i -u admin:password http://localhost:8080/users
//
// The correct way if you have sensitive data:
-// func (c *UsersController) Get() (results []viewmodels.User) {
-// data := c.Service.GetAll()
//
-// for _, user := range data {
-// results = append(results, viewmodels.User{user})
-// }
-// return
-// }
+// func (c *UsersController) Get() (results []viewmodels.User) {
+// data := c.Service.GetAll()
+//
+// for _, user := range data {
+// results = append(results, viewmodels.User{user})
+// }
+// return
+// }
+//
// otherwise just return the datamodels.
func (c *UsersController) Get() (results []datamodels.User) {
return c.Service.GetAll()
diff --git a/_examples/mvc/middleware/per-method/main.go b/_examples/mvc/middleware/per-method/main.go
index f4e13560..83392a23 100644
--- a/_examples/mvc/middleware/per-method/main.go
+++ b/_examples/mvc/middleware/per-method/main.go
@@ -9,9 +9,11 @@ else as well, otherwise I am going with the first one:
```go
// 1
-mvc.Configure(app.Party("/user"), func(m *mvc.Application) {
- m.Router.Use(cache.Handler(10*time.Second))
-})
+
+ mvc.Configure(app.Party("/user"), func(m *mvc.Application) {
+ m.Router.Use(cache.Handler(10*time.Second))
+ })
+
```
```go
@@ -32,10 +34,12 @@ mvc.Configure(userRouter, ...)
```go
// 4
// same:
-app.PartyFunc("/user", func(r iris.Party){
- r.Use(cache.Handler(10*time.Second))
- mvc.Configure(r, ...)
-})
+
+ app.PartyFunc("/user", func(r iris.Party){
+ r.Use(cache.Handler(10*time.Second))
+ mvc.Configure(r, ...)
+ })
+
```
If you want to use a middleware for a single route,
@@ -48,16 +52,18 @@ then you just call it on the method:
var myMiddleware := myMiddleware.New(...) // this should return an iris/context.Handler
type UserController struct{}
-func (c *UserController) GetSomething(ctx iris.Context) {
- // ctx.Proceed checks if myMiddleware called `ctx.Next()`
- // inside it and returns true if so, otherwise false.
- nextCalled := ctx.Proceed(myMiddleware)
- if !nextCalled {
- return
- }
- // else do the job here, it's allowed
-}
+ func (c *UserController) GetSomething(ctx iris.Context) {
+ // ctx.Proceed checks if myMiddleware called `ctx.Next()`
+ // inside it and returns true if so, otherwise false.
+ nextCalled := ctx.Proceed(myMiddleware)
+ if !nextCalled {
+ return
+ }
+
+ // else do the job here, it's allowed
+ }
+
```
And last, if you want to add a middleware on a specific method
diff --git a/_examples/mvc/middleware/without-ctx-next/main.go b/_examples/mvc/middleware/without-ctx-next/main.go
index 1473880e..aae02aeb 100644
--- a/_examples/mvc/middleware/without-ctx-next/main.go
+++ b/_examples/mvc/middleware/without-ctx-next/main.go
@@ -1,8 +1,10 @@
-/*Package main shows how to add done handlers in an MVC application without
+/*
+Package main shows how to add done handlers in an MVC application without
the necessity of `ctx.Next()` inside the controller's methods.
When we want the `Done` handlers of that specific mvc app's `Party`
-to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest`*/
+to be executed but we don't want to add `ctx.Next()` on the `exampleController#EndRequest`
+*/
package main
import (
diff --git a/_examples/mvc/overview/main.go b/_examples/mvc/overview/main.go
index 0e1449cf..26c2eb81 100644
--- a/_examples/mvc/overview/main.go
+++ b/_examples/mvc/overview/main.go
@@ -28,42 +28,45 @@ func pong(ctx iris.Context) {
}
/*
- +-------------------+
- | Env (DEV, PROD) |
- +---------+---------+
- | | |
- | | |
- | | |
- DEV | | | PROD
+ +-------------------+
+ | Env (DEV, PROD) |
+ +---------+---------+
+ | | |
+ | | |
+ | | |
+ DEV | | | PROD
+
-------------------+---------------------+ | +----------------------+-------------------
- | | |
- | | |
- +---+-----+ +----------------v------------------+ +----+----+
- | sqlite | | NewDB(Env) DB | | mysql |
- +---+-----+ +----------------+---+--------------+ +----+----+
- | | | |
- | | | |
- | | | |
- +--------------+-----+ +-------------------v---v-----------------+ +----+------+
- | greeterWithLogging | | NewGreetService(Env, DB) GreetService | | greeter |
- +--------------+-----+ +---------------------------+-------------+ +----+------+
- | | |
- | | |
- | +-----------------------------------------+ |
- | | GreetController | | |
- | | | | |
- | | - Service GreetService <-- | |
- | | | |
- | +-------------------+---------------------+ |
- | | |
- | | |
- | | |
- | +-----------+-----------+ |
- | | HTTP Request | |
- | +-----------------------+ |
- | | /greet?name=kataras | |
- | +-----------+-----------+ |
- | | |
+
+ | | |
+ | | |
+ +---+-----+ +----------------v------------------+ +----+----+
+ | sqlite | | NewDB(Env) DB | | mysql |
+ +---+-----+ +----------------+---+--------------+ +----+----+
+ | | | |
+ | | | |
+ | | | |
+ +--------------+-----+ +-------------------v---v-----------------+ +----+------+
+ | greeterWithLogging | | NewGreetService(Env, DB) GreetService | | greeter |
+ +--------------+-----+ +---------------------------+-------------+ +----+------+
+ | | |
+ | | |
+ | +-----------------------------------------+ |
+ | | GreetController | | |
+ | | | | |
+ | | - Service GreetService <-- | |
+ | | | |
+ | +-------------------+---------------------+ |
+ | | |
+ | | |
+ | | |
+ | +-----------+-----------+ |
+ | | HTTP Request | |
+ | +-----------------------+ |
+ | | /greet?name=kataras | |
+ | +-----------+-----------+ |
+ | | |
+
+------------------+--------+ +------------+------------+ +-------+------------------+
| model.Response (JSON) | | Response (JSON, error) | | Bad Request |
+---------------------------+ +-------------------------+ +--------------------------+
diff --git a/_examples/mvc/repository/web/controllers/movie_controller.go b/_examples/mvc/repository/web/controllers/movie_controller.go
index a800d959..9f1aec89 100644
--- a/_examples/mvc/repository/web/controllers/movie_controller.go
+++ b/_examples/mvc/repository/web/controllers/movie_controller.go
@@ -23,14 +23,16 @@ type MovieController struct {
// curl -i http://localhost:8080/movies
//
// The correct way if you have sensitive data:
-// func (c *MovieController) Get() (results []viewmodels.Movie) {
-// data := c.Service.GetAll()
//
-// for _, movie := range data {
-// results = append(results, viewmodels.Movie{movie})
-// }
-// return
-// }
+// func (c *MovieController) Get() (results []viewmodels.Movie) {
+// data := c.Service.GetAll()
+//
+// for _, movie := range data {
+// results = append(results, viewmodels.Movie{movie})
+// }
+// return
+// }
+//
// otherwise just return the datamodels.
func (c *MovieController) Get() (results []datamodels.Movie) {
return c.Service.GetAll()
diff --git a/_examples/project/api/router.go b/_examples/project/api/router.go
index c5668b7f..5b3d718a 100644
--- a/_examples/project/api/router.go
+++ b/_examples/project/api/router.go
@@ -18,7 +18,7 @@ func (srv *Server) buildRouter() {
ServerName: srv.config.ServerName,
Env: srv.config.Env,
Developer: "kataras",
- TimeLocation: time.FixedZone("Greece/Athens", 10800),
+ TimeLocation: time.FixedZone("Greece/Athens", 7200),
}))
api := srv.Party("/api")
diff --git a/_examples/request-body/read-many/main.go b/_examples/request-body/read-many/main.go
index cc22d775..af970968 100644
--- a/_examples/request-body/read-many/main.go
+++ b/_examples/request-body/read-many/main.go
@@ -8,7 +8,7 @@ func main() {
app := iris.New()
app.Post("/", logAllBody, logJSON, logFormValues, func(ctx iris.Context) {
- // body, err := ioutil.ReadAll(ctx.Request().Body) once or
+ // body, err := io.ReadAll(ctx.Request().Body) once or
body, err := ctx.GetBody() // as many times as you need.
if err != nil {
ctx.StopWithError(iris.StatusInternalServerError, err)
diff --git a/_examples/response-writer/content-negotiation/main_test.go b/_examples/response-writer/content-negotiation/main_test.go
index 08c5e5a6..acb5bf9d 100644
--- a/_examples/response-writer/content-negotiation/main_test.go
+++ b/_examples/response-writer/content-negotiation/main_test.go
@@ -4,7 +4,7 @@ import (
"bytes"
"compress/gzip"
"encoding/xml"
- "io/ioutil"
+ "io"
"testing"
"github.com/kataras/iris/v12"
@@ -69,7 +69,7 @@ func TestContentNegotiation(t *testing.T) {
t.Fatal(err)
}
- rawResponse, err := ioutil.ReadAll(zr)
+ rawResponse, err := io.ReadAll(zr)
if err != nil {
t.Fatal(err)
}
diff --git a/_examples/routing/custom-router/main.go b/_examples/routing/custom-router/main.go
index 3ec24fe2..aba16974 100644
--- a/_examples/routing/custom-router/main.go
+++ b/_examples/routing/custom-router/main.go
@@ -7,14 +7,15 @@ import (
"github.com/kataras/iris/v12/core/router"
)
-/* A Router should contain all three of the following methods:
- - HandleRequest should handle the request based on the Context.
- HandleRequest(ctx iris.Context)
- - Build should builds the handler, it's being called on router's BuildRouter.
- Build(provider router.RoutesProvider) error
- - RouteExists reports whether a particular route exists.
- RouteExists(ctx iris.Context, method, path string) bool
- - FireErrorCode(ctx iris.Context) should handle the given ctx.GetStatusCode().
+/*
+ A Router should contain all three of the following methods:
+ - HandleRequest should handle the request based on the Context.
+ HandleRequest(ctx iris.Context)
+ - Build should builds the handler, it's being called on router's BuildRouter.
+ Build(provider router.RoutesProvider) error
+ - RouteExists reports whether a particular route exists.
+ RouteExists(ctx iris.Context, method, path string) bool
+ - FireErrorCode(ctx iris.Context) should handle the given ctx.GetStatusCode().
For a more detailed, complete and useful example
you can take a look at the iris' router itself which is located at:
diff --git a/_examples/routing/custom-wrapper/main_test.go b/_examples/routing/custom-wrapper/main_test.go
index 540f0435..638cab5b 100644
--- a/_examples/routing/custom-wrapper/main_test.go
+++ b/_examples/routing/custom-wrapper/main_test.go
@@ -1,7 +1,7 @@
package main
import (
- "io/ioutil"
+ "os"
"path/filepath"
"strings"
"testing"
@@ -29,7 +29,7 @@ func (r resource) loadFromBase(dir string) string {
fullpath := filepath.Join(dir, filename)
- b, err := ioutil.ReadFile(fullpath)
+ b, err := os.ReadFile(fullpath)
if err != nil {
panic(fullpath + " failed with error: " + err.Error())
}
diff --git a/_examples/routing/route-handlers-execution-rules/main.go b/_examples/routing/route-handlers-execution-rules/main.go
index 5b503b7e..73675729 100644
--- a/_examples/routing/route-handlers-execution-rules/main.go
+++ b/_examples/routing/route-handlers-execution-rules/main.go
@@ -1,4 +1,5 @@
-/*Package main is a simple example of the behavior change of the execution flow of the handlers,
+/*
+Package main is a simple example of the behavior change of the execution flow of the handlers,
normally we need the `ctx.Next()` to call the next handler in a route's handler chain,
but with the `ExecutionRules` we can change this default behavior.
Please read below before continue.
@@ -8,11 +9,11 @@ The `Party#SetExecutionRules` alters the execution flow of the route handlers.
For example, if for some reason the desired result is the (done or all) handlers
to be executed no matter what, even if no `ctx.Next()` is called in the previous handlers:
-app.SetExecutionRules(iris.ExecutionRules {
- Begin: iris.ExecutionOptions{Force: true}, # begin handlers(.Use)
- Main: iris.ExecutionOptions{Force: true}, # main handler (.Handle/Get...)
- Done: iris.ExecutionOptions{Force: true}, # done handlers (.Done)
-})
+ app.SetExecutionRules(iris.ExecutionRules {
+ Begin: iris.ExecutionOptions{Force: true}, # begin handlers(.Use)
+ Main: iris.ExecutionOptions{Force: true}, # main handler (.Handle/Get...)
+ Done: iris.ExecutionOptions{Force: true}, # done handlers (.Done)
+ })
Note that if `true` then the only remained way to "break" the handler chain
is by calling the `ctx.StopExecution()` (now that `ctx.Next()` doesn't even matter).
@@ -22,7 +23,6 @@ the same rules will be applied to that as well.
Reset of these rules to their defaults (before `Party#Handle`) can be done
with `Party#SetExecutionRules(iris.ExecutionRules{})`.
-
*/
package main
diff --git a/_examples/url-shortener/main_test.go b/_examples/url-shortener/main_test.go
index 46d1a90d..1c6d38a1 100644
--- a/_examples/url-shortener/main_test.go
+++ b/_examples/url-shortener/main_test.go
@@ -1,7 +1,6 @@
package main
import (
- "io/ioutil"
"os"
"testing"
"time"
@@ -14,7 +13,7 @@ import (
// The rest possible checks is up to you, take it as as an exercise!
func TestURLShortener(t *testing.T) {
// temp db file
- f, err := ioutil.TempFile("", "shortener")
+ f, err := os.CreateTemp("", "shortener")
if err != nil {
t.Fatalf("creating temp file for database failed: %v", err)
}
diff --git a/_examples/view/embedding-templates-into-app/bindata.go b/_examples/view/embedding-templates-into-app/bindata.go
index 4075f21a..2df28740 100644
--- a/_examples/view/embedding-templates-into-app/bindata.go
+++ b/_examples/view/embedding-templates-into-app/bindata.go
@@ -1,6 +1,6 @@
// Code generated by go-bindata. (@generated) DO NOT EDIT.
-//Package main generated by go-bindata.// sources:
+// Package main generated by go-bindata.// sources:
// templates/layouts/layout.html
// templates/layouts/mylayout.html
// templates/page1.html
@@ -12,7 +12,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -310,11 +309,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
@@ -371,7 +372,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/view/template_amber_1_embedded/bindata.go b/_examples/view/template_amber_1_embedded/bindata.go
index 1a797f84..d92c4889 100644
--- a/_examples/view/template_amber_1_embedded/bindata.go
+++ b/_examples/view/template_amber_1_embedded/bindata.go
@@ -10,7 +10,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -266,11 +265,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
@@ -323,7 +324,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/view/template_blocks_1_embedded/bindata.go b/_examples/view/template_blocks_1_embedded/bindata.go
index 2c284465..1d3155a2 100644
--- a/_examples/view/template_blocks_1_embedded/bindata.go
+++ b/_examples/view/template_blocks_1_embedded/bindata.go
@@ -13,7 +13,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -332,11 +331,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
@@ -394,7 +395,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/view/template_jet_1_embedded/bindata.go b/_examples/view/template_jet_1_embedded/bindata.go
index 60528aff..b80211e4 100644
--- a/_examples/view/template_jet_1_embedded/bindata.go
+++ b/_examples/view/template_jet_1_embedded/bindata.go
@@ -12,7 +12,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -310,11 +309,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
@@ -371,7 +372,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/view/template_pug_2_embedded/bindata.go b/_examples/view/template_pug_2_embedded/bindata.go
index 1547e982..99d59246 100644
--- a/_examples/view/template_pug_2_embedded/bindata.go
+++ b/_examples/view/template_pug_2_embedded/bindata.go
@@ -10,7 +10,6 @@ import (
"compress/gzip"
"fmt"
"io"
- "io/ioutil"
"net/http"
"os"
"path/filepath"
@@ -266,11 +265,13 @@ var _bindata = map[string]func() (*asset, error){
// directory embedded in the file by go-bindata.
// For example if you run go-bindata on data/... and data contains the
// following hierarchy:
-// data/
-// foo.txt
-// img/
-// a.png
-// b.png
+//
+// data/
+// foo.txt
+// img/
+// a.png
+// b.png
+//
// then AssetDir("data") would return []string{"foo.txt", "img"}
// AssetDir("data/img") would return []string{"a.png", "b.png"}
// AssetDir("foo.txt") and AssetDir("nonexistent") would return an error
@@ -321,7 +322,7 @@ func RestoreAsset(dir, name string) error {
if err != nil {
return err
}
- err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
+ err = os.WriteFile(_filePath(dir, name), data, info.Mode())
if err != nil {
return err
}
diff --git a/_examples/websocket/gorilla-filewatch/main.go b/_examples/websocket/gorilla-filewatch/main.go
index e740c707..00583eb3 100644
--- a/_examples/websocket/gorilla-filewatch/main.go
+++ b/_examples/websocket/gorilla-filewatch/main.go
@@ -12,7 +12,6 @@ package main
import (
"flag"
- "io/ioutil"
"log"
"os"
"strconv"
@@ -53,7 +52,7 @@ func readFileIfModified(lastMod time.Time) ([]byte, time.Time, error) {
if !fi.ModTime().After(lastMod) {
return nil, lastMod, nil
}
- p, err := ioutil.ReadFile(filename)
+ p, err := os.ReadFile(filename)
if err != nil {
return nil, fi.ModTime(), err
}
diff --git a/apps/switch.go b/apps/switch.go
index 56952477..d3d2dba0 100644
--- a/apps/switch.go
+++ b/apps/switch.go
@@ -13,12 +13,13 @@ import (
// The cases are filtered in order of their registration.
//
// Example Code:
-// switcher := Switch(Hosts{
-// "mydomain.com": app,
-// "test.mydomain.com": testSubdomainApp,
-// "otherdomain.com": "appName",
-// })
-// switcher.Listen(":80")
+//
+// switcher := Switch(Hosts{
+// "mydomain.com": app,
+// "test.mydomain.com": testSubdomainApp,
+// "otherdomain.com": "appName",
+// })
+// switcher.Listen(":80")
//
// Note that this is NOT an alternative for a load balancer.
// The filters are executed by registration order and a matched Application
diff --git a/auth/auth.go b/auth/auth.go
index a39cd51b..ce80ce88 100644
--- a/auth/auth.go
+++ b/auth/auth.go
@@ -99,6 +99,7 @@ func MustLoad[T User](filename string) *Auth[T] {
// Must is a helper that wraps a call to a function returning (*Auth[T], error)
// and panics if the error is non-nil. It is intended for use in variable
// initializations such as
+//
// var s = auth.Must(auth.New[MyUser](config))
func Must[T User](s *Auth[T], err error) *Auth[T] {
if err != nil {
@@ -142,12 +143,13 @@ func New[T User](config Configuration) (*Auth[T], error) {
// method when a Provider of T and ErrorHandler is available through the registered Party's dependencies.
//
// Usage Example:
-// api := app.Party("/api")
-// api.EnsureStaticBindings().RegisterDependency(
-// NewAuthProviderErrorHandler(),
-// NewAuthCustomerProvider,
-// auth.Must(auth.New[Customer](authConfig)).WithProviderAndErrorHandler,
-// )
+//
+// api := app.Party("/api")
+// api.EnsureStaticBindings().RegisterDependency(
+// NewAuthProviderErrorHandler(),
+// NewAuthCustomerProvider,
+// auth.Must(auth.New[Customer](authConfig)).WithProviderAndErrorHandler,
+// )
func (s *Auth[T]) WithProviderAndErrorHandler(provider Provider[T], errHandler ErrorHandler) *Auth[T] {
if provider != nil {
for i := range s.providers {
diff --git a/cache/browser.go b/cache/browser.go
index 9462cd5f..c0fe70b1 100644
--- a/cache/browser.go
+++ b/cache/browser.go
@@ -49,10 +49,11 @@ var NoCache = func(ctx *context.Context) {
// Usage: `app.Use(cache.StaticCache(24 * time.Hour))` or `app.Use(cache.Staticcache(-1))`.
// A middleware, which is a simple Handler can be called inside another handler as well, example:
// cacheMiddleware := cache.StaticCache(...)
-// func(ctx iris.Context){
-// cacheMiddleware(ctx)
-// [...]
-// }
+//
+// func(ctx iris.Context){
+// cacheMiddleware(ctx)
+// [...]
+// }
var StaticCache = func(cacheDur time.Duration) context.Handler {
if int64(cacheDur) <= 0 {
return NoCache
diff --git a/cache/client/client.go b/cache/client/client.go
index 5d89c429..13d2fb20 100644
--- a/cache/client/client.go
+++ b/cache/client/client.go
@@ -2,7 +2,7 @@ package client
import (
"bytes"
- "io/ioutil"
+ "io"
"net/http"
"time"
@@ -17,8 +17,8 @@ import (
// register one client handler per route.
//
// it's just calls a remote cache service server/handler,
-// which lives on other, external machine.
//
+// which lives on other, external machine.
type ClientHandler struct {
// bodyHandler the original route's handler
bodyHandler context.Handler
@@ -162,7 +162,7 @@ func (h *ClientHandler) ServeHTTP(ctx *context.Context) {
// get the status code , content type and the write the response body
ctx.ContentType(response.Header.Get(cfg.ContentTypeHeader))
ctx.StatusCode(response.StatusCode)
- responseBody, err := ioutil.ReadAll(response.Body)
+ responseBody, err := io.ReadAll(response.Body)
response.Body.Close()
if err != nil {
return
diff --git a/cache/client/rule/validator.go b/cache/client/rule/validator.go
index 1f8ca36c..45cf03df 100644
--- a/cache/client/rule/validator.go
+++ b/cache/client/rule/validator.go
@@ -22,12 +22,13 @@ type PreValidator func(*context.Context) bool
//
// Q: What's the difference between this and a PreValidator?
// A: PreValidator runs BEFORE trying to get the cache, it cares only for the request
-// and if at least one PreValidator returns false then it just runs the original handler and stop there, at the other hand
-// a PostValidator runs if all PreValidators returns true and original handler is executed but with a response recorder,
-// also the PostValidator should return true to store the cached response.
-// Last, a PostValidator accepts a context
-// in order to be able to catch the original handler's response,
-// the PreValidator checks only for request.
+//
+// and if at least one PreValidator returns false then it just runs the original handler and stop there, at the other hand
+// a PostValidator runs if all PreValidators returns true and original handler is executed but with a response recorder,
+// also the PostValidator should return true to store the cached response.
+// Last, a PostValidator accepts a context
+// in order to be able to catch the original handler's response,
+// the PreValidator checks only for request.
//
// If a function of type of PostValidator returns true then the (shared-always) cache is allowed to be stored.
type PostValidator func(*context.Context) bool
diff --git a/configuration.go b/configuration.go
index 49cab717..27e332dd 100644
--- a/configuration.go
+++ b/configuration.go
@@ -2,7 +2,6 @@ package iris
import (
"fmt"
- "io/ioutil"
"os"
"os/user"
"path/filepath"
@@ -65,7 +64,7 @@ func parseYAML(filename string) (Configuration, error) {
}
// read the raw contents of the file
- data, err := ioutil.ReadFile(yamlAbsPath)
+ data, err := os.ReadFile(yamlAbsPath)
if err != nil {
return c, fmt.Errorf("parse yaml: %w", err)
}
@@ -112,7 +111,6 @@ func YAML(filename string) Configuration {
// Read more about toml's implementation at:
// https://github.com/toml-lang/toml
//
-//
// Accepts the absolute path of the configuration file.
// An error will be shown to the user via panic with the error message.
// Error may occur when the file does not exist or is not formatted correctly.
@@ -144,7 +142,7 @@ func TOML(filename string) Configuration {
}
// read the raw contents of the file
- data, err := ioutil.ReadFile(tomlAbsPath)
+ data, err := os.ReadFile(tomlAbsPath)
if err != nil {
panic(fmt.Errorf("toml :%w", err))
}
@@ -754,6 +752,7 @@ type Configuration struct {
// then the application tries to optimize for the best performance where is possible.
//
// Defaults to false.
+ // Deprecated. As of version 12.2.x this field does nothing.
EnableOptimizations bool `ini:"enable_optimizations" json:"enableOptimizations,omitempty" yaml:"EnableOptimizations" toml:"EnableOptimizations"`
// EnableProtoJSON when this field is true
// enables the proto marshaler on given proto messages when calling the Context.JSON method.
diff --git a/configuration_test.go b/configuration_test.go
index ae0e3edf..213d0fb7 100644
--- a/configuration_test.go
+++ b/configuration_test.go
@@ -1,7 +1,6 @@
package iris
import (
- "io/ioutil"
"os"
"reflect"
"testing"
@@ -103,7 +102,7 @@ func createGlobalConfiguration(t *testing.T) {
out, err := yaml.Marshal(&c)
if err == nil {
- err = ioutil.WriteFile(filename, out, os.FileMode(0666))
+ err = os.WriteFile(filename, out, os.FileMode(0666))
}
if err != nil {
t.Fatalf("error while writing the global configuration field at: %s. Trace: %v\n", filename, err)
@@ -131,7 +130,7 @@ func testConfigurationGlobal(t *testing.T, c Configurator) {
}
func TestConfigurationYAML(t *testing.T) {
- yamlFile, ferr := ioutil.TempFile("", "configuration.yml")
+ yamlFile, ferr := os.CreateTemp("", "configuration.yml")
if ferr != nil {
t.Fatal(ferr)
@@ -264,7 +263,7 @@ Other:
}
func TestConfigurationTOML(t *testing.T) {
- tomlFile, ferr := ioutil.TempFile("", "configuration.toml")
+ tomlFile, ferr := os.CreateTemp("", "configuration.toml")
if ferr != nil {
t.Fatal(ferr)
diff --git a/context/context.go b/context/context.go
index 8117afa8..a5f87f94 100644
--- a/context/context.go
+++ b/context/context.go
@@ -8,7 +8,6 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
"mime"
"mime/multipart"
"net"
@@ -31,7 +30,6 @@ import (
"github.com/Shopify/goreferrer"
"github.com/fatih/structs"
- gojson "github.com/goccy/go-json"
"github.com/iris-contrib/schema"
"github.com/mailru/easyjson"
"github.com/mailru/easyjson/jwriter"
@@ -100,7 +98,7 @@ type (
// is terminated and the error is received by the ReadJSONStream method,
// otherwise it continues to read the next available object.
// Look the `Context.ReadJSONStream` method.
- DecodeFunc func(ctx stdContext.Context, outPtr interface{}) error
+ DecodeFunc func(outPtr interface{}) error
)
// Unmarshal parses the X-encoded data and stores the result in the value pointed to by v.
@@ -539,7 +537,6 @@ func (ctx *Context) Do(handlers Handlers) {
// Router is calling this function to add the route's handler.
// If AddHandler called then the handlers will be inserted
// to the end of the already-defined route's handler.
-//
func (ctx *Context) AddHandler(handlers ...Handler) {
ctx.handlers = append(ctx.handlers, handlers...)
}
@@ -590,23 +587,26 @@ func (ctx *Context) HandlerIndex(n int) (currentIndex int) {
//
// That said let's see an example of `ctx.Proceed`:
//
-// var authMiddleware = basicauth.New(basicauth.Config{
-// Users: map[string]string{
-// "admin": "password",
-// },
-// })
+// var authMiddleware = basicauth.New(basicauth.Config{
+// Users: map[string]string{
+// "admin": "password",
+// },
+// })
+//
+// func (c *UsersController) BeginRequest(ctx iris.Context) {
+// if !ctx.Proceed(authMiddleware) {
+// ctx.StopExecution()
+// }
+// }
//
-// func (c *UsersController) BeginRequest(ctx iris.Context) {
-// if !ctx.Proceed(authMiddleware) {
-// ctx.StopExecution()
-// }
-// }
// This Get() will be executed in the same handler as `BeginRequest`,
// internally controller checks for `ctx.StopExecution`.
// So it will not be fired if BeginRequest called the `StopExecution`.
-// func(c *UsersController) Get() []models.User {
-// return c.Service.GetAll()
-//}
+//
+// func(c *UsersController) Get() []models.User {
+// return c.Service.GetAll()
+// }
+//
// Alternative way is `!ctx.IsStopped()` if middleware make use of the `ctx.StopExecution()` on failure.
func (ctx *Context) Proceed(h Handler) bool {
_, ok := ctx.ProceedAndReportIfStopped(h)
@@ -841,8 +841,7 @@ func (ctx *Context) StopWithPlainError(statusCode int, err error) {
// it will also fire the specified error code handler.
func (ctx *Context) StopWithJSON(statusCode int, jsonObject interface{}) error {
ctx.StopWithStatus(statusCode)
- _, err := ctx.writeJSON(jsonObject, nil) // do not modify - see errors.DefaultContextErrorHandler.
- return err
+ return ctx.writeJSON(jsonObject, nil) // do not modify - see errors.DefaultContextErrorHandler.
}
// StopWithProblem stops the handlers chain, writes the status code
@@ -854,8 +853,7 @@ func (ctx *Context) StopWithJSON(statusCode int, jsonObject interface{}) error {
func (ctx *Context) StopWithProblem(statusCode int, problem Problem) error {
ctx.StopWithStatus(statusCode)
problem.Status(statusCode)
- _, err := ctx.Problem(problem)
- return err
+ return ctx.Problem(problem)
}
// +------------------------------------------------------------+
@@ -939,7 +937,7 @@ func (ctx *Context) RequestPath(escape bool) string {
const sufscheme = "://"
-// GetScheme returns the full scheme of the request URL (https://, http:// or ws:// and e.t.c.``).
+// GetScheme returns the full scheme of the request URL (https://, http:// or ws:// and e.t.c.).
func GetScheme(r *http.Request) string {
scheme := r.URL.Scheme
@@ -1111,10 +1109,11 @@ func (ctx *Context) FullRequestURI() string {
// even if it's part of a private network.
//
// Look `Configuration.RemoteAddrHeaders`,
-// `Configuration.RemoteAddrHeadersForce`,
-// `Configuration.WithRemoteAddrHeader(...)`,
-// `Configuration.WithoutRemoteAddrHeader(...)` and
-// `Configuration.RemoteAddrPrivateSubnets` for more.
+//
+// Configuration.RemoteAddrHeadersForce,
+// Configuration.WithRemoteAddrHeader(...),
+// Configuration.WithoutRemoteAddrHeader(...) and
+// Configuration.RemoteAddrPrivateSubnetsW for more.
func (ctx *Context) RemoteAddr() string {
if remoteHeaders := ctx.app.ConfigurationReadOnly().GetRemoteAddrHeaders(); len(remoteHeaders) > 0 {
privateSubnets := ctx.app.ConfigurationReadOnly().GetRemoteAddrPrivateSubnets()
@@ -1176,7 +1175,7 @@ func (ctx *Context) GetHeader(name string) string {
// try to find another way of detecting the type(i.e, content type),
// there are many blogs that describe these problems and provide different kind of solutions,
// it's always depending on the application you're building,
-// this is the reason why this `IsAjax`` is simple enough for general purpose use.
+// this is the reason why this `IsAjax` is simple enough for general purpose use.
//
// Read more at: https://developer.mozilla.org/en-US/docs/AJAX
// and https://xhr.spec.whatwg.org/
@@ -1557,9 +1556,11 @@ func (ctx *Context) URLParamEscape(name string) string {
// Example:
//
// n, err := context.URLParamInt("url_query_param_name")
-// if errors.Is(err, context.ErrNotFound) {
-// // [handle error...]
-// }
+//
+// if errors.Is(err, context.ErrNotFound) {
+// // [handle error...]
+// }
+//
// Another usage would be `err == context.ErrNotFound`
// HOWEVER prefer use the new `errors.Is` as API details may change in the future.
var ErrNotFound = errors.New("not found")
@@ -1816,7 +1817,7 @@ func GetForm(r *http.Request, postMaxMemory int64, resetBody bool) (form map[str
setBody(r, body) // so the ctx.request.Body works
defer restoreBody() // so the next GetForm calls work.
- // r.Body = ioutil.NopCloser(io.TeeReader(r.Body, buf))
+ // r.Body = io.NopCloser(io.TeeReader(r.Body, buf))
} else {
resetBody = false
}
@@ -1828,7 +1829,7 @@ func GetForm(r *http.Request, postMaxMemory int64, resetBody bool) (form map[str
// subsequent calls have no effect, are idempotent.
err := r.ParseMultipartForm(postMaxMemory)
// if resetBody {
- // r.Body = ioutil.NopCloser(bytes.NewBuffer(bodyCopy))
+ // r.Body = io.NopCloser(bytes.NewBuffer(bodyCopy))
// }
if err != nil && err != http.ErrNotMultipart {
return nil, false
@@ -2037,7 +2038,6 @@ func (ctx *Context) PostValueBool(name string) (bool, error) {
// FormFile returns the first uploaded file that received from the client.
//
-//
// The default form's memory maximum size is 32MB, it can be changed by the
// `iris#WithPostMaxMemory` configurator at main configuration passed on `app.Run`'s second argument.
//
@@ -2284,7 +2284,7 @@ var emptyFunc = func() {}
// GetBody reads and returns the request body.
func GetBody(r *http.Request, resetBody bool) ([]byte, func(), error) {
- data, err := ioutil.ReadAll(r.Body)
+ data, err := io.ReadAll(r.Body)
if err != nil {
return nil, nil, err
}
@@ -2301,7 +2301,7 @@ func GetBody(r *http.Request, resetBody bool) ([]byte, func(), error) {
}
func setBody(r *http.Request, data []byte) {
- r.Body = ioutil.NopCloser(bytes.NewBuffer(data))
+ r.Body = io.NopCloser(bytes.NewBuffer(data))
}
const disableRequestBodyConsumptionContextKey = "iris.request.body.record"
@@ -2385,10 +2385,6 @@ func (ctx *Context) UnmarshalBody(outPtr interface{}, unmarshaler Unmarshaler) e
return ctx.app.Validate(outPtr)
}
-func (ctx *Context) shouldOptimize() bool {
- return ctx.app.ConfigurationReadOnly().GetEnableOptimizations()
-}
-
// JSONReader holds the JSON decode options of the `Context.ReadJSON, ReadBody` methods.
type JSONReader struct { // Note(@kataras): struct instead of optional funcs to keep consistently with the encoder options.
// DisallowUnknownFields causes the json decoder to return an error when the destination
@@ -2413,123 +2409,31 @@ type JSONReader struct { // Note(@kataras): struct instead of optional funcs to
// {"username": "makis"}
// {"username": "george"}
ArrayStream bool
-
- // Optional context cancelation of decoder when Optimize field is enabled.
- // On ReadJSON method this is automatically binded to the request context.
- Context stdContext.Context
}
-type internalJSONDecoder interface {
- Token() (json.Token, error) // gojson.Token is an alias of this, so we are ok.
- More() bool
- DisallowUnknownFields()
-}
+var ReadJSON = func(ctx *Context, outPtr interface{}, opts ...JSONReader) error {
+ decoder := json.NewDecoder(ctx.request.Body)
+ // decoder := gojson.NewDecoder(ctx.Request().Body)
+ if len(opts) > 0 {
+ options := opts[0]
-type unmarshalerContext interface {
- // UnmarshalJSON unmarshal json with context support.
- UnmarshalJSON(stdContext.Context, []byte) error //lint:ignore stdmethods external pkg.
-}
-
-func wrapDecodeFunc(decodeFunc func(interface{}) error) DecodeFunc {
- return func(_ stdContext.Context, outPtr interface{}) error {
- return decodeFunc(outPtr)
- }
-}
-
-func (options JSONReader) unmarshal(ctx stdContext.Context, body []byte, outPtr interface{}) error {
- if options.Optimize {
- if outPtr != nil {
- if _, supportsContext := outPtr.(unmarshalerContext); !supportsContext {
- return gojson.Unmarshal(body, outPtr)
- }
+ if options.DisallowUnknownFields {
+ decoder.DisallowUnknownFields()
}
-
- return gojson.UnmarshalContext(ctx, body, outPtr)
}
- return json.Unmarshal(body, outPtr)
-}
-
-func (options JSONReader) getDecoder(r io.Reader, outPtr interface{}) (internalJSONDecoder, DecodeFunc) {
- var (
- decoder internalJSONDecoder
- decodeFunc DecodeFunc
- )
-
- if options.Optimize {
- dec := gojson.NewDecoder(r)
-
- if outPtr != nil {
- // If a custom type does not implement the unnmarshal json with context interface
- // that is REQUIRED by the gojson, then fallback to the normal gojson decode without context support,
- // so we protect compatibility against existing objects.
- if _, supportsContext := outPtr.(unmarshalerContext); supportsContext {
- decodeFunc = dec.DecodeContext
- } else {
- decodeFunc = wrapDecodeFunc(dec.Decode)
- }
- } else {
- decodeFunc = dec.DecodeContext
- }
-
- decoder = dec
- } else {
- dec := json.NewDecoder(r)
- decodeFunc = wrapDecodeFunc(dec.Decode)
- decoder = dec
+ if err := decoder.Decode(&outPtr); err != nil {
+ return err
}
- if options.DisallowUnknownFields {
- decoder.DisallowUnknownFields()
- }
-
- return decoder, decodeFunc
+ return ctx.app.Validate(outPtr)
}
// ReadJSON reads JSON from request's body and binds it to a value of any json-valid type.
//
// Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-json/main.go
func (ctx *Context) ReadJSON(outPtr interface{}, opts ...JSONReader) error {
- var options JSONReader
- options.Optimize = ctx.shouldOptimize()
-
- if len(opts) > 0 {
- options = opts[0]
- }
-
- if ctx.IsRecordingBody() {
- body, restoreBody, err := GetBody(ctx.request, true)
- if err != nil {
- return err
- }
- restoreBody()
-
- err = options.unmarshal(ctx.request.Context(), body, outPtr)
- if err != nil {
- return err
- }
- } else {
- _, decodeFunc := options.getDecoder(ctx.request.Body, outPtr)
- err := decodeFunc(ctx.request.Context(), outPtr)
- if err != nil {
- return err
- }
- }
-
- return ctx.app.Validate(outPtr)
-
- /*
- b, err := ctx.GetBody()
- if err != nil {
- return err
- }
-
- if options.Optimize {
- return gojson.UnmarshalContext(ctx.request.Context(), b, outPtr)
- } else {
- return json.Unmarshal(b, outPtr)
- }
- */
+ return ReadJSON(ctx, outPtr, opts...)
}
// ReadJSONStream is an alternative of ReadJSON which can reduce the memory load
@@ -2543,21 +2447,16 @@ func (ctx *Context) ReadJSON(outPtr interface{}, opts ...JSONReader) error {
//
// Example: https://github.com/kataras/iris/blob/master/_examples/request-body/read-json-stream/main.go
func (ctx *Context) ReadJSONStream(onDecode func(DecodeFunc) error, opts ...JSONReader) error {
- var options JSONReader
- if len(opts) > 0 {
- options = opts[0]
- }
+ decoder := json.NewDecoder(ctx.request.Body)
- decoder, decodeFunc := options.getDecoder(ctx.request.Body, nil)
-
- if options.ArrayStream {
+ if len(opts) > 0 && opts[0].ArrayStream {
_, err := decoder.Token() // read open bracket.
if err != nil {
return err
}
for decoder.More() { // hile the array contains values.
- if err = onDecode(decodeFunc); err != nil {
+ if err = onDecode(decoder.Decode); err != nil {
return err
}
}
@@ -2568,7 +2467,7 @@ func (ctx *Context) ReadJSONStream(onDecode func(DecodeFunc) error, opts ...JSON
// while the array contains values
for decoder.More() {
- if err := onDecode(decodeFunc); err != nil {
+ if err := onDecode(decoder.Decode); err != nil {
return err
}
}
@@ -2788,7 +2687,7 @@ func (ctx *Context) ReadMultipartRelated() (MultipartRelated, error) {
}
defer part.Close()
- b, err := ioutil.ReadAll(part)
+ b, err := io.ReadAll(part)
if err != nil {
return MultipartRelated{}, fmt.Errorf("multipart related: next part: read: %w", err)
}
@@ -3149,13 +3048,14 @@ func (ctx *Context) SetLastModified(modtime time.Time) {
// that has to perform one or more client side preconditions before the actual check, e.g. `CheckIfModifiedSince`.
// Usage:
// ok, err := context.CheckIfModifiedSince(modTime)
-// if err != nil {
-// if errors.Is(err, context.ErrPreconditionFailed) {
-// [handle missing client conditions,such as not valid request method...]
-// }else {
-// [the error is probably a time parse error...]
-// }
-// }
+//
+// if err != nil {
+// if errors.Is(err, context.ErrPreconditionFailed) {
+// [handle missing client conditions,such as not valid request method...]
+// }else {
+// [the error is probably a time parse error...]
+// }
+// }
var ErrPreconditionFailed = errors.New("precondition failed")
// CheckIfModifiedSince checks if the response is modified since the "modtime".
@@ -3232,9 +3132,9 @@ func (ctx *Context) WriteWithExpiration(body []byte, modtime time.Time) (int, er
//
// This function may be used in the following cases:
//
-// * if response body is too big (more than iris.LimitRequestBodySize(if set)).
-// * if response body is streamed from slow external sources.
-// * if response body must be streamed to the client in chunks.
+// - if response body is too big (more than iris.LimitRequestBodySize(if set)).
+// - if response body is streamed from slow external sources.
+// - if response body must be streamed to the client in chunks.
// (aka `http server push`).
func (ctx *Context) StreamWriter(writer func(w io.Writer) error) error {
cancelCtx := ctx.Request().Context()
@@ -3287,10 +3187,12 @@ func (ctx *Context) ClientSupportsEncoding(encodings ...string) bool {
// will change the response writer to a compress writer instead.
// All future write and rich write methods will respect this option.
// Usage:
-// app.Use(func(ctx iris.Context){
-// err := ctx.CompressWriter(true)
-// ctx.Next()
-// })
+//
+// app.Use(func(ctx iris.Context){
+// err := ctx.CompressWriter(true)
+// ctx.Next()
+// })
+//
// The recommendation is to compress data as much as possible and therefore to use this field,
// but some types of resources, such as jpeg images, are already compressed.
// Sometimes, using additional compression doesn't reduce payload size and
@@ -3350,15 +3252,18 @@ func (ctx *Context) CompressWriter(enable bool) error {
// All future calls of `ctx.GetBody/ReadXXX/UnmarshalBody` methods will respect this option.
//
// Usage:
-// app.Use(func(ctx iris.Context){
-// err := ctx.CompressReader(true)
-// ctx.Next()
-// })
+//
+// app.Use(func(ctx iris.Context){
+// err := ctx.CompressReader(true)
+// ctx.Next()
+// })
+//
// More:
-// if cr, ok := ctx.Request().Body.(*CompressReader); ok {
-// cr.Src // the original request body
-// cr.Encoding // the compression algorithm.
-// }
+//
+// if cr, ok := ctx.Request().Body.(*CompressReader); ok {
+// cr.Src // the original request body
+// cr.Encoding // the compression algorithm.
+// }
//
// It returns `ErrRequestNotCompressed` if client's request data are not compressed
// (or empty)
@@ -3592,15 +3497,16 @@ func (ctx *Context) fireFallbackViewOnce(err ErrViewNotExist) error {
// is responsible to handle the error or render a different view.
//
// Usage:
-// FallbackView(iris.FallbackView("fallback.html"))
-// FallbackView(iris.FallbackViewLayout("layouts/fallback.html"))
-// OR
-// FallbackView(iris.FallbackViewFunc(ctx iris.Context, err iris.ErrViewNotExist) error {
-// err.Name is the previous template name.
-// err.IsLayout reports whether the failure came from the layout template.
-// err.Data is the template data provided to the previous View call.
-// [...custom logic e.g. ctx.View("fallback", err.Data)]
-// })
+//
+// FallbackView(iris.FallbackView("fallback.html"))
+// FallbackView(iris.FallbackViewLayout("layouts/fallback.html"))
+// OR
+// FallbackView(iris.FallbackViewFunc(ctx iris.Context, err iris.ErrViewNotExist) error {
+// err.Name is the previous template name.
+// err.IsLayout reports whether the failure came from the layout template.
+// err.Data is the template data provided to the previous View call.
+// [...custom logic e.g. ctx.View("fallback", err.Data)]
+// })
func (ctx *Context) FallbackView(providers ...FallbackViewProvider) {
key := ctx.app.ConfigurationReadOnly().GetFallbackViewContextKey()
if key == "" {
@@ -3749,8 +3655,6 @@ type ProtoMarshalOptions = protojson.MarshalOptions
// JSON contains the options for the JSON (Context's) Renderer.
type JSON struct {
- // http-specific
- StreamingJSON bool `yaml:"StreamingJSON"`
// content-specific
UnescapeHTML bool `yaml:"UnescapeHTML"`
Indent string `yaml:"Indent"`
@@ -3772,8 +3676,7 @@ var DefaultJSONOptions = JSON{}
// IsDefault reports whether this JSON options structure holds the default values.
func (j *JSON) IsDefault() bool {
- return j.StreamingJSON == DefaultJSONOptions.StreamingJSON &&
- j.UnescapeHTML == DefaultJSONOptions.UnescapeHTML &&
+ return j.UnescapeHTML == DefaultJSONOptions.UnescapeHTML &&
j.Indent == DefaultJSONOptions.Indent &&
j.Prefix == DefaultJSONOptions.Prefix &&
j.ASCII == DefaultJSONOptions.ASCII &&
@@ -3858,28 +3761,24 @@ func (ctx *Context) handleSpecialJSONResponseValue(v interface{}, options *JSON)
}
// WriteJSON marshals the given interface object and writes the JSON response to the 'writer'.
-func WriteJSON(ctx stdContext.Context, writer io.Writer, v interface{}, options *JSON, shouldOptimize bool) (int, error) {
- if options.StreamingJSON {
- var err error
- if shouldOptimize {
- // jsoniterConfig := jsoniter.Config{
- // EscapeHTML: !options.UnescapeHTML,
- // IndentionStep: 4,
- // }.Froze()
- // enc := jsoniterConfig.NewEncoder(ctx.writer)
- // err = enc.Encode(v)
- enc := gojson.NewEncoder(writer)
- enc.SetEscapeHTML(!options.UnescapeHTML)
- enc.SetIndent(options.Prefix, options.Indent)
- err = enc.EncodeContext(ctx, v)
- } else {
- enc := json.NewEncoder(writer)
- enc.SetEscapeHTML(!options.UnescapeHTML)
- enc.SetIndent(options.Prefix, options.Indent)
- err = enc.Encode(v)
- }
+var WriteJSON = func(ctx *Context, v interface{}, options *JSON) error {
+ if !options.Secure && !options.ASCII && options.Prefix == "" {
+ // jsoniterConfig := jsoniter.Config{
+ // EscapeHTML: !options.UnescapeHTML,
+ // IndentionStep: 4,
+ // }.Froze()
+ // enc := jsoniterConfig.NewEncoder(ctx.writer)
+ // err = enc.Encode(v)
+ //
+ // enc := gojson.NewEncoder(ctx.writer)
+ // enc.SetEscapeHTML(!options.UnescapeHTML)
+ // enc.SetIndent(options.Prefix, options.Indent)
+ // err = enc.EncodeContext(ctx, v)
+ enc := json.NewEncoder(ctx.writer)
+ enc.SetEscapeHTML(!options.UnescapeHTML)
+ enc.SetIndent(options.Prefix, options.Indent)
- return 0, err
+ return enc.Encode(v)
}
var (
@@ -3887,35 +3786,15 @@ func WriteJSON(ctx stdContext.Context, writer io.Writer, v interface{}, options
err error
)
- // Let's keep it as it is.
- // if !shouldOptimize && options.Indent == "" {
- // options.Indent = " "
- // }
-
if indent := options.Indent; indent != "" {
- if shouldOptimize {
- // result,err = jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent
- result, err = gojson.MarshalIndent(v, "", indent)
- } else {
- result, err = json.MarshalIndent(v, "", indent)
- }
-
+ result, err = json.MarshalIndent(v, "", indent)
result = append(result, newLineB...)
} else {
- if shouldOptimize {
- // result, err = jsoniter.ConfigCompatibleWithStandardLibrary.Marshal
- if ctx != nil {
- result, err = gojson.MarshalContext(ctx, v)
- } else {
- result, err = gojson.Marshal(v)
- }
- } else {
- result, err = json.Marshal(v)
- }
+ result, err = json.Marshal(v)
}
if err != nil {
- return 0, err
+ return err
}
prependSecure := false
@@ -3960,7 +3839,8 @@ func WriteJSON(ctx stdContext.Context, writer io.Writer, v interface{}, options
result = append(stringToBytes(prefix), result...)
}
- return writer.Write(result)
+ _, err = ctx.Write(result)
+ return err
}
// See https://golang.org/src/strings/builder.go#L45
@@ -4007,25 +3887,27 @@ func (ctx *Context) handleContextError(err error) {
}
// JSON marshals the given "v" value to JSON and writes the response to the client.
-// Look the Configuration.EnableProtoJSON/EnableEasyJSON and EnableOptimizations too.
+// Look the Configuration.EnableProtoJSON and EnableEasyJSON too.
//
// It reports any JSON parser or write errors back to the caller.
// Look the Application.SetContextErrorHandler to override the
// default status code 500 with a custom error response.
//
-// It can, optionally, accept the JSON structure which may hold customizations over the
-// final JSON response but keep in mind that the caller should NOT modify that JSON options
-// value in another goroutine while JSON method is still running.
-func (ctx *Context) JSON(v interface{}, opts ...JSON) (n int, err error) {
+// Customize the behavior of every `Context.JSON“ can be achieved
+// by modifying the package-level `WriteJSON` function on program initilization.
+func (ctx *Context) JSON(v interface{}, opts ...JSON) (err error) {
var options *JSON
if len(opts) > 0 {
options = &opts[0]
+ } else {
+ // If no options are given safely read the already-initialized value.
+ options = &DefaultJSONOptions
}
- if n, err = ctx.writeJSON(v, options); err != nil {
+ if err = ctx.writeJSON(v, options); err != nil {
// if no options are given or OmitErrorHandler is true
// then do call the error handler (which may lead to a cycle).
- if options == nil || !options.OmitErrorHandler {
+ if !options.OmitErrorHandler {
ctx.handleContextError(err)
}
}
@@ -4033,76 +3915,38 @@ func (ctx *Context) JSON(v interface{}, opts ...JSON) (n int, err error) {
return
}
-func (ctx *Context) writeJSON(v interface{}, options *JSON) (int, error) {
+func (ctx *Context) writeJSON(v interface{}, options *JSON) error {
ctx.ContentType(ContentJSONHeaderValue)
// After content type given and before everything else, try handle proto or easyjson, no matter the performance mode.
- if handled, n, err := ctx.handleSpecialJSONResponseValue(v, options); handled {
- return n, err
+ if handled, _, err := ctx.handleSpecialJSONResponseValue(v, options); handled {
+ return err
}
- shouldOptimize := ctx.shouldOptimize()
- if options == nil {
- if shouldOptimize {
- // If no options given and optimizations are enabled.
- // write using the fast json marshaler with the http request context as soon as possible.
- result, err := gojson.MarshalContext(ctx.request.Context(), v)
- if err != nil {
- return 0, err
- }
-
- return ctx.Write(result)
- }
-
- // Else if no options given neither optimizations are enabled, then safely read the already-initialized object.
- options = &DefaultJSONOptions
- }
-
- return WriteJSON(ctx, ctx.writer, v, options, shouldOptimize)
+ return WriteJSON(ctx, v, options)
}
var finishCallbackB = []byte(");")
-// WriteJSONP marshals the given interface object and writes the JSON response to the writer.
-func WriteJSONP(writer io.Writer, v interface{}, options JSONP, optimize bool) (int, error) {
+// WriteJSONP marshals the given interface object and writes the JSONP response to the writer.
+var WriteJSONP = func(ctx *Context, v interface{}, options *JSONP) (err error) {
if callback := options.Callback; callback != "" {
- n, err := writer.Write(stringToBytes(callback + "("))
+ _, err = ctx.Write(stringToBytes(callback + "("))
if err != nil {
- return n, err
+ return err
}
- defer writer.Write(finishCallbackB)
+ defer func() {
+ if err == nil {
+ ctx.Write(finishCallbackB)
+ }
+ }()
}
- if !optimize && options.Indent == "" {
- options.Indent = " "
- }
-
- if indent := options.Indent; indent != "" {
- marshalIndent := json.MarshalIndent
- if optimize {
- // marshalIndent = jsoniter.ConfigCompatibleWithStandardLibrary.MarshalIndent
- marshalIndent = gojson.MarshalIndent
- }
-
- result, err := marshalIndent(v, "", indent)
- if err != nil {
- return 0, err
- }
- result = append(result, newLineB...)
- return writer.Write(result)
- }
-
- marshal := json.Marshal
- if optimize {
- // marshal = jsoniter.ConfigCompatibleWithStandardLibrary.Marshal
- marshal = gojson.Marshal
- }
-
- result, err := marshal(v)
- if err != nil {
- return 0, err
- }
- return writer.Write(result)
+ err = WriteJSON(ctx, v, &JSON{
+ Indent: options.Indent,
+ OmitErrorHandler: options.OmitErrorHandler,
+ })
+ return err
}
// DefaultJSONPOptions is the optional settings that are being used
@@ -4114,14 +3958,16 @@ var DefaultJSONPOptions = JSONP{}
// It reports any JSON parser or write errors back to the caller.
// Look the Application.SetContextErrorHandler to override the
// default status code 500 with a custom error response.
-func (ctx *Context) JSONP(v interface{}, opts ...JSONP) (n int, err error) {
- options := DefaultJSONPOptions
+func (ctx *Context) JSONP(v interface{}, opts ...JSONP) (err error) {
+ var options *JSONP
if len(opts) > 0 {
- options = opts[0]
+ options = &opts[0]
+ } else {
+ options = &DefaultJSONPOptions
}
ctx.ContentType(ContentJavascriptHeaderValue)
- if n, err = WriteJSONP(ctx.writer, v, options, ctx.shouldOptimize()); err != nil {
+ if err = WriteJSONP(ctx, v, options); err != nil {
if !options.OmitErrorHandler {
ctx.handleContextError(err)
}
@@ -4174,32 +4020,21 @@ func (m xmlMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
}
// WriteXML marshals the given interface object and writes the XML response to the writer.
-func WriteXML(writer io.Writer, v interface{}, options XML, optimize bool) (int, error) {
+var WriteXML = func(ctx *Context, v interface{}, options *XML) error {
if prefix := options.Prefix; prefix != "" {
- n, err := writer.Write(stringToBytes(prefix))
+ _, err := ctx.Write(stringToBytes(prefix))
if err != nil {
- return n, err
+ return err
}
}
- if !optimize && options.Indent == "" {
- options.Indent = " " // Two spaces for XML is the default indentation when not optimized.
+ encoder := xml.NewEncoder(ctx.writer)
+ encoder.Indent("", options.Indent)
+ if err := encoder.Encode(v); err != nil {
+ return err
}
- if indent := options.Indent; indent != "" {
- result, err := xml.MarshalIndent(v, "", indent)
- if err != nil {
- return 0, err
- }
- result = append(result, newLineB...)
- return writer.Write(result)
- }
-
- result, err := xml.Marshal(v)
- if err != nil {
- return 0, err
- }
- return writer.Write(result)
+ return encoder.Flush()
}
// DefaultXMLOptions is the optional settings that are being used
@@ -4212,14 +4047,16 @@ var DefaultXMLOptions = XML{}
// It reports any XML parser or write errors back to the caller.
// Look the Application.SetContextErrorHandler to override the
// default status code 500 with a custom error response.
-func (ctx *Context) XML(v interface{}, opts ...XML) (n int, err error) {
- options := DefaultXMLOptions
+func (ctx *Context) XML(v interface{}, opts ...XML) (err error) {
+ var options *XML
if len(opts) > 0 {
- options = opts[0]
+ options = &opts[0]
+ } else {
+ options = &DefaultXMLOptions
}
ctx.ContentType(ContentXMLHeaderValue)
- if n, err = WriteXML(ctx.writer, v, options, ctx.shouldOptimize()); err != nil {
+ if err = WriteXML(ctx, v, options); err != nil {
if !options.OmitErrorHandler {
ctx.handleContextError(err)
}
@@ -4239,7 +4076,7 @@ func (ctx *Context) XML(v interface{}, opts ...XML) (n int, err error) {
// send a response of content type "application/problem+xml" instead.
//
// Read more at: https://github.com/kataras/iris/wiki/Routing-error-handlers
-func (ctx *Context) Problem(v interface{}, opts ...ProblemOptions) (int, error) {
+func (ctx *Context) Problem(v interface{}, opts ...ProblemOptions) error {
options := DefaultProblemOptions
if len(opts) > 0 {
options = opts[0]
@@ -4276,13 +4113,14 @@ func (ctx *Context) Problem(v interface{}, opts ...ProblemOptions) (int, error)
}
// WriteMarkdown parses the markdown to html and writes these contents to the writer.
-func WriteMarkdown(writer io.Writer, markdownB []byte, options Markdown) (n int, err error) {
+var WriteMarkdown = func(ctx *Context, markdownB []byte, options *Markdown) error {
buf := blackfriday.Run(markdownB)
if options.Sanitize {
buf = bluemonday.UGCPolicy().SanitizeBytes(buf)
}
- return writer.Write(buf)
+ _, err := ctx.Write(buf)
+ return err
}
// DefaultMarkdownOptions is the optional settings that are being used
@@ -4294,14 +4132,16 @@ var DefaultMarkdownOptions = Markdown{}
// It reports any Markdown parser or write errors back to the caller.
// Look the Application.SetContextErrorHandler to override the
// default status code 500 with a custom error response.
-func (ctx *Context) Markdown(markdownB []byte, opts ...Markdown) (n int, err error) {
- options := DefaultMarkdownOptions
+func (ctx *Context) Markdown(markdownB []byte, opts ...Markdown) (err error) {
+ var options *Markdown
if len(opts) > 0 {
- options = opts[0]
+ options = &opts[0]
+ } else {
+ options = &DefaultMarkdownOptions
}
ctx.ContentType(ContentHTMLHeaderValue)
- if n, err = WriteMarkdown(ctx.writer, markdownB, options); err != nil {
+ if err = WriteMarkdown(ctx, markdownB, options); err != nil {
if !options.OmitErrorHandler {
ctx.handleContextError(err)
}
@@ -4310,31 +4150,46 @@ func (ctx *Context) Markdown(markdownB []byte, opts ...Markdown) (n int, err err
return
}
+// WriteYAML sends YAML response to the client.
+var WriteYAML = func(ctx *Context, v interface{}, indentSpace int) error {
+ encoder := yaml.NewEncoder(ctx.writer)
+ encoder.SetIndent(indentSpace)
+
+ if err := encoder.Encode(v); err != nil {
+ return err
+ }
+
+ return encoder.Close()
+}
+
// YAML marshals the given "v" value using the yaml marshaler and writes the result to the client.
//
// It reports any YAML parser or write errors back to the caller.
// Look the Application.SetContextErrorHandler to override the
// default status code 500 with a custom error response.
-func (ctx *Context) YAML(v interface{}) (int, error) {
- out, err := yaml.Marshal(v)
- if err != nil {
- ctx.handleContextError(err)
- return 0, err
- }
-
+func (ctx *Context) YAML(v interface{}) error {
ctx.ContentType(ContentYAMLHeaderValue)
- n, err := ctx.Write(out)
+
+ err := WriteYAML(ctx, v, 0)
if err != nil {
ctx.handleContextError(err)
+ return err
}
- return n, err
+ return nil
}
// TextYAML calls the Context.YAML method but with the text/yaml content type instead.
-func (ctx *Context) TextYAML(v interface{}) (int, error) {
- ctx.contentTypeOnce(ContentYAMLTextHeaderValue, "")
- return ctx.YAML(v)
+func (ctx *Context) TextYAML(v interface{}) error {
+ ctx.ContentType(ContentYAMLTextHeaderValue)
+
+ err := WriteYAML(ctx, v, 4)
+ if err != nil {
+ ctx.handleContextError(err)
+ return err
+ }
+
+ return nil
}
// Protobuf marshals the given "v" value of proto Message and writes its result to the client.
@@ -4583,19 +4438,54 @@ func (ctx *Context) Negotiate(v interface{}) (int, error) {
case ContentTextHeaderValue, ContentHTMLHeaderValue:
return ctx.WriteString(v.(string))
case ContentMarkdownHeaderValue:
- return ctx.Markdown(v.([]byte))
+ err := ctx.Markdown(v.([]byte))
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentJSONHeaderValue:
- return ctx.JSON(v)
+ err := ctx.JSON(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentJSONProblemHeaderValue, ContentXMLProblemHeaderValue:
- return ctx.Problem(v)
+ err := ctx.Problem(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentJavascriptHeaderValue:
- return ctx.JSONP(v)
+ err := ctx.JSONP(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentXMLHeaderValue, ContentXMLUnreadableHeaderValue:
- return ctx.XML(v)
+ err := ctx.XML(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentYAMLHeaderValue:
- return ctx.YAML(v)
+ err := ctx.YAML(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentYAMLTextHeaderValue:
- return ctx.TextYAML(v)
+ err := ctx.TextYAML(v)
+ if err != nil {
+ return 0, err
+ }
+
+ return ctx.writer.Written(), nil
case ContentProtobufHeaderValue:
msg, ok := v.(proto.Message)
if !ok {
@@ -5438,15 +5328,15 @@ const cookieOptionsContextKey = "iris.cookie.options"
// cookies sent or received from the next Handler in the chain.
//
// Available builtin Cookie options are:
-// * CookieAllowReclaim
-// * CookieAllowSubdomains
-// * CookieSecure
-// * CookieHTTPOnly
-// * CookieSameSite
-// * CookiePath
-// * CookieCleanPath
-// * CookieExpires
-// * CookieEncoding
+// - CookieAllowReclaim
+// - CookieAllowSubdomains
+// - CookieSecure
+// - CookieHTTPOnly
+// - CookieSameSite
+// - CookiePath
+// - CookieCleanPath
+// - CookieExpires
+// - CookieEncoding
//
// Example at: https://github.com/kataras/iris/tree/master/_examples/cookies/securecookie
func (ctx *Context) AddCookieOptions(options ...CookieOption) {
@@ -5554,8 +5444,9 @@ var SetCookieKVExpiration = 8760 * time.Hour
// (note that client should be responsible for that if server sent an empty cookie's path, all browsers are compatible)
// ctx.SetCookieKV(name, value, iris.CookieCleanPath/iris.CookiePath(""))
// More:
-// iris.CookieExpires(time.Duration)
-// iris.CookieHTTPOnly(false)
+//
+// iris.CookieExpires(time.Duration)
+// iris.CookieHTTPOnly(false)
//
// Examples: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
func (ctx *Context) SetCookieKV(name, value string, options ...CookieOption) {
@@ -6102,11 +5993,11 @@ const userContextKey = "iris.user"
// next handlers in the chain.
//
// The "i" input argument can be:
-// - A value which completes the User interface
-// - A map[string]interface{}.
-// - A value which does not complete the whole User interface
-// - A value which does not complete the User interface at all
-// (only its `User().GetRaw` method is available).
+// - A value which completes the User interface
+// - A map[string]interface{}.
+// - A value which does not complete the whole User interface
+// - A value which does not complete the User interface at all
+// (only its `User().GetRaw` method is available).
//
// Look the `User` method to retrieve it.
func (ctx *Context) SetUser(i interface{}) error {
@@ -6174,21 +6065,21 @@ func (ctx *Context) Deadline() (deadline time.Time, ok bool) {
//
// Done is provided for use in select statements:
//
-// // Stream generates values with DoSomething and sends them to out
-// // until DoSomething returns an error or ctx.Done is closed.
-// func Stream(ctx context.Context, out chan<- Value) error {
-// for {
-// v, err := DoSomething(ctx)
-// if err != nil {
-// return err
-// }
-// select {
-// case <-ctx.Done():
-// return ctx.Err()
-// case out <- v:
-// }
-// }
-// }
+// // Stream generates values with DoSomething and sends them to out
+// // until DoSomething returns an error or ctx.Done is closed.
+// func Stream(ctx context.Context, out chan<- Value) error {
+// for {
+// v, err := DoSomething(ctx)
+// if err != nil {
+// return err
+// }
+// select {
+// case <-ctx.Done():
+// return ctx.Err()
+// case out <- v:
+// }
+// }
+// }
//
// See https://blog.golang.org/pipelines for more examples of how to use
// a Done channel for cancellation.
diff --git a/context/context_user.go b/context/context_user.go
index d76ba6d4..3b138c05 100644
--- a/context/context_user.go
+++ b/context/context_user.go
@@ -166,10 +166,12 @@ func (u *SimpleUser) GetField(key string) (interface{}, error) {
// UserMap can be used to convert a common map[string]interface{} to a User.
// Usage:
-// user := map[string]interface{}{
-// "username": "kataras",
-// "age" : 27,
-// }
+//
+// user := map[string]interface{}{
+// "username": "kataras",
+// "age" : 27,
+// }
+//
// ctx.SetUser(user)
// OR
// user := UserStruct{....}
diff --git a/context/handler.go b/context/handler.go
index 13f94128..60e03155 100644
--- a/context/handler.go
+++ b/context/handler.go
@@ -275,7 +275,6 @@ type Filter func(*Context) bool
// Handlers here should act like middleware, they should contain `ctx.Next` to proceed
// to the next handler of the chain. Those "handlers" are registered to the per-request context.
//
-//
// It checks the "filter" and if passed then
// it, correctly, executes the "handlers".
//
diff --git a/context/request_params.go b/context/request_params.go
index b45dbe70..ea9b6c0b 100644
--- a/context/request_params.go
+++ b/context/request_params.go
@@ -131,11 +131,12 @@ func (r *RequestParams) GetIntUnslashed(key string) (int, bool) {
// Key is the specific type, which should be unique.
// The value is a function which accepts the parameter index
// and it should return the value as the parameter type evaluator expects it.
-// i.e [reflect.TypeOf("string")] = func(paramIndex int) interface{} {
-// return func(ctx *Context) {
-// return ctx.Params().GetEntryAt(paramIndex).ValueRaw.()
-// }
-// }
+//
+// i.e [reflect.TypeOf("string")] = func(paramIndex int) interface{} {
+// return func(ctx *Context) {
+// return ctx.Params().GetEntryAt(paramIndex).ValueRaw.()
+// }
+// }
//
// Read https://github.com/kataras/iris/tree/master/_examples/routing/macros for more details.
// Checks for total available request parameters length
@@ -261,7 +262,9 @@ var ParamResolvers = map[reflect.Type]func(paramIndex int) interface{}{
// and the parameter's index based on the registered path.
// Usage: nameResolver := ParamResolverByKindAndKey(reflect.TypeOf(""), 0)
// Inside a Handler: nameResolver.Call(ctx)[0]
-// it will return the reflect.Value Of the exact type of the parameter(based on the path parameters and macros).
+//
+// it will return the reflect.Value Of the exact type of the parameter(based on the path parameters and macros).
+//
// It is only useful for dynamic binding of the parameter, it is used on "hero" package and it should be modified
// only when Macros are modified in such way that the default selections for the available go std types are not enough.
//
diff --git a/context/response_recorder.go b/context/response_recorder.go
index ab19c7aa..db3241ee 100644
--- a/context/response_recorder.go
+++ b/context/response_recorder.go
@@ -4,7 +4,7 @@ import (
"bytes"
"errors"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/textproto"
"strconv"
@@ -32,7 +32,7 @@ func releaseResponseRecorder(w *ResponseRecorder) {
// A ResponseRecorder is used mostly for testing
// in order to record and modify, if necessary, the body and status code and headers.
//
-// See `context.Recorder`` method too.
+// See `context.Recorder“ method too.
type ResponseRecorder struct {
ResponseWriter
@@ -366,7 +366,7 @@ func (w *ResponseRecorder) Result() *http.Response { // a modified copy of net/h
}
res.Status = fmt.Sprintf("%03d %s", res.StatusCode, http.StatusText(res.StatusCode))
if w.chunks != nil {
- res.Body = ioutil.NopCloser(bytes.NewReader(w.chunks))
+ res.Body = io.NopCloser(bytes.NewReader(w.chunks))
} else {
res.Body = http.NoBody
}
diff --git a/context/status.go b/context/status.go
index 59bd8ebe..af194872 100644
--- a/context/status.go
+++ b/context/status.go
@@ -111,7 +111,6 @@ func StatusText(code int) string {
// Read more at `iris/Configuration#DisableAutoFireStatusCode` and
// `iris/core/router/Party#OnAnyErrorCode` for relative information.
//
-//
// Modify this variable when your Iris server or/and client
// not follows the RFC: https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
var StatusCodeNotSuccessful = func(statusCode int) bool { return statusCode >= 400 }
diff --git a/core/handlerconv/from_std.go b/core/handlerconv/from_std.go
index 404657b2..3bb8627f 100644
--- a/core/handlerconv/from_std.go
+++ b/core/handlerconv/from_std.go
@@ -10,9 +10,10 @@ import (
// FromStd converts native http.Handler & http.HandlerFunc to context.Handler.
//
// Supported form types:
-// .FromStd(h http.Handler)
-// .FromStd(func(w http.ResponseWriter, r *http.Request))
-// .FromStd(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc))
+//
+// .FromStd(h http.Handler)
+// .FromStd(func(w http.ResponseWriter, r *http.Request))
+// .FromStd(func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc))
func FromStd(handler interface{}) context.Handler {
switch h := handler.(type) {
case context.Handler:
diff --git a/core/memstore/memstore.go b/core/memstore/memstore.go
index 1da39ca3..95322ece 100644
--- a/core/memstore/memstore.go
+++ b/core/memstore/memstore.go
@@ -730,7 +730,6 @@ func (e Entry) Value() interface{} {
// Save same as `Set`
// However, if "immutable" is true then saves it as immutable (same as `SetImmutable`).
//
-//
// Returns the entry and true if it was just inserted, meaning that
// it will return the entry and a false boolean if the entry exists and it has been updated.
func (r *Store) Save(key string, value interface{}, immutable bool) (Entry, bool) {
diff --git a/core/router/api_builder.go b/core/router/api_builder.go
index f0a14874..c1f51240 100644
--- a/core/router/api_builder.go
+++ b/core/router/api_builder.go
@@ -377,8 +377,9 @@ func (api *APIBuilder) RegisterDependency(dependencies ...interface{}) {
// (see ConfigureContainer().RegisterDependency)
// or leave the framework to parse the request and fill the values accordingly.
// The output of the "handlersFn" can be any output result:
-// custom structs , string, []byte, int, error,
-// a combination of the above, hero.Result(hero.View | hero.Response) and more.
+//
+// custom structs , string, []byte, int, error,
+// a combination of the above, hero.Result(hero.View | hero.Response) and more.
//
// If more than one handler function is registered
// then the execution happens without the nessecity of the `Context.Next` method,
@@ -390,22 +391,22 @@ func (api *APIBuilder) RegisterDependency(dependencies ...interface{}) {
// The client's request body and server's response body Go types.
// Could be any data structure.
//
-// type (
-// request struct {
-// Firstname string `json:"firstname"`
-// Lastname string `json:"lastname"`
-// }
+// type (
+// request struct {
+// Firstname string `json:"firstname"`
+// Lastname string `json:"lastname"`
+// }
//
-// response struct {
-// ID uint64 `json:"id"`
-// Message string `json:"message"`
-// }
-// )
+// response struct {
+// ID uint64 `json:"id"`
+// Message string `json:"message"`
+// }
+// )
//
// Register the route hander.
//
-// HTTP VERB ROUTE PATH ROUTE HANDLER
-// app.HandleFunc("PUT", "/users/{id:uint64}", updateUser)
+// HTTP VERB ROUTE PATH ROUTE HANDLER
+// app.HandleFunc("PUT", "/users/{id:uint64}", updateUser)
//
// Code the route handler function.
// Path parameters and request body are binded
@@ -413,26 +414,26 @@ func (api *APIBuilder) RegisterDependency(dependencies ...interface{}) {
// The "id" uint64 binds to "{id:uint64}" route path parameter and
// the "input" binds to client request data such as JSON.
//
-// func updateUser(id uint64, input request) response {
-// // [custom logic...]
+// func updateUser(id uint64, input request) response {
+// // [custom logic...]
//
-// return response{
-// ID:id,
-// Message: "User updated successfully",
-// }
-// }
+// return response{
+// ID:id,
+// Message: "User updated successfully",
+// }
+// }
//
// Simulate a client request which sends data
// to the server and prints out the response.
//
-// curl --request PUT -d '{"firstname":"John","lastname":"Doe"}' \
-// -H "Content-Type: application/json" \
-// http://localhost:8080/users/42
+// curl --request PUT -d '{"firstname":"John","lastname":"Doe"}' \
+// -H "Content-Type: application/json" \
+// http://localhost:8080/users/42
//
-// {
-// "id": 42,
-// "message": "User updated successfully"
-// }
+// {
+// "id": 42,
+// "message": "User updated successfully"
+// }
//
// See the `ConfigureContainer` for more features regrading
// the dependency injection, mvc and function handlers.
@@ -474,11 +475,12 @@ func (api *APIBuilder) AllowMethods(methods ...string) Party {
// For example, if for some reason the desired result is the (done or all) handlers to be executed no matter what
// even if no `ctx.Next()` is called in the previous handlers, including the begin(`Use`),
// the main(`Handle`) and the done(`Done`) handlers themselves, then:
-// Party#SetExecutionRules(iris.ExecutionRules {
-// Begin: iris.ExecutionOptions{Force: true},
-// Main: iris.ExecutionOptions{Force: true},
-// Done: iris.ExecutionOptions{Force: true},
-// })
+//
+// Party#SetExecutionRules(iris.ExecutionRules {
+// Begin: iris.ExecutionOptions{Force: true},
+// Main: iris.ExecutionOptions{Force: true},
+// Done: iris.ExecutionOptions{Force: true},
+// })
//
// Note that if : true then the only remained way to "break" the handler chain is by `ctx.StopExecution()` now that `ctx.Next()` does not matter.
//
@@ -567,11 +569,14 @@ func (api *APIBuilder) handle(errorCode int, method string, relativePath string,
// otherwise use `Party` which can handle many paths with different handlers and middlewares.
//
// Usage:
-// app.HandleMany("GET", "/user /user/{id:uint64} /user/me", genericUserHandler)
+//
+// app.HandleMany("GET", "/user /user/{id:uint64} /user/me", genericUserHandler)
+//
// At the other side, with `Handle` we've had to write:
-// app.Handle("GET", "/user", userHandler)
-// app.Handle("GET", "/user/{id:uint64}", userByIDHandler)
-// app.Handle("GET", "/user/me", userMeHandler)
+//
+// app.Handle("GET", "/user", userHandler)
+// app.Handle("GET", "/user/{id:uint64}", userByIDHandler)
+// app.Handle("GET", "/user/me", userMeHandler)
//
// app.HandleMany("GET POST", "/path", handler)
func (api *APIBuilder) HandleMany(methodOrMulti string, relativePathorMulti string, handlers ...context.Handler) (routes []*Route) {
@@ -606,7 +611,7 @@ func (api *APIBuilder) HandleMany(methodOrMulti string, relativePathorMulti stri
//
// Alternatively, to get just the handler for that look the FileServer function instead.
//
-// api.HandleDir("/static", iris.Dir("./assets"), iris.DirOptions{IndexName: "/index.html", Compress: true})
+// api.HandleDir("/static", iris.Dir("./assets"), iris.DirOptions{IndexName: "/index.html", Compress: true})
//
// Returns all the registered routes, including GET index and path patterm and HEAD.
//
@@ -904,12 +909,13 @@ func (api *APIBuilder) Party(relativePath string, handlers ...context.Handler) P
// Note: `iris#Party` and `core/router#Party` describes the exactly same interface.
//
// Usage:
-// app.PartyFunc("/users", func(u iris.Party){
-// u.Use(authMiddleware, logMiddleware)
-// u.Get("/", getAllUsers)
-// u.Post("/", createOrUpdateUser)
-// u.Delete("/", deleteUser)
-// })
+//
+// app.PartyFunc("/users", func(u iris.Party){
+// u.Use(authMiddleware, logMiddleware)
+// u.Get("/", getAllUsers)
+// u.Post("/", createOrUpdateUser)
+// u.Delete("/", deleteUser)
+// })
//
// Look `Party` for more.
func (api *APIBuilder) PartyFunc(relativePath string, partyBuilderFunc func(p Party)) Party {
@@ -949,16 +955,21 @@ type (
// Useful when the api's dependencies amount are too much to pass on a function.
//
// Usage:
-// app.PartyConfigure("/users", &api.UsersAPI{UserRepository: ..., ...})
+//
+// app.PartyConfigure("/users", &api.UsersAPI{UserRepository: ..., ...})
+//
// Where UsersAPI looks like:
-// type UsersAPI struct { [...] }
-// func(api *UsersAPI) Configure(router iris.Party) {
-// router.Get("/{id:uuid}", api.getUser)
-// [...]
-// }
+//
+// type UsersAPI struct { [...] }
+// func(api *UsersAPI) Configure(router iris.Party) {
+// router.Get("/{id:uuid}", api.getUser)
+// [...]
+// }
+//
// Usage with (static) dependencies:
-// app.RegisterDependency(userRepo, ...)
-// app.PartyConfigure("/users", new(api.UsersAPI))
+//
+// app.RegisterDependency(userRepo, ...)
+// app.PartyConfigure("/users", new(api.UsersAPI))
func (api *APIBuilder) PartyConfigure(relativePath string, partyReg ...PartyConfigurator) Party {
var child Party
@@ -1626,15 +1637,16 @@ func (api *APIBuilder) RegisterView(viewEngine context.ViewEngine) {
// FallbackView registers one or more fallback views for a template or a template layout.
// Usage:
-// FallbackView(iris.FallbackView("fallback.html"))
-// FallbackView(iris.FallbackViewLayout("layouts/fallback.html"))
-// OR
-// FallbackView(iris.FallbackViewFunc(ctx iris.Context, err iris.ErrViewNotExist) error {
-// err.Name is the previous template name.
-// err.IsLayout reports whether the failure came from the layout template.
-// err.Data is the template data provided to the previous View call.
-// [...custom logic e.g. ctx.View("fallback", err.Data)]
-// })
+//
+// FallbackView(iris.FallbackView("fallback.html"))
+// FallbackView(iris.FallbackViewLayout("layouts/fallback.html"))
+// OR
+// FallbackView(iris.FallbackViewFunc(ctx iris.Context, err iris.ErrViewNotExist) error {
+// err.Name is the previous template name.
+// err.IsLayout reports whether the failure came from the layout template.
+// err.Data is the template data provided to the previous View call.
+// [...custom logic e.g. ctx.View("fallback", err.Data)]
+// })
func (api *APIBuilder) FallbackView(provider context.FallbackViewProvider) {
handler := func(ctx *context.Context) {
ctx.FallbackView(provider)
@@ -1653,9 +1665,10 @@ func (api *APIBuilder) FallbackView(provider context.FallbackViewProvider) {
// app := iris.New()
// app.RegisterView(iris.$VIEW_ENGINE("./views", ".$extension"))
// my := app.Party("/my").Layout("layouts/mylayout.html")
-// my.Get("/", func(ctx iris.Context) {
-// ctx.View("page1.html")
-// })
+//
+// my.Get("/", func(ctx iris.Context) {
+// ctx.View("page1.html")
+// })
//
// Examples: https://github.com/kataras/iris/tree/master/_examples/view
func (api *APIBuilder) Layout(tmplLayoutFile string) Party {
diff --git a/core/router/api_builder_benchmark_test.go b/core/router/api_builder_benchmark_test.go
index b88b587d..d9b8015a 100644
--- a/core/router/api_builder_benchmark_test.go
+++ b/core/router/api_builder_benchmark_test.go
@@ -12,7 +12,6 @@ import (
"github.com/kataras/golog"
)
-//
// randStringBytesMaskImprSrc helps us to generate random paths for the test,
// the below piece of code is external, as an answer to a stackoverflow question.
//
diff --git a/core/router/fs.go b/core/router/fs.go
index d6315cbb..b83539d7 100644
--- a/core/router/fs.go
+++ b/core/router/fs.go
@@ -7,7 +7,6 @@ import (
"html"
"html/template"
"io"
- "io/ioutil"
"net/http"
"net/url"
"os"
@@ -1041,7 +1040,7 @@ func cacheFiles(ctx stdContext.Context, fs http.FileSystem, names []string, comp
fi := newFileInfo(path.Base(name), inf.Mode(), inf.ModTime())
- contents, err := ioutil.ReadAll(f)
+ contents, err := io.ReadAll(f)
f.Close()
if err != nil {
return err
diff --git a/core/router/handler_execution_rules.go b/core/router/handler_execution_rules.go
index fd94feb3..6c77af4f 100644
--- a/core/router/handler_execution_rules.go
+++ b/core/router/handler_execution_rules.go
@@ -6,9 +6,10 @@ import (
// ExecutionRules gives control to the execution of the route handlers outside of the handlers themselves.
// Usage:
-// Party#SetExecutionRules(ExecutionRules {
-// Done: ExecutionOptions{Force: true},
-// })
+//
+// Party#SetExecutionRules(ExecutionRules {
+// Done: ExecutionOptions{Force: true},
+// })
//
// See `Party#SetExecutionRules` for more.
type ExecutionRules struct {
diff --git a/core/router/mime.go b/core/router/mime.go
index 05e6db4c..b4c21bcd 100644
--- a/core/router/mime.go
+++ b/core/router/mime.go
@@ -560,9 +560,9 @@ func init() {
// system's mime.types file(s) if available under one or more of these
// names:
//
-// /etc/mime.types
-// /etc/apache2/mime.types
-// /etc/apache/mime.types
+// /etc/mime.types
+// /etc/apache2/mime.types
+// /etc/apache/mime.types
//
// On Windows, MIME types are extracted from the registry.
//
diff --git a/core/router/route.go b/core/router/route.go
index f35e2a98..e55a4419 100644
--- a/core/router/route.go
+++ b/core/router/route.go
@@ -491,8 +491,9 @@ func (r *Route) GetTitle() string {
// Should be called after `Build` state.
//
// It prints the @method: @path (@description) (@route_rel_location)
-// * @handler_name (@handler_rel_location)
-// * @second_handler ...
+// - @handler_name (@handler_rel_location)
+// - @second_handler ...
+//
// If route and handler line:number locations are equal then the second is ignored.
func (r *Route) Trace(w io.Writer, stoppedIndex int) {
title := r.GetTitle()
diff --git a/doc.go b/doc.go
index 7f97f681..2e430d42 100644
--- a/doc.go
+++ b/doc.go
@@ -34,34 +34,33 @@ Easy to learn for new gophers and advanced features for experienced, it goes as
Source code and other details for the project are available at GitHub:
- https://github.com/kataras/iris
+ https://github.com/kataras/iris
-Current Version
+# Current Version
-12.2.0-beta3
+12.2.0-beta4
-Installation
+# Installation
The only requirement is the Go Programming Language, at least version 1.18.
- $ go get github.com/kataras/iris/v12@master
+ $ go get github.com/kataras/iris/v12@master
Wiki:
- https://github.com/kataras/iris/wiki
+ https://github.com/kataras/iris/wiki
Examples:
- https://github.com/kataras/iris/tree/master/_examples
+ https://github.com/kataras/iris/tree/master/_examples
Middleware:
- https://github.com/kataras/iris/tree/master/middleware
- https://github.com/iris-contrib/middleware
+ https://github.com/kataras/iris/tree/master/middleware
+ https://github.com/iris-contrib/middleware
Home Page:
- https://iris-go.com
-
+ https://iris-go.com
*/
package iris
diff --git a/go.mod b/go.mod
index 389e38a7..3951d662 100644
--- a/go.mod
+++ b/go.mod
@@ -15,7 +15,6 @@ require (
github.com/fatih/structs v1.1.0
github.com/flosch/pongo2/v4 v4.0.2
github.com/go-redis/redis/v8 v8.11.5
- github.com/goccy/go-json v0.9.8-0.20220506185958-23bd66f4c0d5
github.com/golang/snappy v0.0.4
github.com/google/uuid v1.3.0
github.com/gorilla/securecookie v1.1.1
diff --git a/go.sum b/go.sum
index 895f1595..848f3f50 100644
--- a/go.sum
+++ b/go.sum
@@ -62,8 +62,6 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
-github.com/goccy/go-json v0.9.8-0.20220506185958-23bd66f4c0d5 h1:aeyOtISssR4sP36FAC9LV96PQqxzcbhz54EWv9U+ZGc=
-github.com/goccy/go-json v0.9.8-0.20220506185958-23bd66f4c0d5/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
diff --git a/hero/container.go b/hero/container.go
index ee3e392c..437366a1 100644
--- a/hero/container.go
+++ b/hero/container.go
@@ -326,23 +326,28 @@ func Handler(fn interface{}) context.Handler {
// It returns a standard `iris/context.Handler` which can be used anywhere in an Iris Application,
// as middleware or as simple route handler or subdomain's handler.
//
-// func(...) iris.Handler
+// func(...) iris.Handler
+//
// - if are all static dependencies then
// there is no reflection involved at serve-time.
//
-// func(pathParameter string, ...)
+// func(pathParameter string, ...)
+//
// - one or more path parameters (e.g. :uid, :string, :int, :path, :uint64)
// are automatically binded to the first input Go standard types (string, int, uint64 and e.t.c.)
//
-// func() error
+// func() error
+//
// - if a function returns an error then this error's text is sent to the client automatically.
//
-// func()
+// func()
+//
// - The result of the function is a dependency too.
// If is a request-scope dependency (dynamic) then
// this function will be called at every request.
//
-// func()
+// func()
+//
// - If is static dependency (e.g. a database or a service) then its result
// can be used as a static dependency to the next dependencies or to the controller/function itself.
func (c *Container) Handler(fn interface{}) context.Handler {
diff --git a/hero/func_result.go b/hero/func_result.go
index ce925773..949d140a 100644
--- a/hero/func_result.go
+++ b/hero/func_result.go
@@ -27,11 +27,9 @@ func defaultResultHandler(ctx *context.Context, v interface{}) error {
switch context.TrimHeaderValue(ctx.GetContentType()) {
case context.ContentXMLHeaderValue, context.ContentXMLUnreadableHeaderValue:
- _, err := ctx.XML(v)
- return err
+ return ctx.XML(v)
case context.ContentYAMLHeaderValue:
- _, err := ctx.YAML(v)
- return err
+ return ctx.YAML(v)
case context.ContentProtobufHeaderValue:
msg, ok := v.(proto.Message)
if !ok {
@@ -45,8 +43,7 @@ func defaultResultHandler(ctx *context.Context, v interface{}) error {
return err
default:
// otherwise default to JSON.
- _, err := ctx.JSON(v)
- return err
+ return ctx.JSON(v)
}
}
diff --git a/hero/func_result_test.go b/hero/func_result_test.go
index dcb76dc9..09c7592c 100644
--- a/hero/func_result_test.go
+++ b/hero/func_result_test.go
@@ -92,7 +92,7 @@ func (e err) Dispatch(ctx iris.Context) {
// write the status code based on the err's StatusCode.
ctx.StatusCode(e.Status)
// send to the client the whole object as json
- _, _ = ctx.JSON(e)
+ _ = ctx.JSON(e)
}
func GetCustomErrorAsDispatcher() err {
diff --git a/httptest/httptest.go b/httptest/httptest.go
index f193e85e..3ff40ca4 100644
--- a/httptest/httptest.go
+++ b/httptest/httptest.go
@@ -98,9 +98,12 @@ func DefaultConfiguration() *Configuration {
// New Prepares and returns a new test framework based on the "app".
// Usage:
-// httptest.New(t, app)
+//
+// httptest.New(t, app)
+//
// With options:
-// httptest.New(t, app, httptest.URL(...), httptest.Debug(true), httptest.LogLevel("debug"), httptest.Strict(true))
+//
+// httptest.New(t, app, httptest.URL(...), httptest.Debug(true), httptest.LogLevel("debug"), httptest.Strict(true))
//
// Example at: https://github.com/kataras/iris/tree/master/_examples/testing/httptest.
func New(t *testing.T, app *iris.Application, setters ...OptionSetter) *httpexpect.Expect {
diff --git a/i18n/internal/locale.go b/i18n/internal/locale.go
index 4d45ceeb..4ce5e567 100644
--- a/i18n/internal/locale.go
+++ b/i18n/internal/locale.go
@@ -152,7 +152,7 @@ func (loc *Locale) Tag() *language.Tag {
}
// Language should return the exact languagecode of this `Locale`
-//that the user provided on `New` function.
+// that the user provided on `New` function.
//
// Same as `Tag().String()` but it's static.
func (loc *Locale) Language() string {
diff --git a/i18n/loader.go b/i18n/loader.go
index 662e2179..511b57db 100644
--- a/i18n/loader.go
+++ b/i18n/loader.go
@@ -3,7 +3,7 @@ package i18n
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "os"
"path/filepath"
"strings"
@@ -33,7 +33,7 @@ func Glob(globPattern string, options LoaderConfig) Loader {
panic(err)
}
- return load(assetNames, ioutil.ReadFile, options)
+ return load(assetNames, os.ReadFile, options)
}
// Assets accepts a function that returns a list of filenames (physical or virtual),
diff --git a/iris.go b/iris.go
index 977fe02a..90245dfe 100644
--- a/iris.go
+++ b/iris.go
@@ -299,6 +299,7 @@ func (app *Application) ConfigurationReadOnly() context.ConfigurationReadOnly {
// Adding one or more outputs : app.Logger().AddOutput(io.Writer...)
//
// Adding custom levels requires import of the `github.com/kataras/golog` package:
+//
// First we create our level to a golog.Level
// in order to be used in the Log functions.
// var SuccessLevel golog.Level = 6
@@ -309,6 +310,7 @@ func (app *Application) ConfigurationReadOnly() context.ConfigurationReadOnly {
// // ColorfulText (Green Color[SUCC])
// ColorfulText: "\x1b[32m[SUCC]\x1b[0m",
// }
+//
// Usage:
// app.Logger().SetLevel("success")
// app.Logger().Logf(SuccessLevel, "a custom leveled log message")
@@ -437,12 +439,12 @@ func (app *Application) GetContextPool() *context.Pool {
//
// ExampleCode:
//
-// type contextErrorHandler struct{}
-// func (e *contextErrorHandler) HandleContextError(ctx iris.Context, err error) {
-// errors.InvalidArgument.Err(ctx, err)
-// }
-// ...
-// app.SetContextErrorHandler(new(contextErrorHandler))
+// type contextErrorHandler struct{}
+// func (e *contextErrorHandler) HandleContextError(ctx iris.Context, err error) {
+// errors.InvalidArgument.Err(ctx, err)
+// }
+// ...
+// app.SetContextErrorHandler(new(contextErrorHandler))
func (app *Application) SetContextErrorHandler(errHandler context.ErrorHandler) *Application {
app.contextErrorHandler = errHandler
return app
@@ -653,9 +655,9 @@ func (app *Application) Shutdown(ctx stdContext.Context) error {
//
// import "github.com/kataras/iris/v12/core/errgroup"
//
-// errgroup.Walk(app.Build(), func(typ interface{}, err error) {
-// app.Logger().Errorf("%s: %s", typ, err)
-// })
+// errgroup.Walk(app.Build(), func(typ interface{}, err error) {
+// app.Logger().Errorf("%s: %s", typ, err)
+// })
func (app *Application) Build() error {
if app.builded {
return nil
diff --git a/iris_guide.go b/iris_guide.go
index cccce2df..d6d43d8c 100644
--- a/iris_guide.go
+++ b/iris_guide.go
@@ -237,7 +237,7 @@ type (
Step3 interface {
// Health enables the /health route.
// If "env" and "developer" are given, these fields will be populated to the client
- // through headers and environemnt on health route.
+ // through headers and environment on health route.
Health(b bool, env, developer string) Step4
}
diff --git a/macro/handler/handler.go b/macro/handler/handler.go
index 1c5fe144..948a8c0b 100644
--- a/macro/handler/handler.go
+++ b/macro/handler/handler.go
@@ -18,7 +18,9 @@ import (
// Note that the builtin macros return error too, but they're handled
// by the `else` literal (error code). To change this behavior
// and send a custom error response you have to register it:
-// app.Macros().Get("uuid").HandleError(func(ctx iris.Context, paramIndex int, err error)).
+//
+// app.Macros().Get("uuid").HandleError(func(ctx iris.Context, paramIndex int, err error)).
+//
// You can also set custom macros by `app.Macros().Register`.
//
// See macro.HandleError to set it.
diff --git a/middleware/accesslog/accesslog_test.go b/middleware/accesslog/accesslog_test.go
index 315285d2..87601315 100644
--- a/middleware/accesslog/accesslog_test.go
+++ b/middleware/accesslog/accesslog_test.go
@@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"net/http"
"net/http/httptest"
"strings"
@@ -324,7 +323,7 @@ func BenchmarkAccessLogAfterPrint(b *testing.B) {
}
func benchmarkAccessLogAfter(b *testing.B, withLogStruct, async bool) {
- ac := New(ioutil.Discard)
+ ac := New(io.Discard)
ac.Clock = TClock(time.Time{})
ac.BytesReceived = false
ac.BytesReceivedBody = false
diff --git a/middleware/accesslog/log.go b/middleware/accesslog/log.go
index 517df92c..ca88aa9f 100644
--- a/middleware/accesslog/log.go
+++ b/middleware/accesslog/log.go
@@ -11,6 +11,7 @@ import (
)
// Log represents the log data specifically for the accesslog middleware.
+//
//easyjson:json
type Log struct {
// The AccessLog instance this Log was created of.
diff --git a/middleware/basicauth/basicauth.go b/middleware/basicauth/basicauth.go
index 97fbb85e..83b783ba 100644
--- a/middleware/basicauth/basicauth.go
+++ b/middleware/basicauth/basicauth.go
@@ -52,8 +52,9 @@ type ErrorHandler func(ctx *context.Context, err error)
// The only required value is the Allow field.
//
// Usage:
-// opts := Options { ... }
-// auth := New(opts)
+//
+// opts := Options { ... }
+// auth := New(opts)
type Options struct {
// Realm directive, read http://tools.ietf.org/html/rfc2617#section-1.2 for details.
// E.g. "Authorization Required".
@@ -171,17 +172,18 @@ type BasicAuth struct {
// The result should be used to wrap an existing handler or the HTTP application's root router.
//
// Example Code:
-// opts := basicauth.Options{
-// Realm: basicauth.DefaultRealm,
-// ErrorHandler: basicauth.DefaultErrorHandler,
-// MaxAge: 2 * time.Hour,
-// GC: basicauth.GC{
-// Every: 3 * time.Hour,
-// },
-// Allow: basicauth.AllowUsers(users),
-// }
-// auth := basicauth.New(opts)
-// app.Use(auth)
+//
+// opts := basicauth.Options{
+// Realm: basicauth.DefaultRealm,
+// ErrorHandler: basicauth.DefaultErrorHandler,
+// MaxAge: 2 * time.Hour,
+// GC: basicauth.GC{
+// Every: 3 * time.Hour,
+// },
+// Allow: basicauth.AllowUsers(users),
+// }
+// auth := basicauth.New(opts)
+// app.Use(auth)
//
// Access the user in the route handler with: ctx.User().GetRaw().(*myCustomType).
//
@@ -238,16 +240,18 @@ func New(opts Options) context.Handler {
// are required as they are compared against the user input
// when access to protected resource is requested.
// A user list can defined with one of the following values:
-// map[string]string form of: {username:password, ...}
-// map[string]interface{} form of: {"username": {"password": "...", "other_field": ...}, ...}
-// []T which T completes the User interface, where T is a struct value
-// []T which T contains at least Username and Password fields.
+//
+// map[string]string form of: {username:password, ...}
+// map[string]interface{} form of: {"username": {"password": "...", "other_field": ...}, ...}
+// []T which T completes the User interface, where T is a struct value
+// []T which T contains at least Username and Password fields.
//
// Usage:
-// auth := Default(map[string]string{
-// "admin": "admin",
-// "john": "p@ss",
-// })
+//
+// auth := Default(map[string]string{
+// "admin": "admin",
+// "john": "p@ss",
+// })
func Default(users interface{}, userOpts ...UserAuthOption) context.Handler {
opts := Options{
Realm: DefaultRealm,
@@ -260,7 +264,8 @@ func Default(users interface{}, userOpts ...UserAuthOption) context.Handler {
// a filename to load the users from.
//
// Usage:
-// auth := Load("users.yml")
+//
+// auth := Load("users.yml")
func Load(jsonOrYamlFilename string, userOpts ...UserAuthOption) context.Handler {
opts := Options{
Realm: DefaultRealm,
diff --git a/middleware/basicauth/user.go b/middleware/basicauth/user.go
index 4f66c1dc..06140e2e 100644
--- a/middleware/basicauth/user.go
+++ b/middleware/basicauth/user.go
@@ -3,7 +3,7 @@ package basicauth
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "os"
"reflect"
"strings"
@@ -16,8 +16,8 @@ import (
// ReadFile can be used to customize the way the
// AllowUsersFile function is loading the filename from.
// Example of usage: embedded users.yml file.
-// Defaults to the `ioutil.ReadFile` which reads the file from the physical disk.
-var ReadFile = ioutil.ReadFile
+// Defaults to the `os.ReadFile` which reads the file from the physical disk.
+var ReadFile = os.ReadFile
// User is a partial part of the iris.User interface.
// It's used to declare a static slice of registered User for authentication.
@@ -48,10 +48,11 @@ type UserAuthOption func(*UserAuthOptions)
// See https://www.usenix.org/legacy/event/usenix99/provos/provos.pdf.
//
// Usage:
-// Default(..., BCRYPT) OR
-// Load(..., BCRYPT) OR
-// Options.Allow = AllowUsers(..., BCRYPT) OR
-// OPtions.Allow = AllowUsersFile(..., BCRYPT)
+//
+// Default(..., BCRYPT) OR
+// Load(..., BCRYPT) OR
+// Options.Allow = AllowUsers(..., BCRYPT) OR
+// OPtions.Allow = AllowUsersFile(..., BCRYPT)
func BCRYPT(opts *UserAuthOptions) {
opts.ComparePassword = func(stored, userPassword string) bool {
err := bcrypt.CompareHashAndPassword([]byte(stored), []byte(userPassword))
@@ -75,10 +76,11 @@ func toUserAuthOptions(opts []UserAuthOption) (options UserAuthOptions) {
// AllowUsers is an AuthFunc which authenticates user input based on a (static) user list.
// The "users" input parameter can be one of the following forms:
-// map[string]string e.g. {username: password, username: password...}.
-// []map[string]interface{} e.g. []{"username": "...", "password": "...", "other_field": ...}, ...}.
-// []T which T completes the User interface.
-// []T which T contains at least Username and Password fields.
+//
+// map[string]string e.g. {username: password, username: password...}.
+// []map[string]interface{} e.g. []{"username": "...", "password": "...", "other_field": ...}, ...}.
+// []T which T completes the User interface.
+// []T which T contains at least Username and Password fields.
//
// Usage:
// New(Options{Allow: AllowUsers(..., [BCRYPT])})
@@ -155,15 +157,17 @@ func userMap(usernamePassword map[string]string, opts ...UserAuthOption) AuthFun
// loaded from a file on initialization.
//
// Example Code:
-// New(Options{Allow: AllowUsersFile("users.yml", BCRYPT)})
+//
+// New(Options{Allow: AllowUsersFile("users.yml", BCRYPT)})
+//
// The users.yml file looks like the following:
-// - username: kataras
-// password: kataras_pass
-// age: 27
-// role: admin
-// - username: makis
-// password: makis_password
-// ...
+// - username: kataras
+// password: kataras_pass
+// age: 27
+// role: admin
+// - username: makis
+// password: makis_password
+// ...
func AllowUsersFile(jsonOrYamlFilename string, opts ...UserAuthOption) AuthFunc {
var (
usernamePassword map[string]string
diff --git a/middleware/basicauth/user_test.go b/middleware/basicauth/user_test.go
index 3ce80a12..b80919bc 100644
--- a/middleware/basicauth/user_test.go
+++ b/middleware/basicauth/user_test.go
@@ -2,7 +2,6 @@ package basicauth
import (
"errors"
- "io/ioutil"
"os"
"reflect"
"testing"
@@ -164,7 +163,7 @@ func TestAllowUsers(t *testing.T) {
// Test YAML user loading with b-encrypted passwords.
func TestAllowUsersFile(t *testing.T) {
- f, err := ioutil.TempFile("", "*users.yml")
+ f, err := os.CreateTemp("", "*users.yml")
if err != nil {
t.Fatal(err)
}
diff --git a/middleware/cors/cors.go b/middleware/cors/cors.go
index 3acb1a82..e6b31ca5 100644
--- a/middleware/cors/cors.go
+++ b/middleware/cors/cors.go
@@ -85,17 +85,18 @@ type (
// please refer to: https://github.com/iris-contrib/middleware repository instead.
//
// Example Code:
-// import "github.com/kataras/iris/v12/middleware/cors"
-// import "github.com/kataras/iris/v12/x/errors"
//
-// app.UseRouter(cors.New().
-// HandleErrorFunc(func(ctx iris.Context, err error) {
-// errors.FailedPrecondition.Err(ctx, err)
-// }).
-// ExtractOriginFunc(cors.StrictOriginExtractor).
-// ReferrerPolicy(cors.NoReferrerWhenDowngrade).
-// AllowOrigin("domain1.com,domain2.com,domain3.com").
-// Handler())
+// import "github.com/kataras/iris/v12/middleware/cors"
+// import "github.com/kataras/iris/v12/x/errors"
+//
+// app.UseRouter(cors.New().
+// HandleErrorFunc(func(ctx iris.Context, err error) {
+// errors.FailedPrecondition.Err(ctx, err)
+// }).
+// ExtractOriginFunc(cors.StrictOriginExtractor).
+// ReferrerPolicy(cors.NoReferrerWhenDowngrade).
+// AllowOrigin("domain1.com,domain2.com,domain3.com").
+// Handler())
func New() *CORS {
return &CORS{
extractOriginFunc: DefaultOriginExtractor,
diff --git a/middleware/grpc/grpc.go b/middleware/grpc/grpc.go
index b073fdf1..8da66ac0 100644
--- a/middleware/grpc/grpc.go
+++ b/middleware/grpc/grpc.go
@@ -13,11 +13,12 @@ import (
// The Iris server SHOULD run under HTTP/2 and clients too.
//
// Usage:
-// import grpcWrapper "github.com/kataras/iris/v12/middleware/grpc"
-// [...]
-// app := iris.New()
-// grpcServer := grpc.NewServer()
-// app.WrapRouter(grpcWrapper.New(grpcServer))
+//
+// import grpcWrapper "github.com/kataras/iris/v12/middleware/grpc"
+// [...]
+// app := iris.New()
+// grpcServer := grpc.NewServer()
+// app.WrapRouter(grpcWrapper.New(grpcServer))
func New(grpcServer http.Handler) router.WrapperFunc {
return func(w http.ResponseWriter, r *http.Request, mux http.HandlerFunc) {
if r.ProtoMajor == 2 && strings.HasPrefix(r.Header.Get("Content-Type"), "application/grpc") {
diff --git a/middleware/hcaptcha/hcaptcha.go b/middleware/hcaptcha/hcaptcha.go
index e6cb41a3..54294df6 100644
--- a/middleware/hcaptcha/hcaptcha.go
+++ b/middleware/hcaptcha/hcaptcha.go
@@ -3,7 +3,7 @@ package hcaptcha
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/http"
"net/url"
@@ -70,7 +70,9 @@ func New(secret string, options ...Option) context.Handler {
// Handler is the HTTP route middleware featured hcaptcha validation.
// It calls the `SiteVerify` method and fires the "next" when user completed the hcaptcha successfully,
-// otherwise it calls the Client's `FailureHandler`.
+//
+// otherwise it calls the Client's `FailureHandler`.
+//
// The hcaptcha's `Response` (which contains any `ErrorCodes`)
// is saved on the Request's Context (see `GetResponseFromContext`).
func (c *Client) Handler(ctx *context.Context) {
@@ -113,7 +115,7 @@ func SiteVerify(ctx *context.Context, secret string) (response Response) {
return
}
- body, err := ioutil.ReadAll(resp.Body)
+ body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
response.ErrorCodes = append(response.ErrorCodes, err.Error())
diff --git a/middleware/jwt/blocklist/redis/blocklist.go b/middleware/jwt/blocklist/redis/blocklist.go
index 74b63cd8..af389373 100644
--- a/middleware/jwt/blocklist/redis/blocklist.go
+++ b/middleware/jwt/blocklist/redis/blocklist.go
@@ -55,14 +55,14 @@ var _ jwt.Blocklist = (*Blocklist)(nil)
//
// Usage:
//
-// blocklist := NewBlocklist()
-// blocklist.ClientOptions.Addr = ...
-// err := blocklist.Connect()
+// blocklist := NewBlocklist()
+// blocklist.ClientOptions.Addr = ...
+// err := blocklist.Connect()
//
// And register it:
//
-// verifier := jwt.NewVerifier(...)
-// verifier.Blocklist = blocklist
+// verifier := jwt.NewVerifier(...)
+// verifier.Blocklist = blocklist
func NewBlocklist() *Blocklist {
return &Blocklist{
GetKey: defaultGetKey,
diff --git a/middleware/jwt/signer.go b/middleware/jwt/signer.go
index 583f8c00..3eca028a 100644
--- a/middleware/jwt/signer.go
+++ b/middleware/jwt/signer.go
@@ -31,8 +31,8 @@ type Signer struct {
//
// Usage:
//
-// signer := NewSigner(HS256, secret, 15*time.Minute)
-// token, err := signer.Sign(userClaims{Username: "kataras"})
+// signer := NewSigner(HS256, secret, 15*time.Minute)
+// token, err := signer.Sign(userClaims{Username: "kataras"})
func NewSigner(signatureAlg Alg, signatureKey interface{}, maxAge time.Duration) *Signer {
if signatureAlg == HS256 {
// A tiny helper if the end-developer uses string instead of []byte for hmac keys.
diff --git a/middleware/jwt/verifier.go b/middleware/jwt/verifier.go
index b5fd75c0..dacfcba5 100644
--- a/middleware/jwt/verifier.go
+++ b/middleware/jwt/verifier.go
@@ -61,24 +61,31 @@ type Verifier struct {
//
// Usage:
//
-// verifier := NewVerifier(HS256, secret)
-// OR
-// verifier := NewVerifier(HS256, secret, Expected{Issuer: "my-app"})
+// verifier := NewVerifier(HS256, secret)
//
-// claimsGetter := func() interface{} { return new(userClaims) }
-// middleware := verifier.Verify(claimsGetter)
// OR
-// middleware := verifier.Verify(claimsGetter, Expected{Issuer: "my-app"})
+//
+// verifier := NewVerifier(HS256, secret, Expected{Issuer: "my-app"})
+//
+// claimsGetter := func() interface{} { return new(userClaims) }
+// middleware := verifier.Verify(claimsGetter)
+//
+// OR
+//
+// middleware := verifier.Verify(claimsGetter, Expected{Issuer: "my-app"})
//
// Register the middleware, e.g.
-// app.Use(middleware)
+//
+// app.Use(middleware)
//
// Get the claims:
-// claims := jwt.Get(ctx).(*userClaims)
-// username := claims.Username
+//
+// claims := jwt.Get(ctx).(*userClaims)
+// username := claims.Username
//
// Get the context user:
-// username, err := ctx.User().GetUsername()
+//
+// username, err := ctx.User().GetUsername()
func NewVerifier(signatureAlg Alg, signatureKey interface{}, validators ...TokenValidator) *Verifier {
if signatureAlg == HS256 {
// A tiny helper if the end-developer uses string instead of []byte for hmac keys.
diff --git a/middleware/methodoverride/methodoverride.go b/middleware/methodoverride/methodoverride.go
index 032b6833..68563f17 100644
--- a/middleware/methodoverride/methodoverride.go
+++ b/middleware/methodoverride/methodoverride.go
@@ -166,11 +166,12 @@ func Query(paramName string) Option {
// to determinate the method to override with.
//
// Use cases:
-// 1. When need to check only for headers and ignore other fields:
-// New(Only(Headers("X-Custom-Header")))
//
-// 2. When need to check only for (first) form field and (second) custom getter:
-// New(Only(FormField("fieldName"), Getter(...)))
+// 1. When need to check only for headers and ignore other fields:
+// New(Only(Headers("X-Custom-Header")))
+//
+// 2. When need to check only for (first) form field and (second) custom getter:
+// New(Only(FormField("fieldName"), Getter(...)))
func Only(o ...Option) Option {
return func(opts *options) {
opts.getters = opts.getters[0:0]
@@ -185,7 +186,6 @@ func Only(o ...Option) Option {
// that do not support certain HTTP operations such as DELETE or PUT for security reasons.
// This wrapper will accept a method, based on criteria, to override the POST method with.
//
-//
// Read more at:
// https://github.com/kataras/iris/issues/1325
func New(opt ...Option) router.WrapperFunc {
diff --git a/middleware/modrevision/modrevision.go b/middleware/modrevision/modrevision.go
index 198339c8..fc3d4655 100644
--- a/middleware/modrevision/modrevision.go
+++ b/middleware/modrevision/modrevision.go
@@ -34,12 +34,13 @@ type Options struct {
// for security reasons.
//
// Example Code:
-// app.Get("/health", modrevision.New(modrevision.Options{
-// ServerName: "Iris Server",
-// Env: "development",
-// Developer: "kataras",
-// TimeLocation: time.FixedZone("Greece/Athens", 10800),
-// }))
+//
+// app.Get("/health", modrevision.New(modrevision.Options{
+// ServerName: "Iris Server",
+// Env: "development",
+// Developer: "kataras",
+// TimeLocation: time.FixedZone("Greece/Athens", 7200),
+// }))
func New(opts Options) context.Handler {
buildTime, buildRevision := context.BuildTime, context.BuildRevision
if opts.UnixTime {
diff --git a/middleware/pprof/pprof.go b/middleware/pprof/pprof.go
index ec9b83ee..385c069e 100644
--- a/middleware/pprof/pprof.go
+++ b/middleware/pprof/pprof.go
@@ -41,7 +41,8 @@ var profileDescriptions = map[string]string{
// New returns a new pprof (profile, cmdline, symbol, goroutine, heap, threadcreate, debug/block) Middleware.
// Note: Route MUST have the last named parameter wildcard named '{action:path}'.
// Example:
-// app.HandleMany("GET", "/debug/pprof /debug/pprof/{action:path}", pprof.New())
+//
+// app.HandleMany("GET", "/debug/pprof /debug/pprof/{action:path}", pprof.New())
func New() context.Handler {
return func(ctx *context.Context) {
if action := ctx.Params().Get("action"); action != "" {
diff --git a/middleware/recaptcha/recaptcha.go b/middleware/recaptcha/recaptcha.go
index 291e0995..def402a5 100644
--- a/middleware/recaptcha/recaptcha.go
+++ b/middleware/recaptcha/recaptcha.go
@@ -3,7 +3,7 @@ package recaptcha
import (
"encoding/json"
"fmt"
- "io/ioutil"
+ "io"
"net/url"
"time"
@@ -50,7 +50,9 @@ func New(secret string) context.Handler {
}
// SiteVerify accepts context and the secret key(https://www.google.com/recaptcha)
-// and returns the google's recaptcha response, if `response.Success` is true
+//
+// and returns the google's recaptcha response, if `response.Success` is true
+//
// then validation passed.
//
// Use `New` for middleware use instead.
@@ -74,7 +76,7 @@ func SiteVerify(ctx *context.Context, secret string) (response Response) {
return
}
- body, err := ioutil.ReadAll(r.Body)
+ body, err := io.ReadAll(r.Body)
r.Body.Close()
if err != nil {
response.ErrorCodes = append(response.ErrorCodes, err.Error())
@@ -113,22 +115,24 @@ var recaptchaForm = `