mirror of
https://github.com/kataras/iris.git
synced 2026-01-21 02:45:59 +00:00
version 12.1.5
Former-commit-id: cda69f08955cb0d594e98bf26197ee573cbba4b2
This commit is contained in:
@@ -182,7 +182,7 @@ const delim = "\n"
|
||||
|
||||
func (g *Group) Error() (s string) {
|
||||
if len(g.Errors) > 0 {
|
||||
msgs := make([]string, len(g.Errors), len(g.Errors))
|
||||
msgs := make([]string, len(g.Errors))
|
||||
for i, err := range g.Errors {
|
||||
msgs[i] = err.Error()
|
||||
}
|
||||
@@ -320,21 +320,6 @@ func sortGroups(groups []*Group) {
|
||||
})
|
||||
}
|
||||
|
||||
func tryGetTypeText(typ interface{}) string {
|
||||
if typ == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
switch v := typ.(type) {
|
||||
case string:
|
||||
return v
|
||||
case fmt.Stringer:
|
||||
return v.String()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func isNotNil(err error) bool {
|
||||
if g, ok := err.(*Group); ok {
|
||||
if len(g.Errors) > 0 {
|
||||
|
||||
@@ -136,7 +136,7 @@ func TestGroup(t *testing.T) {
|
||||
|
||||
t.Run("Walk", func(t *testing.T) {
|
||||
expectedEntries := 4
|
||||
Walk(g, func(typ interface{}, err error) {
|
||||
_ = Walk(g, func(typ interface{}, err error) {
|
||||
g.IncludeChildren = false
|
||||
childAPIErrorsGroup.IncludeChildren = false
|
||||
childAPIErrorsGroup2.IncludeChildren = false
|
||||
|
||||
@@ -14,13 +14,13 @@ import (
|
||||
// .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 handler.(type) {
|
||||
switch h := handler.(type) {
|
||||
case context.Handler:
|
||||
{
|
||||
//
|
||||
// it's already a iris handler
|
||||
//
|
||||
return handler.(context.Handler)
|
||||
return h
|
||||
}
|
||||
|
||||
case http.Handler:
|
||||
@@ -28,7 +28,6 @@ func FromStd(handler interface{}) context.Handler {
|
||||
// handlerFunc.ServeHTTP(w,r)
|
||||
//
|
||||
{
|
||||
h := handler.(http.Handler)
|
||||
return func(ctx context.Context) {
|
||||
h.ServeHTTP(ctx.ResponseWriter(), ctx.Request())
|
||||
}
|
||||
@@ -39,7 +38,7 @@ func FromStd(handler interface{}) context.Handler {
|
||||
//
|
||||
// handlerFunc(w,r)
|
||||
//
|
||||
return FromStd(http.HandlerFunc(handler.(func(http.ResponseWriter, *http.Request))))
|
||||
return FromStd(http.HandlerFunc(h))
|
||||
}
|
||||
|
||||
case func(http.ResponseWriter, *http.Request, http.HandlerFunc):
|
||||
@@ -47,7 +46,7 @@ func FromStd(handler interface{}) context.Handler {
|
||||
//
|
||||
// handlerFunc(w,r, http.HandlerFunc)
|
||||
//
|
||||
return FromStdWithNext(handler.(func(http.ResponseWriter, *http.Request, http.HandlerFunc)))
|
||||
return FromStdWithNext(h)
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -15,7 +15,10 @@ import (
|
||||
func TestFromStd(t *testing.T) {
|
||||
expected := "ok"
|
||||
std := func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(expected))
|
||||
_, err := w.Write([]byte(expected))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
h := handlerconv.FromStd(http.HandlerFunc(std))
|
||||
|
||||
@@ -64,13 +64,11 @@ func (i *interruptListener) notifyAndFire() {
|
||||
os.Interrupt,
|
||||
syscall.SIGINT, // register that too, it should be ok
|
||||
// os.Kill is equivalent with the syscall.SIGKILL
|
||||
os.Kill,
|
||||
syscall.SIGKILL, // register that too, it should be ok
|
||||
// os.Kill,
|
||||
// syscall.SIGKILL, // register that too, it should be ok
|
||||
// kill -SIGTERM XXXX
|
||||
syscall.SIGTERM,
|
||||
)
|
||||
select {
|
||||
case <-ch:
|
||||
i.FireNow()
|
||||
}
|
||||
<-ch
|
||||
i.FireNow()
|
||||
}
|
||||
|
||||
@@ -194,12 +194,8 @@ func (su *Supervisor) supervise(blockFunc func() error) error {
|
||||
su.notifyErr(err)
|
||||
|
||||
if su.isWaiting() {
|
||||
blockStatement:
|
||||
for {
|
||||
select {
|
||||
case <-su.unblockChan:
|
||||
break blockStatement
|
||||
}
|
||||
for range su.unblockChan {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ func ExampleSupervisor_RegisterOnError() {
|
||||
|
||||
go su.ListenAndServe()
|
||||
time.Sleep(1 * time.Second)
|
||||
su.Shutdown(context.TODO())
|
||||
if err := su.Shutdown(context.TODO()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Output:
|
||||
@@ -49,37 +51,30 @@ func (m myTestTask) OnServe(host TaskHost) {
|
||||
ticker := time.NewTicker(m.restartEvery)
|
||||
defer ticker.Stop()
|
||||
rans := 0
|
||||
for {
|
||||
select {
|
||||
case _, ok := <-ticker.C:
|
||||
{
|
||||
if !ok {
|
||||
m.logger.Println("ticker issue, closed channel, exiting from this task...")
|
||||
return
|
||||
}
|
||||
exitAfterXRestarts := m.maxRestarts
|
||||
if rans == exitAfterXRestarts {
|
||||
m.logger.Println("exit")
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
|
||||
defer cancel()
|
||||
host.Supervisor.Shutdown(ctx) // total shutdown
|
||||
host.Supervisor.RestoreFlow() // free to exit (if shutdown)
|
||||
return
|
||||
}
|
||||
|
||||
rans++
|
||||
|
||||
m.logger.Println(fmt.Sprintf("closed %d times", rans))
|
||||
host.Shutdown(context.TODO())
|
||||
|
||||
startDelay := 2 * time.Second
|
||||
time.AfterFunc(startDelay, func() {
|
||||
m.logger.Println("restart")
|
||||
host.Serve() // restart
|
||||
})
|
||||
|
||||
}
|
||||
for range ticker.C {
|
||||
exitAfterXRestarts := m.maxRestarts
|
||||
if rans == exitAfterXRestarts {
|
||||
m.logger.Println("exit")
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), 5*time.Second)
|
||||
defer cancel()
|
||||
_ = host.Supervisor.Shutdown(ctx) // total shutdown
|
||||
host.Supervisor.RestoreFlow() // free to exit (if shutdown)
|
||||
return
|
||||
}
|
||||
|
||||
rans++
|
||||
|
||||
m.logger.Println(fmt.Sprintf("closed %d times", rans))
|
||||
host.Shutdown(context.TODO())
|
||||
|
||||
startDelay := 2 * time.Second
|
||||
time.AfterFunc(startDelay, func() {
|
||||
m.logger.Println("restart")
|
||||
if err := host.Serve(); err != nil { // restart
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,10 @@ func testSupervisor(t *testing.T, creator func(*http.Server, []func(TaskHost)) *
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(expectedBody))
|
||||
_, err := w.Write([]byte(expectedBody))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
// host (server wrapper and adapter) construction
|
||||
|
||||
@@ -27,7 +27,7 @@ func WriteStartupLogOnServe(w io.Writer) func(TaskHost) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
interruptkey = "CMD"
|
||||
}
|
||||
w.Write([]byte(fmt.Sprintf("Now listening on: %s\nApplication started. Press %s+C to shut down.\n",
|
||||
_, _ = w.Write([]byte(fmt.Sprintf("Now listening on: %s\nApplication started. Press %s+C to shut down.\n",
|
||||
listeningURI, interruptkey)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ func (r *Store) Save(key string, value interface{}, immutable bool) (Entry, bool
|
||||
// we should allow this
|
||||
kv.ValueRaw = value
|
||||
kv.immutable = immutable
|
||||
} else if kv.immutable == false {
|
||||
} else if !kv.immutable {
|
||||
// if it was not immutable then user can alt it via `Set` and `SetImmutable`
|
||||
kv.ValueRaw = value
|
||||
kv.immutable = immutable
|
||||
|
||||
@@ -91,13 +91,8 @@ var IsLoopbackHost = func(requestHost string) bool {
|
||||
const (
|
||||
// defaultServerHostname returns the default hostname which is "localhost"
|
||||
defaultServerHostname = "localhost"
|
||||
// defaultServerPort returns the default port which is 8080, not used
|
||||
defaultServerPort = 8080
|
||||
)
|
||||
|
||||
// defaultServerAddr the default server addr which is: localhost:8080
|
||||
var defaultServerAddr = defaultServerHostname + ":" + strconv.Itoa(defaultServerPort)
|
||||
|
||||
// ResolveAddr tries to convert a given string to an address which is compatible with net.Listener and server
|
||||
func ResolveAddr(addr string) string {
|
||||
// check if addr has :port, if not do it +:80 ,we need the hostname for many cases
|
||||
|
||||
@@ -23,13 +23,17 @@ type tcpKeepAliveListener struct {
|
||||
}
|
||||
|
||||
// Accept accepts tcp connections aka clients.
|
||||
func (l tcpKeepAliveListener) Accept() (c net.Conn, err error) {
|
||||
func (l tcpKeepAliveListener) Accept() (net.Conn, error) {
|
||||
tc, err := l.AcceptTCP()
|
||||
if err != nil {
|
||||
return
|
||||
return tc, err
|
||||
}
|
||||
if err = tc.SetKeepAlive(true); err != nil {
|
||||
return tc, err
|
||||
}
|
||||
if err = tc.SetKeepAlivePeriod(3 * time.Minute); err != nil {
|
||||
return tc, err
|
||||
}
|
||||
tc.SetKeepAlive(true)
|
||||
tc.SetKeepAlivePeriod(3 * time.Minute)
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -42,66 +41,6 @@ type repository struct {
|
||||
pos map[string]int
|
||||
}
|
||||
|
||||
func (repo *repository) remove(route *Route) bool {
|
||||
for i, r := range repo.routes {
|
||||
if r == route {
|
||||
return repo.removeByIndex(i)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (repo *repository) removeByPath(tmplPath string) bool {
|
||||
if repo.pos != nil {
|
||||
if idx, ok := repo.pos[tmplPath]; ok {
|
||||
return repo.removeByIndex(idx)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (repo *repository) removeByName(routeName string) bool {
|
||||
for i, r := range repo.routes {
|
||||
if r.Name == routeName {
|
||||
return repo.removeByIndex(i)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (repo *repository) removeByIndex(idx int) bool {
|
||||
n := len(repo.routes)
|
||||
|
||||
if n == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
if idx >= n {
|
||||
return false
|
||||
}
|
||||
|
||||
if n == 1 && idx == 0 {
|
||||
repo.routes = repo.routes[0:0]
|
||||
repo.pos = nil
|
||||
return true
|
||||
}
|
||||
|
||||
r := repo.routes[idx]
|
||||
if r == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
repo.routes = append(repo.routes[:idx], repo.routes[idx+1:]...)
|
||||
if repo.pos != nil {
|
||||
delete(repo.pos, r.Path)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (repo *repository) get(routeName string) *Route {
|
||||
for _, r := range repo.routes {
|
||||
if r.Name == routeName {
|
||||
@@ -160,15 +99,6 @@ func (repo *repository) register(route *Route) {
|
||||
repo.pos[route.tmpl.Src] = len(repo.routes) - 1
|
||||
}
|
||||
|
||||
type apiError struct {
|
||||
error
|
||||
}
|
||||
|
||||
func (e *apiError) Is(err error) bool {
|
||||
_, ok := err.(*apiError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// APIBuilder the visible API for constructing the router
|
||||
// and child routers.
|
||||
type APIBuilder struct {
|
||||
@@ -179,9 +109,6 @@ type APIBuilder struct {
|
||||
// the api builder global routes repository
|
||||
routes *repository
|
||||
|
||||
// the api builder global route path reverser object
|
||||
// used by the view engine but it can be used anywhere.
|
||||
reverser *RoutePathReverser
|
||||
// the api builder global errors, can be filled by the Subdomain, WildcardSubdomain, Handle...
|
||||
// the list of possible errors that can be
|
||||
// collected on the build state to log
|
||||
@@ -344,7 +271,7 @@ func (api *APIBuilder) CreateRoutes(methods []string, relativePath string, handl
|
||||
// if allowMethods are empty, then simply register with the passed, main, method.
|
||||
methods = append(api.allowMethods, methods...)
|
||||
|
||||
routes := make([]*Route, len(methods), len(methods))
|
||||
routes := make([]*Route, len(methods))
|
||||
|
||||
for i, m := range methods {
|
||||
route, err := NewRoute(m, subdomain, path, possibleMainHandlerName, routeHandlers, *api.macros)
|
||||
@@ -492,11 +419,22 @@ func (api *APIBuilder) HandleDir(requestPath, directory string, opts ...DirOptio
|
||||
continue
|
||||
}
|
||||
|
||||
slashIdx := strings.IndexByte(s.RequestPath, '/')
|
||||
if slashIdx == -1 {
|
||||
slashIdx = 0
|
||||
if n := len(api.relativePath); n > 0 && api.relativePath[n-1] == SubdomainPrefix[0] {
|
||||
// this api is a subdomain-based.
|
||||
slashIdx := strings.IndexByte(s.RequestPath, '/')
|
||||
if slashIdx == -1 {
|
||||
slashIdx = 0
|
||||
}
|
||||
|
||||
requestPath = s.RequestPath[slashIdx:]
|
||||
} else {
|
||||
requestPath = s.RequestPath[strings.Index(s.RequestPath, api.relativePath)+len(api.relativePath):]
|
||||
}
|
||||
requestPath = s.RequestPath[slashIdx:]
|
||||
|
||||
if requestPath == "" {
|
||||
requestPath = "/"
|
||||
}
|
||||
|
||||
routes = append(routes, api.CreateRoutes([]string{http.MethodGet}, requestPath, h)...)
|
||||
getRoute.StaticSites = append(getRoute.StaticSites, s)
|
||||
}
|
||||
@@ -861,9 +799,6 @@ func (api *APIBuilder) StaticContent(reqPath string, cType string, content []byt
|
||||
return api.registerResourceRoute(reqPath, h)
|
||||
}
|
||||
|
||||
// errDirectoryFileNotFound returns an error with message: 'Directory or file %s couldn't found. Trace: +error trace'
|
||||
var errDirectoryFileNotFound = errors.New("Directory or file %s couldn't found. Trace: %s")
|
||||
|
||||
// Favicon serves static favicon
|
||||
// accepts 2 parameters, second is optional
|
||||
// favPath (string), declare the system directory path of the __.ico
|
||||
|
||||
@@ -307,7 +307,10 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||
sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() })
|
||||
|
||||
ctx.ContentType(context.ContentHTMLHeaderValue)
|
||||
ctx.WriteString("<pre>\n")
|
||||
_, err = ctx.WriteString("<pre>\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, d := range dirs {
|
||||
name := d.Name()
|
||||
if d.IsDir() {
|
||||
@@ -317,10 +320,13 @@ func FileServer(directory string, opts ...DirOptions) context.Handler {
|
||||
// part of the URL path, and not indicate the start of a query
|
||||
// string or fragment.
|
||||
url := url.URL{Path: joinPath("./"+dirName, name)} // edit here to redirect correctly, standard library misses that.
|
||||
ctx.Writef("<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
|
||||
_, err = ctx.Writef("<a href=\"%s\">%s</a>\n", url.String(), htmlReplacer.Replace(name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ctx.WriteString("</pre>\n")
|
||||
return nil
|
||||
_, err = ctx.WriteString("</pre>\n")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,6 @@ type ExecutionRules struct {
|
||||
Main ExecutionOptions
|
||||
}
|
||||
|
||||
func handlersNames(handlers context.Handlers) (names []string) {
|
||||
for _, h := range handlers {
|
||||
if h == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
names = append(names, context.HandlerName(h))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func applyExecutionRules(rules ExecutionRules, begin, done, main *context.Handlers) {
|
||||
if !rules.Begin.Force && !rules.Done.Force && !rules.Main.Force {
|
||||
return // do not proceed and spend buld-time here if nothing changed.
|
||||
|
||||
@@ -542,7 +542,7 @@ var types = map[string]string{
|
||||
func init() {
|
||||
for ext, typ := range types {
|
||||
// skip errors
|
||||
mime.AddExtensionType(ext, typ)
|
||||
_ = mime.AddExtensionType(ext, typ)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,13 +62,6 @@ func prefix(s string, prefix string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
func suffix(s string, suffix string) string {
|
||||
if !strings.HasSuffix(s, suffix) {
|
||||
return s + suffix
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func splitMethod(methodMany string) []string {
|
||||
methodMany = strings.Trim(methodMany, " ")
|
||||
return strings.Split(methodMany, " ")
|
||||
@@ -348,7 +341,7 @@ func toStringSlice(args []interface{}) (argsString []string) {
|
||||
return
|
||||
}
|
||||
|
||||
argsString = make([]string, argsSize, argsSize)
|
||||
argsString = make([]string, argsSize)
|
||||
for i, v := range args {
|
||||
if s, ok := v.(string); ok {
|
||||
argsString[i] = s
|
||||
|
||||
@@ -95,12 +95,6 @@ type trie struct {
|
||||
subdomain string
|
||||
}
|
||||
|
||||
func newTrie() *trie {
|
||||
return &trie{
|
||||
root: newTrieNode(),
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
pathSep = "/"
|
||||
pathSepB = '/'
|
||||
|
||||
Reference in New Issue
Block a user