Skip to content

Commit 4ba6d51

Browse files
committed
fix
1 parent 6db66d8 commit 4ba6d51

25 files changed

+128
-158
lines changed

cmd/web.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func runWeb(ctx *cli.Context) error {
191191
}
192192

193193
// Set up Chi routes
194-
c := routers.NormalRoutes(graceful.GetManager().HammerContext())
194+
c := routers.NormalRoutes()
195195
err := listen(c, true)
196196
<-graceful.GetManager().Done()
197197
log.Info("PID: %d Gitea Web Finished", os.Getpid())

modules/context/api.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"code.gitea.io/gitea/modules/httpcache"
2121
"code.gitea.io/gitea/modules/log"
2222
"code.gitea.io/gitea/modules/setting"
23+
"code.gitea.io/gitea/modules/web"
24+
web_types "code.gitea.io/gitea/modules/web/types"
2325

2426
"gitea.com/go-chi/cache"
2527
)
@@ -41,6 +43,12 @@ type APIContext struct {
4143
Package *Package
4244
}
4345

46+
func init() {
47+
web.RegisterResponseStatusProvider[*APIContext](func(req *http.Request) web_types.ResponseStatusProvider {
48+
return req.Context().Value(apiContextKey).(*APIContext)
49+
})
50+
}
51+
4452
// Currently, we have the following common fields in error response:
4553
// * message: the message for end users (it shouldn't be used for error type detection)
4654
// if we need to indicate some errors, we should introduce some new fields like ErrorCode or ErrorType

