diff --git a/modules/auth/sso/interface.go b/modules/auth/sso/interface.go
index 7efe79a69c..9b1472f2b3 100644
--- a/modules/auth/sso/interface.go
+++ b/modules/auth/sso/interface.go
@@ -8,12 +8,12 @@ import (
 	"net/http"
 
 	"code.gitea.io/gitea/models"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/session"
+	"code.gitea.io/gitea/modules/web/middleware"
 )
 
 // DataStore represents a data store
-type DataStore middlewares.DataStore
+type DataStore middleware.DataStore
 
 // SessionStore represents a session store
 type SessionStore session.Store
diff --git a/modules/auth/sso/oauth2.go b/modules/auth/sso/oauth2.go
index b6f59dc924..fcd6845b38 100644
--- a/modules/auth/sso/oauth2.go
+++ b/modules/auth/sso/oauth2.go
@@ -12,8 +12,8 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/timeutil"
+	"code.gitea.io/gitea/modules/web/middleware"
 )
 
 // Ensure the struct implements the interface.
@@ -122,7 +122,7 @@ func (o *OAuth2) VerifyAuthData(req *http.Request, w http.ResponseWriter, store
 		return nil
 	}
 
-	if middlewares.IsInternalPath(req) || !middlewares.IsAPIPath(req) && !isAttachmentDownload(req) {
+	if middleware.IsInternalPath(req) || !middleware.IsAPIPath(req) && !isAttachmentDownload(req) {
 		return nil
 	}
 
diff --git a/modules/auth/sso/sso.go b/modules/auth/sso/sso.go
index f3788e4c9d..437bf3af7a 100644
--- a/modules/auth/sso/sso.go
+++ b/modules/auth/sso/sso.go
@@ -13,8 +13,8 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/web/middleware"
 )
 
 // ssoMethods contains the list of SSO authentication plugins in the order they are expected to be
