mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
Add a better example for the recaptcha middleware as requested at: https://github.com/kataras/iris/issues/799
Former-commit-id: 85c3286a9d6be5cf47631e7608f70f3790934e64
This commit is contained in:
parent
7cd78df9e3
commit
ef41e07d4e
44
_examples/miscellaneous/recaptcha/custom_form/main.go
Normal file
44
_examples/miscellaneous/recaptcha/custom_form/main.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/kataras/iris"
|
||||||
|
|
||||||
|
"github.com/kataras/iris/middleware/recaptcha"
|
||||||
|
)
|
||||||
|
|
||||||
|
// keys should be obtained by https://www.google.com/recaptcha
|
||||||
|
const (
|
||||||
|
recaptchaPublic = "6Lf3WywUAAAAAKNfAm5DP2J5ahqedtZdHTYaKkJ6"
|
||||||
|
recaptchaSecret = "6Lf3WywUAAAAAJpArb8nW_LCL_PuPuokmEABFfgw"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := iris.New()
|
||||||
|
|
||||||
|
r := recaptcha.New(recaptchaSecret)
|
||||||
|
|
||||||
|
app.Get("/comment", showRecaptchaForm)
|
||||||
|
|
||||||
|
// pass the middleware before the main handler or use the `recaptcha.SiteVerify`.
|
||||||
|
app.Post("/comment", r, postComment)
|
||||||
|
|
||||||
|
app.Run(iris.Addr(":8080"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var htmlForm = `<form action="/comment" 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="Verify">
|
||||||
|
</form>`
|
||||||
|
|
||||||
|
func showRecaptchaForm(ctx iris.Context) {
|
||||||
|
contents := fmt.Sprintf(htmlForm, recaptchaPublic)
|
||||||
|
ctx.HTML(contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
func postComment(ctx iris.Context) {
|
||||||
|
// [...]
|
||||||
|
ctx.JSON(iris.Map{"success": true})
|
||||||
|
}
|
|
@ -1,44 +1,40 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
|
|
||||||
"github.com/kataras/iris/middleware/recaptcha"
|
"github.com/kataras/iris/middleware/recaptcha"
|
||||||
)
|
)
|
||||||
|
|
||||||
// publicDataSiteKey and secretKey and should be obtained by https://www.google.com/recaptcha.
|
// keys should be obtained by https://www.google.com/recaptcha
|
||||||
const (
|
const (
|
||||||
publicDataSiteKey = ""
|
recaptchaPublic = ""
|
||||||
secretKey = ""
|
recaptchaSecret = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func showRecaptchaForm(ctx iris.Context, path string) {
|
||||||
|
ctx.HTML(recaptcha.GetFormHTML(recaptchaPublic, path))
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
r := recaptcha.New(secretKey)
|
// On both Get and Post on this example, so you can easly
|
||||||
|
// use a single route to show a form and the main subject if recaptcha's validation result succeed.
|
||||||
|
app.HandleMany("GET POST", "/", func(ctx iris.Context) {
|
||||||
|
if ctx.Method() == iris.MethodGet {
|
||||||
|
showRecaptchaForm(ctx, "/")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
app.Get("/comment", showRecaptchaForm)
|
result := recaptcha.SiteFerify(ctx, recaptchaSecret)
|
||||||
|
if !result.Success {
|
||||||
|
/* redirect here if u want or do nothing */
|
||||||
|
ctx.HTML("<b> failed please try again </b>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// pass the middleware before the main handler or use the `recaptcha.SiteVerify`.
|
ctx.Writef("succeed.")
|
||||||
app.Post("/comment", r, postComment)
|
})
|
||||||
|
|
||||||
app.Run(iris.Addr(":8080"))
|
app.Run(iris.Addr(":8080"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlForm = `<form action="/comment" 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="Verify">
|
|
||||||
</form>`
|
|
||||||
|
|
||||||
func showRecaptchaForm(ctx iris.Context) {
|
|
||||||
contents := fmt.Sprintf(htmlForm, publicDataSiteKey)
|
|
||||||
ctx.HTML(contents)
|
|
||||||
}
|
|
||||||
|
|
||||||
func postComment(ctx iris.Context) {
|
|
||||||
// [...]
|
|
||||||
ctx.JSON(iris.Map{"success": true})
|
|
||||||
}
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ func h(ctx iris.Context) {
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := newApp()
|
app := newApp()
|
||||||
|
app.Logger().SetLevel("debug")
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// GET
|
// GET
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -1056,7 +1055,7 @@ func (ctx *context) Proceed(h Handler) bool {
|
||||||
|
|
||||||
// HandlerName returns the current handler's name, helpful for debugging.
|
// HandlerName returns the current handler's name, helpful for debugging.
|
||||||
func (ctx *context) HandlerName() string {
|
func (ctx *context) HandlerName() string {
|
||||||
return runtime.FuncForPC(reflect.ValueOf(ctx.handlers[ctx.currentHandlerIndex]).Pointer()).Name()
|
return HandlerName(ctx.handlers[ctx.currentHandlerIndex])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do sets the handler index to zero, executes the first handler
|
// Do sets the handler index to zero, executes the first handler
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package context
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
// A Handler responds to an HTTP request.
|
// A Handler responds to an HTTP request.
|
||||||
// It writes reply headers and data to the Context.ResponseWriter() and then return.
|
// It writes reply headers and data to the Context.ResponseWriter() and then return.
|
||||||
// Returning signals that the request is finished;
|
// Returning signals that the request is finished;
|
||||||
|
@ -20,3 +25,12 @@ type Handler func(Context)
|
||||||
//
|
//
|
||||||
// See `Handler` for more.
|
// See `Handler` for more.
|
||||||
type Handlers []Handler
|
type Handlers []Handler
|
||||||
|
|
||||||
|
// HandlerName returns the name, the handler function informations.
|
||||||
|
// Same as `context.HandlerName`.
|
||||||
|
func HandlerName(h Handler) string {
|
||||||
|
pc := reflect.ValueOf(h).Pointer()
|
||||||
|
// l, n := runtime.FuncForPC(pc).FileLine(pc)
|
||||||
|
// return fmt.Sprintf("%s:%d", l, n)
|
||||||
|
return runtime.FuncForPC(pc).Name()
|
||||||
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/kataras/iris/core/netutil"
|
"github.com/kataras/iris/core/netutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const host = "http://live.iris-go.com"
|
const host = "https://live.iris-go.com"
|
||||||
|
|
||||||
// PostForm performs the PostForm with a secure client.
|
// PostForm performs the PostForm with a secure client.
|
||||||
func PostForm(p string, data url.Values) (*http.Response, error) {
|
func PostForm(p string, data url.Values) (*http.Response, error) {
|
||||||
|
|
|
@ -23,15 +23,17 @@ func CheckForUpdates() {
|
||||||
updateAvailale := v.Compare(Version) == version.Smaller
|
updateAvailale := v.Compare(Version) == version.Smaller
|
||||||
|
|
||||||
if updateAvailale {
|
if updateAvailale {
|
||||||
|
if confirmUpdate(v) {
|
||||||
has, ft := hasInternetConnection()
|
has, ft := hasInternetConnection()
|
||||||
canUpdate := (has && ft && ask()) || !has || !ft
|
canUpdate := (has && ft && ask()) || !has || !ft
|
||||||
if canUpdate {
|
if canUpdate {
|
||||||
installVersion(v)
|
installVersion()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func installVersion(v version.Version) {
|
func confirmUpdate(v version.Version) bool {
|
||||||
// on help? when asking for installing the new update
|
// on help? when asking for installing the new update
|
||||||
// and when answering "No".
|
// and when answering "No".
|
||||||
ignoreUpdatesMsg := "Would you like to ignore future updates? Disable the version checker via:\napp.Run(..., iris.WithoutVersionChecker)"
|
ignoreUpdatesMsg := "Would you like to ignore future updates? Disable the version checker via:\napp.Run(..., iris.WithoutVersionChecker)"
|
||||||
|
@ -47,10 +49,11 @@ func installVersion(v version.Version) {
|
||||||
Message: shouldUpdateNowMsg,
|
Message: shouldUpdateNowMsg,
|
||||||
Help: ignoreUpdatesMsg,
|
Help: ignoreUpdatesMsg,
|
||||||
}, &confirmUpdate, nil)
|
}, &confirmUpdate, nil)
|
||||||
|
return confirmUpdate // it's true only when update was available and user typed "yes".
|
||||||
|
}
|
||||||
|
|
||||||
// run the updater last, so the user can star the repo and at the same time
|
func installVersion() {
|
||||||
// the app will update her/his local iris.
|
golog.Infof("Downloading...\n")
|
||||||
if confirmUpdate { // it's true only when update was available and user typed "yes".
|
|
||||||
repo := "github.com/kataras/iris/..."
|
repo := "github.com/kataras/iris/..."
|
||||||
cmd := exec.Command("go", "get", "-u", "-v", repo)
|
cmd := exec.Command("go", "get", "-u", "-v", repo)
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
|
@ -65,9 +68,6 @@ func installVersion(v version.Version) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if update was available but chosen not to update then just continue...
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Author's note:
|
/* Author's note:
|
||||||
We could use github webhooks to automatic notify for updates
|
We could use github webhooks to automatic notify for updates
|
||||||
when a new update is pushed to the repository
|
when a new update is pushed to the repository
|
||||||
|
|
|
@ -146,6 +146,13 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co
|
||||||
}
|
}
|
||||||
|
|
||||||
fullpath := api.relativePath + relativePath // for now, keep the last "/" if any, "/xyz/"
|
fullpath := api.relativePath + relativePath // for now, keep the last "/" if any, "/xyz/"
|
||||||
|
if len(handlers) == 0 {
|
||||||
|
api.reporter.Add("missing handlers for route %s: %s", method, fullpath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// before join the middleware + handlers + done handlers.
|
||||||
|
possibleMainHandlerName := context.HandlerName(handlers[0])
|
||||||
|
|
||||||
// global begin handlers -> middleware that are registered before route registration
|
// global begin handlers -> middleware that are registered before route registration
|
||||||
// -> handlers that are passed to this Handle function.
|
// -> handlers that are passed to this Handle function.
|
||||||
|
@ -158,7 +165,7 @@ func (api *APIBuilder) Handle(method string, relativePath string, handlers ...co
|
||||||
// here we separate the subdomain and relative path
|
// here we separate the subdomain and relative path
|
||||||
subdomain, path := splitSubdomainAndPath(fullpath)
|
subdomain, path := splitSubdomainAndPath(fullpath)
|
||||||
|
|
||||||
r, err := NewRoute(method, subdomain, path, routeHandlers, api.macros)
|
r, err := NewRoute(method, subdomain, path, possibleMainHandlerName, routeHandlers, api.macros)
|
||||||
if err != nil { // template path parser errors:
|
if err != nil { // template path parser errors:
|
||||||
api.reporter.Add("%v -> %s:%s:%s", err, method, subdomain, path)
|
api.reporter.Add("%v -> %s:%s:%s", err, method, subdomain, path)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/kataras/golog"
|
||||||
"html"
|
"html"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -136,7 +137,9 @@ func (h *routerHandler) Build(provider RoutesProvider) error {
|
||||||
if err := h.addRoute(r); err != nil {
|
if err := h.addRoute(r); err != nil {
|
||||||
// node errors:
|
// node errors:
|
||||||
rp.Add("%v -> %s", err, r.String())
|
rp.Add("%v -> %s", err, r.String())
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
golog.Debugf(r.Trace())
|
||||||
}
|
}
|
||||||
|
|
||||||
return rp.Return()
|
return rp.Return()
|
||||||
|
|
|
@ -23,6 +23,7 @@ type Route struct {
|
||||||
// Handlers are the main route's handlers, executed by order.
|
// Handlers are the main route's handlers, executed by order.
|
||||||
// Cannot be empty.
|
// Cannot be empty.
|
||||||
Handlers context.Handlers
|
Handlers context.Handlers
|
||||||
|
mainHandlerName string
|
||||||
// temp storage, they're appended to the Handlers on build.
|
// temp storage, they're appended to the Handlers on build.
|
||||||
// Execution happens after Begin and main Handler(s), can be empty.
|
// Execution happens after Begin and main Handler(s), can be empty.
|
||||||
doneHandlers context.Handlers
|
doneHandlers context.Handlers
|
||||||
|
@ -36,7 +37,7 @@ type Route struct {
|
||||||
// handlers and the macro container which all routes should share.
|
// handlers and the macro container which all routes should share.
|
||||||
// It parses the path based on the "macros",
|
// It parses the path based on the "macros",
|
||||||
// handlers are being changed to validate the macros at serve time, if needed.
|
// handlers are being changed to validate the macros at serve time, if needed.
|
||||||
func NewRoute(method, subdomain, unparsedPath string,
|
func NewRoute(method, subdomain, unparsedPath, mainHandlerName string,
|
||||||
handlers context.Handlers, macros *macro.Map) (*Route, error) {
|
handlers context.Handlers, macros *macro.Map) (*Route, error) {
|
||||||
|
|
||||||
tmpl, err := macro.Parse(unparsedPath, macros)
|
tmpl, err := macro.Parse(unparsedPath, macros)
|
||||||
|
@ -60,6 +61,7 @@ func NewRoute(method, subdomain, unparsedPath string,
|
||||||
tmpl: tmpl,
|
tmpl: tmpl,
|
||||||
Path: path,
|
Path: path,
|
||||||
Handlers: handlers,
|
Handlers: handlers,
|
||||||
|
mainHandlerName: mainHandlerName,
|
||||||
FormattedPath: formattedPath,
|
FormattedPath: formattedPath,
|
||||||
}
|
}
|
||||||
return route, nil
|
return route, nil
|
||||||
|
@ -203,6 +205,27 @@ func (r Route) ResolvePath(args ...string) string {
|
||||||
return formattedPath
|
return formattedPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trace returns some debug infos as a string sentence.
|
||||||
|
// Should be called after Build.
|
||||||
|
func (r Route) Trace() string {
|
||||||
|
printfmt := fmt.Sprintf("%s:", r.Method)
|
||||||
|
if r.Subdomain != "" {
|
||||||
|
printfmt += fmt.Sprintf(" %s", r.Subdomain)
|
||||||
|
}
|
||||||
|
printfmt += fmt.Sprintf(" %s ", r.Tmpl().Src)
|
||||||
|
if l := len(r.Handlers); l > 1 {
|
||||||
|
printfmt += fmt.Sprintf("-> %s() and %d more", r.mainHandlerName, l-1)
|
||||||
|
} else {
|
||||||
|
printfmt += fmt.Sprintf("-> %s()", r.mainHandlerName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// printfmt := fmt.Sprintf("%s: %s >> %s", r.Method, r.Subdomain+r.Tmpl().Src, r.mainHandlerName)
|
||||||
|
// if l := len(r.Handlers); l > 0 {
|
||||||
|
// printfmt += fmt.Sprintf(" and %d more", l)
|
||||||
|
// }
|
||||||
|
return printfmt // without new line.
|
||||||
|
}
|
||||||
|
|
||||||
type routeReadOnlyWrapper struct {
|
type routeReadOnlyWrapper struct {
|
||||||
*Route
|
*Route
|
||||||
}
|
}
|
||||||
|
@ -222,3 +245,7 @@ func (rd routeReadOnlyWrapper) Subdomain() string {
|
||||||
func (rd routeReadOnlyWrapper) Path() string {
|
func (rd routeReadOnlyWrapper) Path() string {
|
||||||
return rd.Route.tmpl.Src
|
return rd.Route.tmpl.Src
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rd routeReadOnlyWrapper) Trace() string {
|
||||||
|
return rd.Route.Trace()
|
||||||
|
}
|
||||||
|
|
3
iris.go
3
iris.go
|
@ -425,7 +425,10 @@ func (app *Application) NewHost(srv *http.Server) *host.Supervisor {
|
||||||
}
|
}
|
||||||
|
|
||||||
su.IgnoredErrors = append(su.IgnoredErrors, app.config.IgnoreServerErrors...)
|
su.IgnoredErrors = append(su.IgnoredErrors, app.config.IgnoreServerErrors...)
|
||||||
|
if len(su.IgnoredErrors) > 0 {
|
||||||
app.logger.Debugf("Host: server will ignore the following errors: %s", su.IgnoredErrors)
|
app.logger.Debugf("Host: server will ignore the following errors: %s", su.IgnoredErrors)
|
||||||
|
}
|
||||||
|
|
||||||
su.Configure(app.hostConfigurators...)
|
su.Configure(app.hostConfigurators...)
|
||||||
|
|
||||||
app.Hosts = append(app.Hosts, su)
|
app.Hosts = append(app.Hosts, su)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user