modules/context/base.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ func (b *Base) SetTotalCountHeader(total int64) {
9696

9797
// Written returns true if there are something sent to web browser
9898
func (b *Base) Written() bool {
99-
return b.Resp.Status() > 0
99+
return b.Resp.WrittenStatus() != 0
100+
}
101+
102+
func (b *Base) WrittenStatus() int {
103+
return b.Resp.WrittenStatus()
100104
}
101105

102106
// Status writes status code

modules/context/context.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"code.gitea.io/gitea/modules/setting"
2222
"code.gitea.io/gitea/modules/templates"
2323
"code.gitea.io/gitea/modules/translation"
24+
"code.gitea.io/gitea/modules/web"
2425
"code.gitea.io/gitea/modules/web/middleware"
26+
web_types "code.gitea.io/gitea/modules/web/types"
2527

2628
"gitea.com/go-chi/cache"
2729
"gitea.com/go-chi/session"
@@ -58,6 +60,12 @@ type Context struct {
5860
Package *Package
5961
}
6062

63+
func init() {
64+
web.RegisterResponseStatusProvider[*Context](func(req *http.Request) web_types.ResponseStatusProvider {
65+
return req.Context().Value(WebContextKey).(*Context)
66+
})
67+
}
68+
6169
// TrHTMLEscapeArgs runs ".Locale.Tr()" but pre-escapes all arguments with html.EscapeString.
6270
// This is useful if the locale message is intended to only produce HTML content.
6371
func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {

modules/context/private.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111

1212
"code.gitea.io/gitea/modules/graceful"
1313
"code.gitea.io/gitea/modules/process"
14+
"code.gitea.io/gitea/modules/web"
15+
web_types "code.gitea.io/gitea/modules/web/types"
1416
)
1517

1618
// PrivateContext represents a context for private routes
@@ -21,6 +23,12 @@ type PrivateContext struct {
2123
Repo *Repository
2224
}
2325

26+
func init() {
27+
web.RegisterResponseStatusProvider[*PrivateContext](func(req *http.Request) web_types.ResponseStatusProvider {
28+
return req.Context().Value(privateContextKey).(*PrivateContext)
29+
})
30+
}
31+
2432
// Deadline is part of the interface for context.Context and we pass this to the request context
2533
func (ctx *PrivateContext) Deadline() (deadline time.Time, ok bool) {
2634
if ctx.Override != nil {

modules/context/response.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ package context
55

66
import (
77
"net/http"
8+
9+
web_types "code.gitea.io/gitea/modules/web/types"
810
)
911

1012
// ResponseWriter represents a response writer for HTTP
1113
type ResponseWriter interface {
1214
http.ResponseWriter
1315
http.Flusher
14-
Status() int
16+
web_types.ResponseStatusProvider
17+
1518
Before(func(ResponseWriter))
16-
Size() int // used by access logger template
19+
20+
Status() int // used by access logger template
21+
Size() int // used by access logger template
1722
}
1823

1924
var _ ResponseWriter = &Response{}
@@ -46,6 +51,10 @@ func (r *Response) Write(bs []byte) (int, error) {
4651
return size, nil
4752
}
4853

54+
func (r *Response) Status() int {
55+
return r.status
56+
}
57+
4958
func (r *Response) Size() int {
5059
return r.written
5160
}
@@ -71,8 +80,8 @@ func (r *Response) Flush() {
7180
}
7281
}
7382

74-
// Status returned status code written
75-
func (r *Response) Status() int {
83+
// WrittenStatus returned status code written
84+
func (r *Response) WrittenStatus() int {
7685
return r.status
7786
}
7887

modules/test/context_tests.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ func MockContext(t *testing.T, path string) *context.Context {
3535
URL: requestURL,
3636
Form: url.Values{},
3737
}
38-
38+
req = req.WithContext(middleware.WithContextData(req.Context()))
3939
base, baseCleanUp := context.NewBaseContext(resp, req)
40-
base.Data = middleware.ContextData{}
40+
base.Data = middleware.GetContextData(req.Context())
4141
base.Locale = &translation.MockLocale{}
4242
ctx := &context.Context{
4343
Base: base,
@@ -61,9 +61,9 @@ func MockAPIContext(t *testing.T, path string) *context.APIContext {
6161
URL: requestURL,
6262
Form: url.Values{},
6363
}
64-
64+
req = req.WithContext(middleware.WithContextData(req.Context()))
6565
base, baseCleanUp := context.NewBaseContext(resp, req)
66-
base.Data = middleware.ContextData{}
66+
base.Data = middleware.GetContextData(req.Context())
6767
base.Locale = &translation.MockLocale{}
6868
ctx := &context.APIContext{Base: base}
6969
_ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later

modules/web/handler.go

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,15 @@ import (
99
"net/http"
1010
"reflect"
1111

12-
"code.gitea.io/gitea/modules/context"
1312
"code.gitea.io/gitea/modules/log"
1413
"code.gitea.io/gitea/modules/web/routing"
14+
"code.gitea.io/gitea/modules/web/types"
1515
)
1616

17-
// ResponseStatusProvider is an interface to check whether the response has been written by the handler
18-
type ResponseStatusProvider interface {
19-
Written() bool
20-
}
21-
22-
// TODO: decouple this from the context package, let the context package register these providers
23-
var argTypeProvider = map[reflect.Type]func(req *http.Request) ResponseStatusProvider{
24-
reflect.TypeOf(&context.APIContext{}): func(req *http.Request) ResponseStatusProvider { return context.GetAPIContext(req) },
25-
reflect.TypeOf(&context.Context{}): func(req *http.Request) ResponseStatusProvider { return context.GetWebContext(req) },
26-
reflect.TypeOf(&context.PrivateContext{}): func(req *http.Request) ResponseStatusProvider { return context.GetPrivateContext(req) },
27-
}
17+
var responseStatusProviders = map[reflect.Type]func(req *http.Request) types.ResponseStatusProvider{}
2818

29-
func RegisterHandleTypeProvider[T any](fn func(req *http.Request) ResponseStatusProvider) {
30-
argTypeProvider[reflect.TypeOf((*T)(nil)).Elem()] = fn
19+
func RegisterResponseStatusProvider[T any](fn func(req *http.Request) types.ResponseStatusProvider) {
20+
responseStatusProviders[reflect.TypeOf((*T)(nil)).Elem()] = fn
3121
}
3222

3323
// responseWriter is a wrapper of http.ResponseWriter, to check whether the response has been written
@@ -36,10 +26,10 @@ type responseWriter struct {
3626
status int
3727
}
3828

39-
var _ ResponseStatusProvider = (*responseWriter)(nil)
29+
var _ types.ResponseStatusProvider = (*responseWriter)(nil)
4030

41-
func (r *responseWriter) Written() bool {
42-
return r.status > 0
31+
func (r *responseWriter) WrittenStatus() int {
32+
return r.status
4333
}
4434

4535
func (r *responseWriter) Header() http.Header {
@@ -68,7 +58,7 @@ var (
6858
func preCheckHandler(fn reflect.Value, argsIn []reflect.Value) {
6959
hasStatusProvider := false
7060
for _, argIn := range argsIn {
71-
if _, hasStatusProvider = argIn.Interface().(ResponseStatusProvider); hasStatusProvider {
61+
if _, hasStatusProvider = argIn.Interface().(types.ResponseStatusProvider); hasStatusProvider {
7262
break
7363
}
7464
}
@@ -101,7 +91,7 @@ func prepareHandleArgsIn(resp http.ResponseWriter, req *http.Request, fn reflect
10191
case httpReqType:
10292
argsIn[i] = reflect.ValueOf(req)
10393
default:
104-
if argFn, ok := argTypeProvider[argTyp]; ok {
94+
if argFn, ok := responseStatusProviders[argTyp]; ok {
10595
if isPreCheck {
10696
argsIn[i] = reflect.ValueOf(&responseWriter{})
10797
} else {
@@ -129,8 +119,8 @@ func handleResponse(fn reflect.Value, ret []reflect.Value) goctx.CancelFunc {
129119

130120
func hasResponseBeenWritten(argsIn []reflect.Value) bool {
131121
for _, argIn := range argsIn {
132-
if statusProvider, ok := argIn.Interface().(ResponseStatusProvider); ok {
133-
if statusProvider.Written() {
122+
if statusProvider, ok := argIn.Interface().(types.ResponseStatusProvider); ok {
123+
if statusProvider.WrittenStatus() != 0 {
134124
return true
135125
}
136126
}
@@ -161,7 +151,7 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
161151
return http.HandlerFunc(func(respOrig http.ResponseWriter, req *http.Request) {
162152
// wrap the response writer to check whether the response has been written
163153
resp := respOrig
164-
if _, ok := resp.(ResponseStatusProvider); !ok {
154+
if _, ok := resp.(types.ResponseStatusProvider); !ok {
165155
resp = &responseWriter{respWriter: resp}
166156
}
167157

modules/web/route.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,36 @@
44
package web
55

66
import (
7+
"context"
78
"net/http"
89
"strings"
910

10-
"code.gitea.io/gitea/modules/context"
1111
"code.gitea.io/gitea/modules/web/middleware"
1212

1313
"gitea.com/go-chi/binding"
14-
chi "github.com/go-chi/chi/v5"
14+
"github.com/go-chi/chi/v5"
1515
)
1616

17-
// Bind binding an obj to a handler
18-
func Bind[T any](_ T) any {
19-
return func(ctx *context.Context) {
17+
// Bind binding an obj to a handler's context data
18+
func Bind[T any](_ T) http.HandlerFunc {
19+
return func(resp http.ResponseWriter, req *http.Request) {
2020
theObj := new(T) // create a new form obj for every request but not use obj directly
21-
binding.Bind(ctx.Req, theObj)
22-
SetForm(ctx, theObj)
23-
middleware.AssignForm(theObj, ctx.Data)
21+
binding.Bind(req, theObj)
22+
SetForm(req.Context(), theObj)
23+
middleware.AssignForm(theObj, middleware.GetContextData(req.Context()))
2424
}
2525
}
2626

2727
// SetForm set the form object
28-
func SetForm(data middleware.ContextDataStore, obj interface{}) {
29-
data.GetData()["__form"] = obj
28+
func SetForm(ctx context.Context, obj interface{}) {
29+
ctxData := middleware.GetContextData(ctx)
30+
ctxData["__form"] = obj
3031
}
3132

3233
// GetForm returns the validate form information
33-
func GetForm(data middleware.ContextDataStore) interface{} {
34-
return data.GetData()["__form"]
34+
func GetForm(ctx context.Context) interface{} {
35+
ctxData := middleware.GetContextData(ctx)
36+
return ctxData["__form"]
3537
}
3638

3739
// Route defines a route based on chi's router

modules/web/routing/logger.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"strings"
99
"time"
1010

11-
"code.gitea.io/gitea/modules/context"
1211
"code.gitea.io/gitea/modules/log"
12+
"code.gitea.io/gitea/modules/web/types"
1313
)
1414

1515
// NewLoggerHandler is a handler that will log routing to the router log taking account of
@@ -86,8 +86,8 @@ func logPrinter(logger log.Logger) func(trigger Event, record *requestRecord) {
8686
}
8787

8888
var status int
89-
if v, ok := record.responseWriter.(context.ResponseWriter); ok {
90-
status = v.Status()
89+
if v, ok := record.responseWriter.(types.ResponseStatusProvider); ok {
90+
status = v.WrittenStatus()
9191
}
9292
logf := log.Info
9393
if strings.HasPrefix(req.RequestURI, "/assets/") {

modules/web/types/response.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package types
5+
6+
// ResponseStatusProvider is an interface to get the written status in the response
7+
// Many packages need this interface, so put it in the separate package to avoid import cycle
8+
type ResponseStatusProvider interface {
9+
WrittenStatus() int
10+
}

routers/api/actions/actions.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
package actions
55

66
import (
7-
"context"
87
"net/http"
98

109
"code.gitea.io/gitea/modules/web"
1110
"code.gitea.io/gitea/routers/api/actions/ping"
1211
"code.gitea.io/gitea/routers/api/actions/runner"
1312
)
1413

15-
func Routes(_ context.Context, prefix string) *web.Route {
14+
func Routes(prefix string) *web.Route {
1615
m := web.NewRoute()
1716

1817
path, handler := ping.NewPingServiceHandler()

routers/api/actions/artifacts.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import (
8282
"code.gitea.io/gitea/modules/storage"
8383
"code.gitea.io/gitea/modules/util"
8484
"code.gitea.io/gitea/modules/web"
85+
web_types "code.gitea.io/gitea/modules/web/types"
8586
)
8687

8788
const (
@@ -102,7 +103,7 @@ type ArtifactContext struct {
102103
}
103104

104105
func init() {
105-
web.RegisterHandleTypeProvider[*ArtifactContext](func(req *http.Request) web.ResponseStatusProvider {
106+
web.RegisterResponseStatusProvider[*ArtifactContext](func(req *http.Request) web_types.ResponseStatusProvider {
106107
return req.Context().Value(artifactContextKey).(*ArtifactContext)
107108
})
108109
}

routers/api/packages/api.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package packages
55

66
import (
7-
gocontext "context"
87
"net/http"
98
"regexp"
109
"strings"
@@ -96,7 +95,7 @@ func verifyAuth(r *web.Route, authMethods []auth.Method) {
9695

9796
// CommonRoutes provide endpoints for most package managers (except containers - see below)
9897
// These are mounted on `/api/packages` (not `/api/v1/packages`)
99-
func CommonRoutes(ctx gocontext.Context) *web.Route {
98+
func CommonRoutes() *web.Route {
10099
r := web.NewRoute()
101100

102101
r.Use(context.PackageContexter())
@@ -590,7 +589,7 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
590589
// ContainerRoutes provides endpoints that implement the OCI API to serve containers
591590
// These have to be mounted on `/v2/...` to comply with the OCI spec:
592591
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md
593-
func ContainerRoutes(ctx gocontext.Context) *web.Route {
592+
func ContainerRoutes() *web.Route {
594593
r := web.NewRoute()
595594

596595
r.Use(context.PackageContexter())

0 commit comments

Comments
 (0)