mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Update to 8.2.2 | Google reCAPTCHA. Read HISTORY.md
Former-commit-id: dc8ee74fa33b2fbc41659c9097955afb152d5a6f
This commit is contained in:
parent
be8295eb50
commit
4da5cd47f1
20
HISTORY.md
20
HISTORY.md
|
@ -18,6 +18,26 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
|
|||
|
||||
**How to upgrade**: Open your command-line and execute this command: `go get -u github.com/kataras/iris`.
|
||||
|
||||
# Th, 10 August 2017 | v8.2.2
|
||||
|
||||
No API Changes.
|
||||
|
||||
- Implement [Google reCAPTCHA](middleware/recaptcha) middleware
|
||||
- Fix [kataras/golog](https://github.com/kataras/golog) prints with colors on windows server 2012 while it shouldn't because its command line tool does not support 256bit colors
|
||||
- Improve the updater by a custom self-updated back-end version checker, can be disabled by:
|
||||
|
||||
```go
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutVersionChecker)
|
||||
```
|
||||
Or
|
||||
```go
|
||||
app.Configure(iris.WithoutVersionChecker)
|
||||
```
|
||||
Or
|
||||
```go
|
||||
app.Configure(iris.WithConfiguration(iris.Configuration{DisableVersionChecker:true}))
|
||||
```
|
||||
|
||||
|
||||
# Tu, 08 August 2017 | v8.2.1
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ Iris is a fast, simple and efficient micro web framework for Go. It provides a b
|
|||
### 📑 Table of contents
|
||||
|
||||
* [Installation](#-installation)
|
||||
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#tu-08-august-2017--v821)
|
||||
* [Latest changes](https://github.com/kataras/iris/blob/master/HISTORY.md#th-10-august-2017--v822)
|
||||
* [Learn](#-learn)
|
||||
* [HTTP Listening](_examples/#http-listening)
|
||||
* [Configuration](_examples/#configuration)
|
||||
|
@ -319,7 +319,7 @@ Thank You for your trust!
|
|||
|
||||
### 📌 Version
|
||||
|
||||
Current: **8.2.1**
|
||||
Current: **8.2.2**
|
||||
|
||||
Each new release is pushed to the master. It stays there until the next version. When a next version is released then the previous version goes to its own branch with `gopkg.in` as its import path (and its own vendor folder), in order to keep it working "for-ever".
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
8.2.1:https://github.com/kataras/iris/blob/master/HISTORY.md#tu-08-august-2017--v821
|
||||
8.2.2:https://github.com/kataras/iris/blob/master/HISTORY.md#th-10-august-2017--v822
|
|
@ -136,9 +136,9 @@ var WithoutInterruptHandler = func(app *Application) {
|
|||
app.config.DisableInterruptHandler = true
|
||||
}
|
||||
|
||||
// WithoutVersionCheck will disable the version checker and updater.
|
||||
var WithoutVersionCheck = func(app *Application) {
|
||||
app.config.DisableVersionCheck = true
|
||||
// WithoutVersionChecker will disable the version checker and updater.
|
||||
var WithoutVersionChecker = func(app *Application) {
|
||||
app.config.DisableVersionChecker = true
|
||||
}
|
||||
|
||||
// WithoutPathCorrection disables the PathCorrection setting.
|
||||
|
@ -281,10 +281,10 @@ type Configuration struct {
|
|||
// Defaults to false.
|
||||
DisableInterruptHandler bool `yaml:"DisableInterruptHandler" toml:"DisableInterruptHandler"`
|
||||
|
||||
// DisableVersionCheck if true then process will be not be notified for any available updates.
|
||||
// DisableVersionChecker if true then process will be not be notified for any available updates.
|
||||
//
|
||||
// Defaults to false.
|
||||
DisableVersionCheck bool `yaml:"DisableVersionCheck" toml:"DisableVersionCheck"`
|
||||
DisableVersionChecker bool `yaml:"DisableVersionChecker" toml:"DisableVersionChecker"`
|
||||
|
||||
// DisablePathCorrection corrects and redirects the requested path to the registered path
|
||||
// for example, if /home/ path is requested but no handler for this Route found,
|
||||
|
@ -607,7 +607,7 @@ func DefaultConfiguration() Configuration {
|
|||
return Configuration{
|
||||
DisableStartupLog: false,
|
||||
DisableInterruptHandler: false,
|
||||
DisableVersionCheck: false,
|
||||
DisableVersionChecker: false,
|
||||
DisablePathCorrection: false,
|
||||
EnablePathEscape: false,
|
||||
FireMethodNotAllowed: false,
|
||||
|
|
33
core/netutil/client.go
Normal file
33
core/netutil/client.go
Normal file
|
@ -0,0 +1,33 @@
|
|||
package netutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/golog"
|
||||
)
|
||||
|
||||
// Client returns a new http.Client using
|
||||
// the "timeout" for open connection and read-write operations.
|
||||
func Client(timeout time.Duration) *http.Client {
|
||||
transport := http.Transport{
|
||||
Dial: func(network string, addr string) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
golog.Debugf("%v", err)
|
||||
return nil, err
|
||||
}
|
||||
if err = conn.SetDeadline(time.Now().Add(timeout)); err != nil {
|
||||
golog.Debugf("%v", err)
|
||||
}
|
||||
return conn, err
|
||||
},
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
return client
|
||||
}
|
2
doc.go
2
doc.go
|
@ -35,7 +35,7 @@ Source code and other details for the project are available at GitHub:
|
|||
|
||||
Current Version
|
||||
|
||||
8.2.1
|
||||
8.2.2
|
||||
|
||||
Installation
|
||||
|
||||
|
|
4
iris.go
4
iris.go
|
@ -32,7 +32,7 @@ import (
|
|||
|
||||
const (
|
||||
// Version is the current version number of the Iris Web Framework.
|
||||
Version = "8.2.1"
|
||||
Version = "8.2.2"
|
||||
)
|
||||
|
||||
// HTTP status codes as registered with IANA.
|
||||
|
@ -648,7 +648,7 @@ func (app *Application) Run(serve Runner, withOrWithout ...Configurator) error {
|
|||
app.Configure(withOrWithout...)
|
||||
app.logger.Debugf("Application: running using %d host(s)", len(app.Hosts)+1)
|
||||
|
||||
if !app.config.DisableVersionCheck && app.logger.Printer.IsTerminal {
|
||||
if !app.config.DisableVersionChecker && app.logger.Printer.IsTerminal {
|
||||
go CheckVersion()
|
||||
}
|
||||
|
||||
|
|
127
middleware/recaptcha/recaptcha.go
Normal file
127
middleware/recaptcha/recaptcha.go
Normal file
|
@ -0,0 +1,127 @@
|
|||
package recaptcha
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/netutil"
|
||||
)
|
||||
|
||||
const (
|
||||
responseFormValue = "g-recaptcha-response"
|
||||
apiURL = "https://www.google.com/recaptcha/api/siteverify"
|
||||
)
|
||||
|
||||
// Response is the google's recaptcha response as JSON.
|
||||
type Response struct {
|
||||
ChallengeTS time.Time `json:"challenge_ts"`
|
||||
Hostname string `json:"hostname"`
|
||||
ErrorCodes []string `json:"error-codes"`
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
var client = netutil.Client(time.Duration(10 * time.Second))
|
||||
|
||||
// New accepts the google's recaptcha secret key and returns
|
||||
// a middleware that verifies the request by sending a response to the google's API(V2-latest).
|
||||
// Secret key can be obtained by https://www.google.com/recaptcha.
|
||||
//
|
||||
// Used for communication between your site and Google. Be sure to keep it a secret.
|
||||
//
|
||||
// Use `SiteVerify` to verify a request inside another handler if needed.
|
||||
func New(secret string) context.Handler {
|
||||
return func(ctx context.Context) {
|
||||
if SiteFerify(ctx, secret).Success {
|
||||
ctx.Next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SiteFerify accepts context and the secret key(https://www.google.com/recaptcha)
|
||||
// and returns the google's recaptcha response, if `response.Success` is true
|
||||
// then validation passed.
|
||||
//
|
||||
// Use `New` for middleware use instead.
|
||||
func SiteFerify(ctx context.Context, secret string) (response Response) {
|
||||
generatedResponseID := ctx.FormValue("g-recaptcha-response")
|
||||
if generatedResponseID == "" {
|
||||
response.ErrorCodes = append(response.ErrorCodes,
|
||||
"form value[g-recaptcha-response] is empty")
|
||||
return
|
||||
}
|
||||
|
||||
r, err := client.PostForm(apiURL,
|
||||
url.Values{
|
||||
"secret": {secret},
|
||||
"response": {generatedResponseID},
|
||||
// optional: let's no track our users "remoteip": {ctx.RemoteAddr()},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
response.ErrorCodes = append(response.ErrorCodes, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(r.Body)
|
||||
r.Body.Close()
|
||||
if err != nil {
|
||||
response.ErrorCodes = append(response.ErrorCodes, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &response)
|
||||
if err != nil {
|
||||
response.ErrorCodes = append(response.ErrorCodes, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
var recaptchaForm = `<form action="%s" method="POST">
|
||||
<script src="https://www.google.com/recaptcha/api.js"></script>
|
||||
<div class="g-recaptcha" data-sitekey="%s"></div>
|
||||
<input type="submit" name="button" value="OK">
|
||||
</form>`
|
||||
|
||||
// GetFormHTML can be used on pages where empty form
|
||||
// is enough to verify that the client is not a "robot".
|
||||
// i.e: GetFormHTML("public_key", "/contact")
|
||||
// will return form tag which imports the google API script,
|
||||
// with a simple submit button where redirects to the
|
||||
// "postActionRelativePath".
|
||||
//
|
||||
// The "postActionRelativePath" MUST use the `SiteVerify` or
|
||||
// followed by the `New()`'s context.Handler (with the secret key this time)
|
||||
// in order to validate if the recaptcha verified.
|
||||
//
|
||||
// The majority of applications will use a custom form,
|
||||
// this function is here for ridiculous simple use cases.
|
||||
//
|
||||
// Example Code:
|
||||
//
|
||||
// Method: "POST" | Path: "/contact"
|
||||
// func postContact(ctx context.Context) {
|
||||
// // [...]
|
||||
// response := recaptcha.SiteFerify(ctx, recaptchaSecret)
|
||||
//
|
||||
// if response.Success {
|
||||
// // [your action here, i.e sendEmail(...)]
|
||||
// }
|
||||
//
|
||||
// ctx.JSON(response)
|
||||
// }
|
||||
//
|
||||
// Method: "GET" | Path: "/contact"
|
||||
// func getContact(ctx context.Context) {
|
||||
// // render the recaptcha form
|
||||
// ctx.HTML(recaptcha.GetFormHTML(recaptchaPublic, "/contact"))
|
||||
// }
|
||||
func GetFormHTML(dataSiteKey string, postActionRelativePath string) string {
|
||||
return fmt.Sprintf(recaptchaForm, postActionRelativePath, dataSiteKey)
|
||||
}
|
87
version.go
87
version.go
|
@ -2,21 +2,21 @@ package iris
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
"github.com/kataras/golog"
|
||||
"github.com/kataras/iris/core/netutil"
|
||||
)
|
||||
|
||||
const (
|
||||
versionURL = "https://raw.githubusercontent.com/kataras/iris/master/VERSION"
|
||||
versionURL = "http://iris-go.com/version"
|
||||
updateCmd = "go get -u -f -v github.com/kataras/iris"
|
||||
)
|
||||
|
||||
|
@ -29,28 +29,16 @@ func CheckVersion() {
|
|||
})
|
||||
}
|
||||
|
||||
type versionInfo struct {
|
||||
Version string `json:"version"`
|
||||
ChangelogURL string `json:"changelog_url"`
|
||||
UpdateAvailable bool `json:"update_available"`
|
||||
}
|
||||
|
||||
func checkVersion() {
|
||||
client := netutil.Client(time.Duration(15 * time.Second))
|
||||
r, err := client.PostForm(versionURL, url.Values{"current_version": {Version}})
|
||||
|
||||
// open connection and read/write timeouts
|
||||
timeout := time.Duration(10 * time.Second)
|
||||
|
||||
transport := http.Transport{
|
||||
Dial: func(network string, addr string) (net.Conn, error) {
|
||||
conn, err := net.DialTimeout(network, addr, timeout)
|
||||
if err != nil {
|
||||
golog.Debugf("%v", err)
|
||||
return nil, err
|
||||
}
|
||||
conn.SetDeadline(time.Now().Add(timeout)) // skip error
|
||||
return conn, nil
|
||||
},
|
||||
}
|
||||
|
||||
client := http.Client{
|
||||
Transport: &transport,
|
||||
}
|
||||
|
||||
r, err := client.Get(versionURL)
|
||||
if err != nil {
|
||||
golog.Debugf("%v", err)
|
||||
return
|
||||
|
@ -68,53 +56,29 @@ func checkVersion() {
|
|||
return
|
||||
}
|
||||
|
||||
var (
|
||||
fetchedVersion = string(b)
|
||||
changelogURL string
|
||||
)
|
||||
|
||||
// 8.2.1:https://github.com/kataras/iris/blob/master/HISTORY.md#tu-08-august-2017--v821
|
||||
if idx := strings.IndexByte(fetchedVersion, ':'); idx > 0 {
|
||||
changelogURL = fetchedVersion[idx+1:]
|
||||
fetchedVersion = fetchedVersion[0:idx]
|
||||
}
|
||||
|
||||
latestVersion, err := version.NewVersion(fetchedVersion)
|
||||
if err != nil {
|
||||
golog.Debugf("while parsing latest version: %v", err)
|
||||
v := new(versionInfo)
|
||||
if err := json.Unmarshal(b, v); err != nil {
|
||||
golog.Debugf("error while unmarshal the response body: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
currentVersion, err := version.NewVersion(Version)
|
||||
if err != nil {
|
||||
golog.Debugf("while parsing current version: %v", err)
|
||||
if !v.UpdateAvailable {
|
||||
return
|
||||
}
|
||||
|
||||
if currentVersion.GreaterThan(latestVersion) {
|
||||
golog.Debugf("current version is greater than latest version, report as bug")
|
||||
return
|
||||
format := "A more recent version has been found[%s > %s].\n"
|
||||
|
||||
if v.ChangelogURL != "" {
|
||||
format += "Release notes: %s\n"
|
||||
}
|
||||
|
||||
if currentVersion.Equal(latestVersion) {
|
||||
return
|
||||
}
|
||||
format += "Update now?[%s]: "
|
||||
|
||||
// currentVersion.LessThan(latestVersion)
|
||||
updaterYesInput := [...]string{"y", "yes"}
|
||||
|
||||
var updaterYesInput = [...]string{"y", "yes"}
|
||||
|
||||
text := "A more recent version has been found[%s > %s].\n"
|
||||
|
||||
if changelogURL != "" {
|
||||
text += "Release notes: %s\n"
|
||||
}
|
||||
|
||||
text += "Update now?[%s]: "
|
||||
|
||||
golog.Warnf(text,
|
||||
latestVersion.String(), currentVersion.String(),
|
||||
changelogURL,
|
||||
golog.Warnf(format, v.Version, Version,
|
||||
v.ChangelogURL,
|
||||
updaterYesInput[0]+"/n")
|
||||
|
||||
silent := false
|
||||
|
@ -126,6 +90,7 @@ func checkVersion() {
|
|||
if !silent {
|
||||
if sc.Scan() {
|
||||
inputText := sc.Text()
|
||||
|
||||
for _, s := range updaterYesInput {
|
||||
if inputText == s {
|
||||
shouldUpdate = true
|
||||
|
@ -146,6 +111,6 @@ func checkVersion() {
|
|||
return
|
||||
}
|
||||
|
||||
golog.Infof("Update process finished, current version: %s.\nManual restart is required to apply the changes.\n", latestVersion.String())
|
||||
golog.Infof("Update process finished.\nManual restart is required to apply the changes.\n")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user