2021-01-26 18:36:53 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2021-01-26 18:36:53 +03:00
package web
import (
"net/http"
"strings"
2021-01-30 11:55:53 +03:00
"code.gitea.io/gitea/modules/web/middleware"
2021-01-26 18:36:53 +03:00
2024-11-05 23:40:44 +03:00
"code.forgejo.org/go-chi/binding"
2023-06-18 10:59:09 +03:00
"github.com/go-chi/chi/v5"
2021-01-26 18:36:53 +03:00
)
2023-06-18 10:59:09 +03:00
// Bind binding an obj to a handler's context data
func Bind [ T any ] ( _ T ) http . HandlerFunc {
return func ( resp http . ResponseWriter , req * http . Request ) {
2022-12-12 11:09:26 +03:00
theObj := new ( T ) // create a new form obj for every request but not use obj directly
2023-06-18 10:59:09 +03:00
data := middleware . GetContextData ( req . Context ( ) )
binding . Bind ( req , theObj )
SetForm ( data , theObj )
middleware . AssignForm ( theObj , data )
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
}
2021-01-26 18:36:53 +03:00
}
// SetForm set the form object
2023-07-04 21:36:08 +03:00
func SetForm ( dataStore middleware . ContextDataStore , obj any ) {
2023-06-18 10:59:09 +03:00
dataStore . GetData ( ) [ "__form" ] = obj
2021-01-26 18:36:53 +03:00
}
// GetForm returns the validate form information
2023-07-04 21:36:08 +03:00
func GetForm ( dataStore middleware . ContextDataStore ) any {
2023-06-18 10:59:09 +03:00
return dataStore . GetData ( ) [ "__form" ]
2021-01-26 18:36:53 +03:00
}
// Route defines a route based on chi's router
type Route struct {
R chi . Router
curGroupPrefix string
2023-07-04 21:36:08 +03:00
curMiddlewares [ ] any
2021-01-26 18:36:53 +03:00
}
// NewRoute creates a new route
func NewRoute ( ) * Route {
r := chi . NewRouter ( )
2023-04-27 09:06:45 +03:00
return & Route { R : r }
2021-01-26 18:36:53 +03:00
}
// Use supports two middlewares
2023-07-04 21:36:08 +03:00
func ( r * Route ) Use ( middlewares ... any ) {
2023-04-27 09:06:45 +03:00
for _ , m := range middlewares {
2023-07-09 15:25:53 +03:00
if m != nil {
r . R . Use ( toHandlerProvider ( m ) )
}
2021-01-26 18:36:53 +03:00
}
}
// Group mounts a sub-Router along a `pattern` string.
2023-07-04 21:36:08 +03:00
func ( r * Route ) Group ( pattern string , fn func ( ) , middlewares ... any ) {
2022-01-20 20:46:10 +03:00
previousGroupPrefix := r . curGroupPrefix
previousMiddlewares := r . curMiddlewares
2021-01-26 18:36:53 +03:00
r . curGroupPrefix += pattern
r . curMiddlewares = append ( r . curMiddlewares , middlewares ... )
fn ( )
r . curGroupPrefix = previousGroupPrefix
r . curMiddlewares = previousMiddlewares
}
func ( r * Route ) getPattern ( pattern string ) string {
newPattern := r . curGroupPrefix + pattern
if ! strings . HasPrefix ( newPattern , "/" ) {
newPattern = "/" + newPattern
}
if newPattern == "/" {
return newPattern
}
return strings . TrimSuffix ( newPattern , "/" )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
func ( r * Route ) wrapMiddlewareAndHandler ( h [ ] any ) ( [ ] func ( http . Handler ) http . Handler , http . HandlerFunc ) {
2023-07-09 15:25:53 +03:00
handlerProviders := make ( [ ] func ( http . Handler ) http . Handler , 0 , len ( r . curMiddlewares ) + len ( h ) + 1 )
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
for _ , m := range r . curMiddlewares {
2023-07-09 15:25:53 +03:00
if m != nil {
handlerProviders = append ( handlerProviders , toHandlerProvider ( m ) )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
}
for _ , m := range h {
2023-07-09 15:25:53 +03:00
if h != nil {
handlerProviders = append ( handlerProviders , toHandlerProvider ( m ) )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
}
middlewares := handlerProviders [ : len ( handlerProviders ) - 1 ]
handlerFunc := handlerProviders [ len ( handlerProviders ) - 1 ] ( nil ) . ServeHTTP
2023-07-09 15:25:53 +03:00
mockPoint := RouteMockPoint ( MockAfterMiddlewares )
if mockPoint != nil {
middlewares = append ( middlewares , mockPoint )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
return middlewares , handlerFunc
}
2023-12-25 15:13:18 +03:00
// Methods adds the same handlers for multiple http "methods" (separated by ",").
// If any method is invalid, the lower level router will panic.
func ( r * Route ) Methods ( methods , pattern string , h ... any ) {
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
middlewares , handlerFunc := r . wrapMiddlewareAndHandler ( h )
fullPattern := r . getPattern ( pattern )
2023-12-25 15:13:18 +03:00
if strings . Contains ( methods , "," ) {
methods := strings . Split ( methods , "," )
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
for _ , method := range methods {
r . R . With ( middlewares ... ) . Method ( strings . TrimSpace ( method ) , fullPattern , handlerFunc )
}
} else {
2023-12-25 15:13:18 +03:00
r . R . With ( middlewares ... ) . Method ( methods , fullPattern , handlerFunc )
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
}
}
2021-01-26 18:36:53 +03:00
// Mount attaches another Route along ./pattern/*
func ( r * Route ) Mount ( pattern string , subR * Route ) {
2023-04-27 09:06:45 +03:00
subR . Use ( r . curMiddlewares ... )
2021-01-26 18:36:53 +03:00
r . R . Mount ( r . getPattern ( pattern ) , subR . R )
}
// Any delegate requests for all methods
2023-07-04 21:36:08 +03:00
func ( r * Route ) Any ( pattern string , h ... any ) {
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
middlewares , handlerFunc := r . wrapMiddlewareAndHandler ( h )
r . R . With ( middlewares ... ) . HandleFunc ( r . getPattern ( pattern ) , handlerFunc )
2021-01-26 18:36:53 +03:00
}
// Delete delegate delete method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Delete ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "DELETE" , pattern , h ... )
2021-01-26 18:36:53 +03:00
}
// Get delegate get method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Get ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "GET" , pattern , h ... )
2021-07-21 06:32:35 +03:00
}
2021-01-26 18:36:53 +03:00
// Head delegate head method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Head ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "HEAD" , pattern , h ... )
2021-01-26 18:36:53 +03:00
}
// Post delegate post method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Post ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "POST" , pattern , h ... )
2021-01-26 18:36:53 +03:00
}
// Put delegate put method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Put ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "PUT" , pattern , h ... )
2021-01-26 18:36:53 +03:00
}
// Patch delegate patch method
2023-07-04 21:36:08 +03:00
func ( r * Route ) Patch ( pattern string , h ... any ) {
2023-07-21 01:43:49 +03:00
r . Methods ( "PATCH" , pattern , h ... )
2021-01-26 18:36:53 +03:00
}
// ServeHTTP implements http.Handler
func ( r * Route ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
r . R . ServeHTTP ( w , req )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// NotFound defines a handler to respond whenever a route could not be found.
2021-01-26 18:36:53 +03:00
func ( r * Route ) NotFound ( h http . HandlerFunc ) {
r . R . NotFound ( h )
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Combo delegates requests to Combo
2023-07-04 21:36:08 +03:00
func ( r * Route ) Combo ( pattern string , h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
return & Combo { r , pattern , h }
}
// Combo represents a tiny group routes with same pattern
type Combo struct {
r * Route
pattern string
2023-07-04 21:36:08 +03:00
h [ ] any
2021-01-26 18:36:53 +03:00
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Get delegates Get method
2023-07-04 21:36:08 +03:00
func ( c * Combo ) Get ( h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
c . r . Get ( c . pattern , append ( c . h , h ... ) ... )
return c
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Post delegates Post method
2023-07-04 21:36:08 +03:00
func ( c * Combo ) Post ( h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
c . r . Post ( c . pattern , append ( c . h , h ... ) ... )
return c
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Delete delegates Delete method
2023-07-04 21:36:08 +03:00
func ( c * Combo ) Delete ( h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
c . r . Delete ( c . pattern , append ( c . h , h ... ) ... )
return c
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Put delegates Put method
2023-07-04 21:36:08 +03:00
func ( c * Combo ) Put ( h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
c . r . Put ( c . pattern , append ( c . h , h ... ) ... )
return c
}
Refactor web route (#24080)
The old code is unnecessarily complex, and has many misuses.
Old code "wraps" a lot, wrap wrap wrap, it's difficult to understand
which kind of handler is used.
The new code uses a general approach, we do not need to write all kinds
of handlers into the "wrapper", do not need to wrap them again and
again.
New code, there are only 2 concepts:
1. HandlerProvider: `func (h any) (handlerProvider func (next)
http.Handler)`, it can be used as middleware
2. Use HandlerProvider to get the final HandlerFunc, and use it for
`r.Get()`
And we can decouple the route package from context package (see the
TODO).
# FAQ
## Is `reflect` safe?
Yes, all handlers are checked during startup, see the `preCheckHandler`
comment. If any handler is wrong, developers could know it in the first
time.
## Does `reflect` affect performance?
No. https://github.com/go-gitea/gitea/pull/24080#discussion_r1164825901
1. This reflect code only runs for each web handler call, handler is far
more slower: 10ms-50ms
2. The reflect is pretty fast (comparing to other code): 0.000265ms
3. XORM has more reflect operations already
2023-04-20 21:49:06 +03:00
// Patch delegates Patch method
2023-07-04 21:36:08 +03:00
func ( c * Combo ) Patch ( h ... any ) * Combo {
2021-01-26 18:36:53 +03:00
c . r . Patch ( c . pattern , append ( c . h , h ... ) ... )
return c
}