@@ -121,7 +121,7 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
 	// Language setting of the user overwrites the one previously set
 	// If the user does not have a locale set, we save the current one.
 	if len(user.Language) == 0 {
-		lc := middlewares.Locale(resp, req)
+		lc := middleware.Locale(resp, req)
 		user.Language = lc.Language()
 		if err := models.UpdateUserCols(user, "language"); err != nil {
 			log.Error(fmt.Sprintf("Error updating user language [user: %d, locale: %s]", user.ID, user.Language))
@@ -129,8 +129,8 @@ func handleSignIn(resp http.ResponseWriter, req *http.Request, sess SessionStore
 		}
 	}
 
-	middlewares.SetCookie(resp, "lang", user.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+	middleware.SetCookie(resp, "lang", user.Language, nil, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
 
 	// Clear whatever CSRF has right now, force to generate a new one
-	middlewares.SetCookie(resp, setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
+	middleware.SetCookie(resp, setting.CSRFCookieName, "", -1, setting.AppSubURL, setting.SessionConfig.Domain, setting.SessionConfig.Secure, true)
 }
diff --git a/modules/auth/sso/sspi_windows.go b/modules/auth/sso/sspi_windows.go
index 10571d67c5..46f7ad9d97 100644
--- a/modules/auth/sso/sspi_windows.go
+++ b/modules/auth/sso/sspi_windows.go
@@ -12,9 +12,9 @@ import (
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/base"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	gouuid "github.com/google/uuid"
 	"github.com/quasoft/websspi"
@@ -136,7 +136,7 @@ func (s *SSPI) VerifyAuthData(req *http.Request, w http.ResponseWriter, store Da
 	}
 
 	// Make sure requests to API paths and PWA resources do not create a new session
-	if !middlewares.IsAPIPath(req) && !isAttachmentDownload(req) {
+	if !middleware.IsAPIPath(req) && !isAttachmentDownload(req) {
 		handleSignIn(w, req, sess, user)
 	}
 
@@ -167,9 +167,9 @@ func (s *SSPI) shouldAuthenticate(req *http.Request) (shouldAuth bool) {
 		} else if req.FormValue("auth_with_sspi") == "1" {
 			shouldAuth = true
 		}
-	} else if middlewares.IsInternalPath(req) {
+	} else if middleware.IsInternalPath(req) {
 		shouldAuth = false
-	} else if middlewares.IsAPIPath(req) || isAttachmentDownload(req) {
+	} else if middleware.IsAPIPath(req) || isAttachmentDownload(req) {
 		shouldAuth = true
 	}
 	return
diff --git a/modules/context/api.go b/modules/context/api.go
index aab6905fd1..4757c2eeb4 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -17,8 +17,8 @@ import (
 	"code.gitea.io/gitea/modules/auth/sso"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/session"
 )
@@ -224,7 +224,7 @@ func APIContexter() func(http.Handler) http.Handler {
 	return func(next http.Handler) http.Handler {
 
 		return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
-			var locale = middlewares.Locale(w, req)
+			var locale = middleware.Locale(w, req)
 			var ctx = APIContext{
 				Context: &Context{
 					Resp:    NewResponse(w),
diff --git a/modules/context/context.go b/modules/context/context.go
index 4fd0861df0..bc48c1415d 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -26,11 +26,11 @@ import (
 	"code.gitea.io/gitea/modules/base"
 	mc "code.gitea.io/gitea/modules/cache"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
 	"code.gitea.io/gitea/modules/translation"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/cache"
 	"gitea.com/go-chi/session"
@@ -56,7 +56,7 @@ type Context struct {
 	translation.Locale
 	Cache   cache.Cache
 	csrf    CSRF
-	Flash   *middlewares.Flash
+	Flash   *middleware.Flash
 	Session session.Store
 
 	Link        string // current request URL
@@ -206,7 +206,7 @@ func (ctx *Context) HTMLString(name string, data interface{}) (string, error) {
 // RenderWithErr used for page has form validation but need to prompt error to users.
 func (ctx *Context) RenderWithErr(msg string, tpl base.TplName, form interface{}) {
 	if form != nil {
-		middlewares.AssignForm(form, ctx.Data)
+		middleware.AssignForm(form, ctx.Data)
 	}
 	ctx.Flash.ErrorMsg = msg
 	ctx.Data["Flash"] = ctx.Flash
@@ -384,12 +384,12 @@ func (ctx *Context) Redirect(location string, status ...int) {
 
 // SetCookie set cookies to web browser
 func (ctx *Context) SetCookie(name string, value string, others ...interface{}) {
-	middlewares.SetCookie(ctx.Resp, name, value, others...)
+	middleware.SetCookie(ctx.Resp, name, value, others...)
 }
 
 // GetCookie returns given cookie value from request header.
 func (ctx *Context) GetCookie(name string) string {
-	return middlewares.GetCookie(ctx.Req, name)
+	return middleware.GetCookie(ctx.Req, name)
 }
 
 // GetSuperSecureCookie returns given cookie value from request header with secret string.
@@ -496,10 +496,10 @@ func GetContext(req *http.Request) *Context {
 
 // SignedUserName returns signed user's name via context
 func SignedUserName(req *http.Request) string {
-	if middlewares.IsInternalPath(req) {
+	if middleware.IsInternalPath(req) {
 		return ""
 	}
-	if middlewares.IsAPIPath(req) {
+	if middleware.IsAPIPath(req) {
 		ctx, ok := req.Context().Value(apiContextKey).(*APIContext)
 		if ok {
 			v := ctx.Data["SignedUserName"]
@@ -539,7 +539,7 @@ func Contexter() func(next http.Handler) http.Handler {
 
 	return func(next http.Handler) http.Handler {
 		return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
-			var locale = middlewares.Locale(resp, req)
+			var locale = middleware.Locale(resp, req)
 			var startTime = time.Now()
 			var link = setting.AppSubURL + strings.TrimSuffix(req.URL.EscapedPath(), "/")
 			var ctx = Context{
@@ -567,7 +567,7 @@ func Contexter() func(next http.Handler) http.Handler {
 			flashCookie := ctx.GetCookie("macaron_flash")
 			vals, _ := url.ParseQuery(flashCookie)
 			if len(vals) > 0 {
-				f := &middlewares.Flash{
+				f := &middleware.Flash{
 					DataStore:  &ctx,
 					Values:     vals,
 					ErrorMsg:   vals.Get("error"),
@@ -578,7 +578,7 @@ func Contexter() func(next http.Handler) http.Handler {
 				ctx.Data["Flash"] = f
 			}
 
-			f := &middlewares.Flash{
+			f := &middleware.Flash{
 				DataStore:  &ctx,
 				Values:     url.Values{},
 				ErrorMsg:   "",
@@ -588,11 +588,11 @@ func Contexter() func(next http.Handler) http.Handler {
 			}
 			ctx.Resp.Before(func(resp ResponseWriter) {
 				if flash := f.Encode(); len(flash) > 0 {
-					middlewares.SetCookie(resp, "macaron_flash", flash, 0,
+					middleware.SetCookie(resp, "macaron_flash", flash, 0,
 						setting.SessionConfig.CookiePath,
-						middlewares.Domain(setting.SessionConfig.Domain),
-						middlewares.HTTPOnly(true),
-						middlewares.Secure(setting.SessionConfig.Secure),
+						middleware.Domain(setting.SessionConfig.Domain),
+						middleware.HTTPOnly(true),
+						middleware.Secure(setting.SessionConfig.Secure),
 						//middlewares.SameSite(opt.SameSite), FIXME: we need a samesite config
 					)
 					return
@@ -600,10 +600,10 @@ func Contexter() func(next http.Handler) http.Handler {
 
 				ctx.SetCookie("macaron_flash", "", -1,
 					setting.SessionConfig.CookiePath,
-					middlewares.Domain(setting.SessionConfig.Domain),
-					middlewares.HTTPOnly(true),
-					middlewares.Secure(setting.SessionConfig.Secure),
-					//middlewares.SameSite(), FIXME: we need a samesite config
+					middleware.Domain(setting.SessionConfig.Domain),
+					middleware.HTTPOnly(true),
+					middleware.Secure(setting.SessionConfig.Secure),
+					//middleware.SameSite(), FIXME: we need a samesite config
 				)
 			})
 
diff --git a/modules/forms/admin.go b/modules/forms/admin.go
index 09ad420e15..2e6bbaf172 100644
--- a/modules/forms/admin.go
+++ b/modules/forms/admin.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 )
@@ -27,7 +27,7 @@ type AdminCreateUserForm struct {
 // Validate validates form fields
 func (f *AdminCreateUserForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AdminEditUserForm form for admin to create user
@@ -54,7 +54,7 @@ type AdminEditUserForm struct {
 // Validate validates form fields
 func (f *AdminEditUserForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AdminDashboardForm form for admin dashboard operations
@@ -66,5 +66,5 @@ type AdminDashboardForm struct {
 // Validate validates form fields
 func (f *AdminDashboardForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/auth_form.go b/modules/forms/auth_form.go
index 10d0f82959..7cf6b9fcd5 100644
--- a/modules/forms/auth_form.go
+++ b/modules/forms/auth_form.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 )
@@ -71,5 +71,5 @@ type AuthenticationForm struct {
 // Validate validates fields
 func (f *AuthenticationForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/org.go b/modules/forms/org.go
index 513f80768f..3b994770fd 100644
--- a/modules/forms/org.go
+++ b/modules/forms/org.go
@@ -10,8 +10,8 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 )
@@ -33,7 +33,7 @@ type CreateOrgForm struct {
 // Validate validates the fields
 func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // UpdateOrgSettingForm form for updating organization settings
@@ -51,7 +51,7 @@ type UpdateOrgSettingForm struct {
 // Validate validates the fields
 func (f *UpdateOrgSettingForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ___________
@@ -74,5 +74,5 @@ type CreateTeamForm struct {
 // Validate validates the fields
 func (f *CreateTeamForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/repo_branch_form.go b/modules/forms/repo_branch_form.go
index afb7f8d4f0..5c631f20d4 100644
--- a/modules/forms/repo_branch_form.go
+++ b/modules/forms/repo_branch_form.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 )
@@ -21,5 +21,5 @@ type NewBranchForm struct {
 // Validate validates the fields
 func (f *NewBranchForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/repo_form.go b/modules/forms/repo_form.go
index 4d37ab072b..ac968a1dd5 100644
--- a/modules/forms/repo_form.go
+++ b/modules/forms/repo_form.go
@@ -13,10 +13,10 @@ import (
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/modules/web/middleware"
 	"code.gitea.io/gitea/routers/utils"
 
 	"gitea.com/go-chi/binding"
@@ -56,7 +56,7 @@ type CreateRepoForm struct {
 // Validate validates the fields
 func (f *CreateRepoForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // MigrateRepoForm form for migrating repository
@@ -87,7 +87,7 @@ type MigrateRepoForm struct {
 // Validate validates the fields
 func (f *MigrateRepoForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ParseRemoteAddr checks if given remote address is valid,
@@ -172,7 +172,7 @@ type RepoSettingForm struct {
 // Validate validates the fields
 func (f *RepoSettingForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // __________                             .__
@@ -209,7 +209,7 @@ type ProtectBranchForm struct {
 // Validate validates the fields
 func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 //  __      __      ___.   .__    .__            __
@@ -271,7 +271,7 @@ type NewWebhookForm struct {
 // Validate validates the fields
 func (f *NewWebhookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewGogshookForm form for creating gogs hook
@@ -285,7 +285,7 @@ type NewGogshookForm struct {
 // Validate validates the fields
 func (f *NewGogshookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewSlackHookForm form for creating slack hook
@@ -301,7 +301,7 @@ type NewSlackHookForm struct {
 // Validate validates the fields
 func (f *NewSlackHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // HasInvalidChannel validates the channel name is in the right format
@@ -320,7 +320,7 @@ type NewDiscordHookForm struct {
 // Validate validates the fields
 func (f *NewDiscordHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewDingtalkHookForm form for creating dingtalk hook
@@ -332,7 +332,7 @@ type NewDingtalkHookForm struct {
 // Validate validates the fields
 func (f *NewDingtalkHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewTelegramHookForm form for creating telegram hook
@@ -345,7 +345,7 @@ type NewTelegramHookForm struct {
 // Validate validates the fields
 func (f *NewTelegramHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewMatrixHookForm form for creating Matrix hook
@@ -360,7 +360,7 @@ type NewMatrixHookForm struct {
 // Validate validates the fields
 func (f *NewMatrixHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewMSTeamsHookForm form for creating MS Teams hook
@@ -372,7 +372,7 @@ type NewMSTeamsHookForm struct {
 // Validate validates the fields
 func (f *NewMSTeamsHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewFeishuHookForm form for creating feishu hook
@@ -384,7 +384,7 @@ type NewFeishuHookForm struct {
 // Validate validates the fields
 func (f *NewFeishuHookForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // .___
@@ -410,7 +410,7 @@ type CreateIssueForm struct {
 // Validate validates the fields
 func (f *CreateIssueForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // CreateCommentForm form for creating comment
@@ -423,7 +423,7 @@ type CreateCommentForm struct {
 // Validate validates the fields
 func (f *CreateCommentForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ReactionForm form for adding and removing reaction
@@ -434,7 +434,7 @@ type ReactionForm struct {
 // Validate validates the fields
 func (f *ReactionForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // IssueLockForm form for locking an issue
@@ -445,7 +445,7 @@ type IssueLockForm struct {
 // Validate validates the fields
 func (i *IssueLockForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, i, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, i, ctx.Locale)
 }
 
 // HasValidReason checks to make sure that the reason submitted in
@@ -510,7 +510,7 @@ type CreateMilestoneForm struct {
 // Validate validates the fields
 func (f *CreateMilestoneForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // .____          ___.          .__
@@ -531,7 +531,7 @@ type CreateLabelForm struct {
 // Validate validates the fields
 func (f *CreateLabelForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // InitializeLabelsForm form for initializing labels
@@ -542,7 +542,7 @@ type InitializeLabelsForm struct {
 // Validate validates the fields
 func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // __________      .__  .__    __________                                     __
@@ -566,7 +566,7 @@ type MergePullRequestForm struct {
 // Validate validates the fields
 func (f *MergePullRequestForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // CodeCommentForm form for adding code comments for PRs
@@ -584,7 +584,7 @@ type CodeCommentForm struct {
 // Validate validates the fields
 func (f *CodeCommentForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // SubmitReviewForm for submitting a finished code review
@@ -597,7 +597,7 @@ type SubmitReviewForm struct {
 // Validate validates the fields
 func (f *SubmitReviewForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ReviewType will return the corresponding reviewtype for type
@@ -643,7 +643,7 @@ type NewReleaseForm struct {
 // Validate validates the fields
 func (f *NewReleaseForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // EditReleaseForm form for changing release
@@ -658,7 +658,7 @@ type EditReleaseForm struct {
 // Validate validates the fields
 func (f *EditReleaseForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 //  __      __.__ __   .__
@@ -679,7 +679,7 @@ type NewWikiForm struct {
 // FIXME: use code generation to generate this method.
 func (f *NewWikiForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ___________    .___.__  __
@@ -704,7 +704,7 @@ type EditRepoFileForm struct {
 // Validate validates the fields
 func (f *EditRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // EditPreviewDiffForm form for changing preview diff
@@ -715,7 +715,7 @@ type EditPreviewDiffForm struct {
 // Validate validates the fields
 func (f *EditPreviewDiffForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 //  ____ ___        .__                    .___
@@ -740,7 +740,7 @@ type UploadRepoFileForm struct {
 // Validate validates the fields
 func (f *UploadRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // RemoveUploadFileForm form for removing uploaded file
@@ -751,7 +751,7 @@ type RemoveUploadFileForm struct {
 // Validate validates the fields
 func (f *RemoveUploadFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ________         .__          __
@@ -774,7 +774,7 @@ type DeleteRepoFileForm struct {
 // Validate validates the fields
 func (f *DeleteRepoFileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ___________.__                 ___________                     __
@@ -793,7 +793,7 @@ type AddTimeManuallyForm struct {
 // Validate validates the fields
 func (f *AddTimeManuallyForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // SaveTopicForm form for save topics for repository
@@ -809,5 +809,5 @@ type DeadlineForm struct {
 // Validate validates the fields
 func (f *DeadlineForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/user_form.go b/modules/forms/user_form.go
index e3090f9ae5..af36628c30 100644
--- a/modules/forms/user_form.go
+++ b/modules/forms/user_form.go
@@ -11,8 +11,8 @@ import (
 	"strings"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 )
@@ -69,7 +69,7 @@ type InstallForm struct {
 // Validate validates the fields
 func (f *InstallForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 //    _____   ____ _________________ ___
@@ -92,7 +92,7 @@ type RegisterForm struct {
 // Validate validates the fields
 func (f *RegisterForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // IsEmailDomainWhitelisted validates that the email address
@@ -130,7 +130,7 @@ type MustChangePasswordForm struct {
 // Validate validates the fields
 func (f *MustChangePasswordForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // SignInForm form for signing in with user/password
@@ -144,7 +144,7 @@ type SignInForm struct {
 // Validate validates the fields
 func (f *SignInForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AuthorizationForm form for authorizing oauth2 clients
@@ -164,7 +164,7 @@ type AuthorizationForm struct {
 // Validate validates the fields
 func (f *AuthorizationForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // GrantApplicationForm form for authorizing oauth2 clients
@@ -179,7 +179,7 @@ type GrantApplicationForm struct {
 // Validate validates the fields
 func (f *GrantApplicationForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AccessTokenForm for issuing access tokens from authorization codes or refresh tokens
@@ -198,7 +198,7 @@ type AccessTokenForm struct {
 // Validate validates the fields
 func (f *AccessTokenForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 //   __________________________________________.___ _______    ________  _________
@@ -223,7 +223,7 @@ type UpdateProfileForm struct {
 // Validate validates the fields
 func (f *UpdateProfileForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // Avatar types
@@ -243,7 +243,7 @@ type AvatarForm struct {
 // Validate validates the fields
 func (f *AvatarForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AddEmailForm form for adding new email
@@ -254,7 +254,7 @@ type AddEmailForm struct {
 // Validate validates the fields
 func (f *AddEmailForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // UpdateThemeForm form for updating a users' theme
@@ -265,7 +265,7 @@ type UpdateThemeForm struct {
 // Validate validates the field
 func (f *UpdateThemeForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // IsThemeExists checks if the theme is a theme available in the config.
@@ -292,7 +292,7 @@ type ChangePasswordForm struct {
 // Validate validates the fields
 func (f *ChangePasswordForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AddOpenIDForm is for changing openid uri
@@ -303,7 +303,7 @@ type AddOpenIDForm struct {
 // Validate validates the fields
 func (f *AddOpenIDForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // AddKeyForm form for adding SSH/GPG key
@@ -317,7 +317,7 @@ type AddKeyForm struct {
 // Validate validates the fields
 func (f *AddKeyForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // NewAccessTokenForm form for creating access token
@@ -328,7 +328,7 @@ type NewAccessTokenForm struct {
 // Validate validates the fields
 func (f *NewAccessTokenForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // EditOAuth2ApplicationForm form for editing oauth2 applications
@@ -340,7 +340,7 @@ type EditOAuth2ApplicationForm struct {
 // Validate validates the fields
 func (f *EditOAuth2ApplicationForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // TwoFactorAuthForm for logging in with 2FA token.
@@ -351,7 +351,7 @@ type TwoFactorAuthForm struct {
 // Validate validates the fields
 func (f *TwoFactorAuthForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // TwoFactorScratchAuthForm for logging in with 2FA scratch token.
@@ -362,7 +362,7 @@ type TwoFactorScratchAuthForm struct {
 // Validate validates the fields
 func (f *TwoFactorScratchAuthForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // U2FRegistrationForm for reserving an U2F name
@@ -373,7 +373,7 @@ type U2FRegistrationForm struct {
 // Validate validates the fields
 func (f *U2FRegistrationForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // U2FDeleteForm for deleting U2F keys
@@ -384,5 +384,5 @@ type U2FDeleteForm struct {
 // Validate validates the fields
 func (f *U2FDeleteForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/forms/user_form_auth_openid.go b/modules/forms/user_form_auth_openid.go
index 06601d7e15..b34f9dcc97 100644
--- a/modules/forms/user_form_auth_openid.go
+++ b/modules/forms/user_form_auth_openid.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 	"gitea.com/go-chi/binding"
 )
 
@@ -21,7 +21,7 @@ type SignInOpenIDForm struct {
 // Validate validates the fields
 func (f *SignInOpenIDForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // SignUpOpenIDForm form for signin up with OpenID
@@ -35,7 +35,7 @@ type SignUpOpenIDForm struct {
 // Validate validates the fields
 func (f *SignUpOpenIDForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
 // ConnectOpenIDForm form for connecting an existing account to an OpenID URI
@@ -47,5 +47,5 @@ type ConnectOpenIDForm struct {
 // Validate validates the fields
 func (f *ConnectOpenIDForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
 	ctx := context.GetContext(req)
-	return middlewares.Validate(errs, ctx.Data, f, ctx.Locale)
+	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go
index e219a8e56a..a15c74d828 100644
--- a/modules/test/context_tests.go
+++ b/modules/test/context_tests.go
@@ -16,7 +16,7 @@ import (
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/git"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"github.com/go-chi/chi"
 	"github.com/stretchr/testify/assert"
@@ -29,7 +29,7 @@ func MockContext(t *testing.T, path string) *context.Context {
 	var ctx = context.Context{
 		Render: &mockRender{},
 		Data:   make(map[string]interface{}),
-		Flash: &middlewares.Flash{
+		Flash: &middleware.Flash{
 			Values: make(url.Values),
 		},
 		Resp:   context.NewResponse(resp),
diff --git a/modules/middlewares/binding.go b/modules/web/middleware/binding.go
similarity index 99%
rename from modules/middlewares/binding.go
rename to modules/web/middleware/binding.go
index 1dabdbb62e..cd418c9792 100644
--- a/modules/middlewares/binding.go
+++ b/modules/web/middleware/binding.go
@@ -3,7 +3,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 import (
 	"reflect"
diff --git a/modules/middlewares/cookie.go b/modules/web/middleware/cookie.go
similarity index 99%
rename from modules/middlewares/cookie.go
rename to modules/web/middleware/cookie.go
index d18541833f..83e365f9c4 100644
--- a/modules/middlewares/cookie.go
+++ b/modules/web/middleware/cookie.go
@@ -3,7 +3,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 import (
 	"net/http"
diff --git a/modules/middlewares/data.go b/modules/web/middleware/data.go
similarity index 92%
rename from modules/middlewares/data.go
rename to modules/web/middleware/data.go
index 2690289362..7de686498a 100644
--- a/modules/middlewares/data.go
+++ b/modules/web/middleware/data.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 // DataStore represents a data store
 type DataStore interface {
diff --git a/modules/middlewares/flash.go b/modules/web/middleware/flash.go
similarity index 98%
rename from modules/middlewares/flash.go
rename to modules/web/middleware/flash.go
index 732e1c76ea..cd9b089b94 100644
--- a/modules/middlewares/flash.go
+++ b/modules/web/middleware/flash.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 import "net/url"
 
diff --git a/modules/middlewares/locale.go b/modules/web/middleware/locale.go
similarity index 98%
rename from modules/middlewares/locale.go
rename to modules/web/middleware/locale.go
index 21980ad486..449095f611 100644
--- a/modules/middlewares/locale.go
+++ b/modules/web/middleware/locale.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 import (
 	"net/http"
diff --git a/modules/middlewares/request.go b/modules/web/middleware/request.go
similarity index 96%
rename from modules/middlewares/request.go
rename to modules/web/middleware/request.go
index aa3d60be28..f620da5eea 100644
--- a/modules/middlewares/request.go
+++ b/modules/web/middleware/request.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a MIT-style
 // license that can be found in the LICENSE file.
 
-package middlewares
+package middleware
 
 import (
 	"net/http"
diff --git a/modules/web/route.go b/modules/web/route.go
index 701b3beed2..59e22c5be1 100644
--- a/modules/web/route.go
+++ b/modules/web/route.go
@@ -11,7 +11,7 @@ import (
 	"strings"
 
 	"code.gitea.io/gitea/modules/context"
-	"code.gitea.io/gitea/modules/middlewares"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
 	"github.com/go-chi/chi"
@@ -120,17 +120,17 @@ func Bind(obj interface{}) http.HandlerFunc {
 		var theObj = reflect.New(tp).Interface() // create a new form obj for every request but not use obj directly
 		binding.Bind(ctx.Req, theObj)
 		SetForm(ctx, theObj)
-		middlewares.AssignForm(theObj, ctx.Data)
+		middleware.AssignForm(theObj, ctx.Data)
 	})
 }
 
 // SetForm set the form object
-func SetForm(data middlewares.DataStore, obj interface{}) {
+func SetForm(data middleware.DataStore, obj interface{}) {
 	data.GetData()["__form"] = obj
 }
 
 // GetForm returns the validate form information
-func GetForm(data middlewares.DataStore) interface{} {
+func GetForm(data middleware.DataStore) interface{} {
 	return data.GetData()["__form"]
 }
 
diff --git a/routers/install.go b/routers/install.go
index da2631931e..69ae428a54 100644
--- a/routers/install.go
+++ b/routers/install.go
@@ -20,12 +20,12 @@ import (
 	"code.gitea.io/gitea/modules/generate"
 	"code.gitea.io/gitea/modules/graceful"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
 	"code.gitea.io/gitea/modules/user"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/session"
 	"gopkg.in/ini.v1"
@@ -47,11 +47,11 @@ func InstallInit(next http.Handler) http.Handler {
 			_ = rnd.HTML(resp, 200, string(tplPostInstall), nil)
 			return
 		}
-		var locale = middlewares.Locale(resp, req)
+		var locale = middleware.Locale(resp, req)
 		var startTime = time.Now()
 		var ctx = context.Context{
 			Resp:    context.NewResponse(resp),
-			Flash:   &middlewares.Flash{},
+			Flash:   &middleware.Flash{},
 			Locale:  locale,
 			Render:  rnd,
 			Session: session.GetSession(req),
@@ -143,7 +143,7 @@ func Install(ctx *context.Context) {
 	form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking
 	form.NoReplyAddress = setting.Service.NoReplyAddress
 
-	middlewares.AssignForm(form, ctx.Data)
+	middleware.AssignForm(form, ctx.Data)
 	ctx.HTML(200, tplInstall)
 }
 
diff --git a/routers/repo/pull.go b/routers/repo/pull.go
index 1862c15f43..6986002102 100644
--- a/routers/repo/pull.go
+++ b/routers/repo/pull.go
@@ -21,7 +21,6 @@ import (
 	auth "code.gitea.io/gitea/modules/forms"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/notification"
 	repo_module "code.gitea.io/gitea/modules/repository"
 	"code.gitea.io/gitea/modules/setting"
@@ -29,6 +28,7 @@ import (
 	"code.gitea.io/gitea/modules/upload"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
+	"code.gitea.io/gitea/modules/web/middleware"
 	"code.gitea.io/gitea/routers/utils"
 	"code.gitea.io/gitea/services/gitdiff"
 	pull_service "code.gitea.io/gitea/services/pull"
@@ -989,7 +989,7 @@ func CompareAndPullRequestPost(ctx *context.Context) {
 	}
 
 	if ctx.HasError() {
-		middlewares.AssignForm(form, ctx.Data)
+		middleware.AssignForm(form, ctx.Data)
 
 		// This stage is already stop creating new pull request, so it does not matter if it has
 		// something to compare or not.
diff --git a/routers/routes/base.go b/routers/routes/base.go
index 4efb7f01d5..12a35936b1 100644
--- a/routers/routes/base.go
+++ b/routers/routes/base.go
@@ -18,10 +18,10 @@ import (
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/httpcache"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/storage"
 	"code.gitea.io/gitea/modules/templates"
+	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/session"
 )
@@ -153,7 +153,7 @@ func Recovery() func(next http.Handler) http.Handler {
 						return
 					}
 
-					var lc = middlewares.Locale(w, req)
+					var lc = middleware.Locale(w, req)
 					var store = dataStore{
 						Data: templates.Vars{
 							"Language":   lc.Language(),
diff --git a/routers/routes/install.go b/routers/routes/install.go
index 0dc066d600..fea396bc26 100644
--- a/routers/routes/install.go
+++ b/routers/routes/install.go
@@ -11,11 +11,11 @@ import (
 
 	"code.gitea.io/gitea/modules/forms"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/middlewares"
 	"code.gitea.io/gitea/modules/public"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
 	"code.gitea.io/gitea/modules/web"
+	"code.gitea.io/gitea/modules/web/middleware"
 	"code.gitea.io/gitea/routers"
 
 	"gitea.com/go-chi/session"
@@ -46,7 +46,7 @@ func installRecovery() func(next http.Handler) http.Handler {
 					combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, string(log.Stack(2)))
 					log.Error("%v", combinedErr)
 
-					lc := middlewares.Locale(w, req)
+					lc := middleware.Locale(w, req)
 					var store = dataStore{
 						Data: templates.Vars{
 							"Language":       lc.Language(),
diff --git a/routers/routes/web.go b/routers/routes/web.go
index 03555e3d54..f2b68aa10a 100644
--- a/routers/routes/web.go
+++ b/routers/routes/web.go
@@ -247,7 +247,7 @@ func RegisterRoutes(m *web.Route) {
 		}
 	}
 
-	// FIXME: not all routes need go through same middlewares.
+	// FIXME: not all routes need go through same middleware.
 	// Especially some AJAX requests, we can reduce middleware number to improve performance.
 	// Routers.
 	// for health check