2021-01-26 23:36:53 +08:00
// Copyright 2021 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2021-01-26 23:36:53 +08:00
package web
import (
"bytes"
"net/http"
"net/http/httptest"
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-21 02:49:06 +08:00
"strconv"
2021-01-26 23:36:53 +08:00
"testing"
2024-06-18 07:28:47 +08:00
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/test"
2021-10-14 10:50:23 +08:00
chi "github.com/go-chi/chi/v5"
2021-01-26 23:36:53 +08:00
"github.com/stretchr/testify/assert"
)
func TestRoute1 ( t * testing . T ) {
buff := bytes . NewBufferString ( "" )
recorder := httptest . NewRecorder ( )
recorder . Body = buff
2024-06-19 06:32:45 +08:00
r := NewRouter ( )
2021-01-26 23:36:53 +08:00
r . Get ( "/{username}/{reponame}/{type:issues|pulls}" , func ( resp http . ResponseWriter , req * http . Request ) {
username := chi . URLParam ( req , "username" )
assert . EqualValues ( t , "gitea" , username )
reponame := chi . URLParam ( req , "reponame" )
assert . EqualValues ( t , "gitea" , reponame )
tp := chi . URLParam ( req , "type" )
assert . EqualValues ( t , "issues" , tp )
} )
req , err := http . NewRequest ( "GET" , "http://localhost:8000/gitea/gitea/issues" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
}
func TestRoute2 ( t * testing . T ) {
buff := bytes . NewBufferString ( "" )
recorder := httptest . NewRecorder ( )
recorder . Body = buff
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-21 02:49:06 +08:00
hit := - 1
2021-01-26 23:36:53 +08:00
2024-06-19 06:32:45 +08:00
r := NewRouter ( )
2021-01-26 23:36:53 +08:00
r . Group ( "/{username}/{reponame}" , func ( ) {
r . Group ( "" , func ( ) {
r . Get ( "/{type:issues|pulls}" , func ( resp http . ResponseWriter , req * http . Request ) {
username := chi . URLParam ( req , "username" )
assert . EqualValues ( t , "gitea" , username )
reponame := chi . URLParam ( req , "reponame" )
assert . EqualValues ( t , "gitea" , reponame )
tp := chi . URLParam ( req , "type" )
assert . EqualValues ( t , "issues" , tp )
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-21 02:49:06 +08:00
hit = 0
2021-01-26 23:36:53 +08:00
} )
r . Get ( "/{type:issues|pulls}/{index}" , func ( resp http . ResponseWriter , req * http . Request ) {
username := chi . URLParam ( req , "username" )
assert . EqualValues ( t , "gitea" , username )
reponame := chi . URLParam ( req , "reponame" )
assert . EqualValues ( t , "gitea" , reponame )
tp := chi . URLParam ( req , "type" )
assert . EqualValues ( t , "issues" , tp )
index := chi . URLParam ( req , "index" )
assert . EqualValues ( t , "1" , index )
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-21 02:49:06 +08:00
hit = 1
2021-01-26 23:36:53 +08:00
} )
} , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
if stop , err := strconv . Atoi ( req . FormValue ( "stop" ) ) ; err == nil {
hit = stop
resp . WriteHeader ( http . StatusOK )
}
2021-01-26 23:36:53 +08:00
} )
r . Group ( "/issues/{index}" , func ( ) {
r . Get ( "/view" , func ( resp http . ResponseWriter , req * http . Request ) {
username := chi . URLParam ( req , "username" )
assert . EqualValues ( t , "gitea" , username )
reponame := chi . URLParam ( req , "reponame" )
assert . EqualValues ( t , "gitea" , reponame )
index := chi . URLParam ( req , "index" )
assert . EqualValues ( t , "1" , index )
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-21 02:49:06 +08:00
hit = 2
2021-01-26 23:36:53 +08:00
} )
} )
} )
req , err := http . NewRequest ( "GET" , "http://localhost:8000/gitea/gitea/issues" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 0 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "GET" , "http://localhost:8000/gitea/gitea/issues/1" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 1 , hit )
req , err = http . NewRequest ( "GET" , "http://localhost:8000/gitea/gitea/issues/1?stop=100" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
assert . EqualValues ( t , 100 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "GET" , "http://localhost:8000/gitea/gitea/issues/1/view" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 2 , hit )
2021-01-26 23:36:53 +08:00
}
func TestRoute3 ( t * testing . T ) {
buff := bytes . NewBufferString ( "" )
recorder := httptest . NewRecorder ( )
recorder . Body = buff
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-21 02:49:06 +08:00
hit := - 1
2021-01-26 23:36:53 +08:00
2024-06-19 06:32:45 +08:00
m := NewRouter ( )
r := NewRouter ( )
2021-01-26 23:36:53 +08:00
r . Mount ( "/api/v1" , m )
m . Group ( "/repos" , func ( ) {
m . Group ( "/{username}/{reponame}" , func ( ) {
m . Group ( "/branch_protections" , func ( ) {
m . Get ( "" , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
hit = 0
2021-01-26 23:36:53 +08:00
} )
m . Post ( "" , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
hit = 1
2021-01-26 23:36:53 +08:00
} )
m . Group ( "/{name}" , func ( ) {
m . Get ( "" , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
hit = 2
2021-01-26 23:36:53 +08:00
} )
m . Patch ( "" , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
hit = 3
2021-01-26 23:36:53 +08:00
} )
m . Delete ( "" , func ( resp http . ResponseWriter , req * http . Request ) {
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-21 02:49:06 +08:00
hit = 4
2021-01-26 23:36:53 +08:00
} )
} )
} )
} )
} )
req , err := http . NewRequest ( "GET" , "http://localhost:8000/api/v1/repos/gitea/gitea/branch_protections" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 0 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "POST" , "http://localhost:8000/api/v1/repos/gitea/gitea/branch_protections" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code , http . StatusOK )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 1 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "GET" , "http://localhost:8000/api/v1/repos/gitea/gitea/branch_protections/master" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 2 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "PATCH" , "http://localhost:8000/api/v1/repos/gitea/gitea/branch_protections/master" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 3 , hit )
2021-01-26 23:36:53 +08:00
req , err = http . NewRequest ( "DELETE" , "http://localhost:8000/api/v1/repos/gitea/gitea/branch_protections/master" , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . EqualValues ( t , http . StatusOK , recorder . Code )
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-21 02:49:06 +08:00
assert . EqualValues ( t , 4 , hit )
2021-01-26 23:36:53 +08:00
}
2024-06-18 07:28:47 +08:00
func TestRouteNormalizePath ( t * testing . T ) {
type paths struct {
EscapedPath , RawPath , Path string
}
testPath := func ( reqPath string , expectedPaths paths ) {
recorder := httptest . NewRecorder ( )
recorder . Body = bytes . NewBuffer ( nil )
actualPaths := paths { EscapedPath : "(none)" , RawPath : "(none)" , Path : "(none)" }
2024-06-19 06:32:45 +08:00
r := NewRouter ( )
2024-06-18 07:28:47 +08:00
r . Get ( "/*" , func ( resp http . ResponseWriter , req * http . Request ) {
actualPaths . EscapedPath = req . URL . EscapedPath ( )
actualPaths . RawPath = req . URL . RawPath
actualPaths . Path = req . URL . Path
} )
req , err := http . NewRequest ( "GET" , reqPath , nil )
assert . NoError ( t , err )
r . ServeHTTP ( recorder , req )
assert . Equal ( t , expectedPaths , actualPaths , "req path = %q" , reqPath )
}
// RawPath could be empty if the EscapedPath is the same as escape(Path) and it is already normalized
testPath ( "/" , paths { EscapedPath : "/" , RawPath : "" , Path : "/" } )
testPath ( "//" , paths { EscapedPath : "/" , RawPath : "/" , Path : "/" } )
testPath ( "/%2f" , paths { EscapedPath : "/%2f" , RawPath : "/%2f" , Path : "//" } )
testPath ( "///a//b/" , paths { EscapedPath : "/a/b" , RawPath : "/a/b" , Path : "/a/b" } )
defer test . MockVariableValue ( & setting . UseSubURLPath , true ) ( )
defer test . MockVariableValue ( & setting . AppSubURL , "/sub-path" ) ( )
testPath ( "/" , paths { EscapedPath : "(none)" , RawPath : "(none)" , Path : "(none)" } ) // 404
testPath ( "/sub-path" , paths { EscapedPath : "/" , RawPath : "/" , Path : "/" } )
testPath ( "/sub-path/" , paths { EscapedPath : "/" , RawPath : "/" , Path : "/" } )
testPath ( "/sub-path//a/b///" , paths { EscapedPath : "/a/b" , RawPath : "/a/b" , Path : "/a/b" } )
testPath ( "/sub-path/%2f/" , paths { EscapedPath : "/%2f" , RawPath : "/%2f" , Path : "//" } )
// "/v2" is special for OCI container registry, it should always be in the root of the site
testPath ( "/v2" , paths { EscapedPath : "/v2" , RawPath : "/v2" , Path : "/v2" } )
testPath ( "/v2/" , paths { EscapedPath : "/v2" , RawPath : "/v2" , Path : "/v2" } )
testPath ( "/v2/%2f" , paths { EscapedPath : "/v2/%2f" , RawPath : "/v2/%2f" , Path : "/v2//" } )
}