summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2021-06-09 07:33:54 +0800
committerGitHub <noreply@github.com>2021-06-09 01:33:54 +0200
commit1bfb0a24d843e10d6d95c4319a84980485e584ed (patch)
treee4a736f9abee3eaad1270bf3b60ee3bb9401a9dc
parente03a91a48ef7fb716cc7c8bfb411ca8f332dcfe5 (diff)
downloadgitea-1bfb0a24d843e10d6d95c4319a84980485e584ed.tar.gz
gitea-1bfb0a24d843e10d6d95c4319a84980485e584ed.zip
Refactor routers directory (#15800)
* refactor routers directory * move func used for web and api to common * make corsHandler a function to prohibit side efects * rm unused func Co-authored-by: 6543 <6543@obermui.de>
-rw-r--r--.golangci.yml4
-rw-r--r--cmd/web.go8
-rw-r--r--contrib/pr/checkout.go3
-rw-r--r--integrations/create_no_session_test.go6
-rw-r--r--integrations/integration_test.go3
-rw-r--r--integrations/lfs_getobject_test.go8
-rw-r--r--routers/api/v1/repo/file.go6
-rw-r--r--routers/common/db.go39
-rw-r--r--routers/common/logger.go33
-rw-r--r--routers/common/middleware.go76
-rw-r--r--routers/common/repo.go127
-rw-r--r--routers/home.go413
-rw-r--r--routers/init.go80
-rw-r--r--routers/install/install.go (renamed from routers/install.go)13
-rw-r--r--routers/install/routes.go (renamed from routers/routes/install.go)38
-rw-r--r--routers/install/setting.go49
-rw-r--r--routers/web/admin/admin.go (renamed from routers/admin/admin.go)0
-rw-r--r--routers/web/admin/admin_test.go (renamed from routers/admin/admin_test.go)0
-rw-r--r--routers/web/admin/auths.go (renamed from routers/admin/auths.go)0
-rw-r--r--routers/web/admin/emails.go (renamed from routers/admin/emails.go)0
-rw-r--r--routers/web/admin/hooks.go (renamed from routers/admin/hooks.go)0
-rw-r--r--routers/web/admin/main_test.go (renamed from routers/user/setting/main_test.go)2
-rw-r--r--routers/web/admin/notice.go (renamed from routers/admin/notice.go)0
-rw-r--r--routers/web/admin/orgs.go (renamed from routers/admin/orgs.go)4
-rw-r--r--routers/web/admin/repos.go (renamed from routers/admin/repos.go)4
-rw-r--r--routers/web/admin/users.go (renamed from routers/admin/users.go)6
-rw-r--r--routers/web/admin/users_test.go (renamed from routers/admin/users_test.go)0
-rw-r--r--routers/web/base.go (renamed from routers/routes/base.go)55
-rw-r--r--routers/web/dev/template.go (renamed from routers/dev/template.go)0
-rw-r--r--routers/web/events/events.go (renamed from routers/events/events.go)2
-rw-r--r--routers/web/explore/code.go139
-rw-r--r--routers/web/explore/org.go39
-rw-r--r--routers/web/explore/repo.go131
-rw-r--r--routers/web/explore/user.go107
-rw-r--r--routers/web/goget.go (renamed from routers/routes/goget.go)2
-rw-r--r--routers/web/home.go65
-rw-r--r--routers/web/metrics.go (renamed from routers/metrics.go)2
-rw-r--r--routers/web/org/home.go (renamed from routers/org/home.go)0
-rw-r--r--routers/web/org/members.go (renamed from routers/org/members.go)0
-rw-r--r--routers/web/org/org.go (renamed from routers/org/org.go)0
-rw-r--r--routers/web/org/org_labels.go (renamed from routers/org/org_labels.go)0
-rw-r--r--routers/web/org/setting.go (renamed from routers/org/setting.go)2
-rw-r--r--routers/web/org/teams.go (renamed from routers/org/teams.go)0
-rw-r--r--routers/web/repo/activity.go (renamed from routers/repo/activity.go)0
-rw-r--r--routers/web/repo/attachment.go (renamed from routers/repo/attachment.go)3
-rw-r--r--routers/web/repo/blame.go (renamed from routers/repo/blame.go)0
-rw-r--r--routers/web/repo/branch.go (renamed from routers/repo/branch.go)0
-rw-r--r--routers/web/repo/commit.go (renamed from routers/repo/commit.go)0
-rw-r--r--routers/web/repo/compare.go (renamed from routers/repo/compare.go)0
-rw-r--r--routers/web/repo/download.go (renamed from routers/repo/download.go)100
-rw-r--r--routers/web/repo/editor.go (renamed from routers/repo/editor.go)0
-rw-r--r--routers/web/repo/editor_test.go (renamed from routers/repo/editor_test.go)0
-rw-r--r--routers/web/repo/http.go (renamed from routers/repo/http.go)0
-rw-r--r--routers/web/repo/issue.go (renamed from routers/repo/issue.go)0
-rw-r--r--routers/web/repo/issue_dependency.go (renamed from routers/repo/issue_dependency.go)0
-rw-r--r--routers/web/repo/issue_label.go (renamed from routers/repo/issue_label.go)0
-rw-r--r--routers/web/repo/issue_label_test.go (renamed from routers/repo/issue_label_test.go)0
-rw-r--r--routers/web/repo/issue_lock.go (renamed from routers/repo/issue_lock.go)0
-rw-r--r--routers/web/repo/issue_stopwatch.go (renamed from routers/repo/issue_stopwatch.go)0
-rw-r--r--routers/web/repo/issue_test.go (renamed from routers/repo/issue_test.go)0
-rw-r--r--routers/web/repo/issue_timetrack.go (renamed from routers/repo/issue_timetrack.go)0
-rw-r--r--routers/web/repo/issue_watch.go (renamed from routers/repo/issue_watch.go)0
-rw-r--r--routers/web/repo/lfs.go (renamed from routers/repo/lfs.go)0
-rw-r--r--routers/web/repo/main_test.go (renamed from routers/repo/main_test.go)2
-rw-r--r--routers/web/repo/middlewares.go (renamed from routers/repo/middlewares.go)0
-rw-r--r--routers/web/repo/migrate.go (renamed from routers/repo/migrate.go)0
-rw-r--r--routers/web/repo/milestone.go (renamed from routers/repo/milestone.go)0
-rw-r--r--routers/web/repo/projects.go (renamed from routers/repo/projects.go)0
-rw-r--r--routers/web/repo/projects_test.go (renamed from routers/repo/projects_test.go)0
-rw-r--r--routers/web/repo/pull.go (renamed from routers/repo/pull.go)0
-rw-r--r--routers/web/repo/pull_review.go (renamed from routers/repo/pull_review.go)0
-rw-r--r--routers/web/repo/release.go (renamed from routers/repo/release.go)0
-rw-r--r--routers/web/repo/release_test.go (renamed from routers/repo/release_test.go)0
-rw-r--r--routers/web/repo/repo.go (renamed from routers/repo/repo.go)24
-rw-r--r--routers/web/repo/search.go (renamed from routers/repo/search.go)0
-rw-r--r--routers/web/repo/setting.go (renamed from routers/repo/setting.go)0
-rw-r--r--routers/web/repo/setting_protected_branch.go (renamed from routers/repo/setting_protected_branch.go)0
-rw-r--r--routers/web/repo/settings_test.go (renamed from routers/repo/settings_test.go)0
-rw-r--r--routers/web/repo/topic.go (renamed from routers/repo/topic.go)0
-rw-r--r--routers/web/repo/view.go (renamed from routers/repo/view.go)0
-rw-r--r--routers/web/repo/webhook.go (renamed from routers/repo/webhook.go)0
-rw-r--r--routers/web/repo/wiki.go (renamed from routers/repo/wiki.go)3
-rw-r--r--routers/web/repo/wiki_test.go (renamed from routers/repo/wiki_test.go)0
-rw-r--r--routers/web/swagger_json.go (renamed from routers/swagger_json.go)2
-rw-r--r--routers/web/user/auth.go (renamed from routers/user/auth.go)0
-rw-r--r--routers/web/user/auth_openid.go (renamed from routers/user/auth_openid.go)0
-rw-r--r--routers/web/user/avatar.go (renamed from routers/user/avatar.go)0
-rw-r--r--routers/web/user/home.go (renamed from routers/user/home.go)0
-rw-r--r--routers/web/user/home_test.go (renamed from routers/user/home_test.go)0
-rw-r--r--routers/web/user/main_test.go (renamed from routers/user/main_test.go)2
-rw-r--r--routers/web/user/notification.go (renamed from routers/user/notification.go)0
-rw-r--r--routers/web/user/oauth.go (renamed from routers/user/oauth.go)0
-rw-r--r--routers/web/user/profile.go (renamed from routers/user/profile.go)2
-rw-r--r--routers/web/user/setting/account.go (renamed from routers/user/setting/account.go)0
-rw-r--r--routers/web/user/setting/account_test.go (renamed from routers/user/setting/account_test.go)0
-rw-r--r--routers/web/user/setting/adopt.go (renamed from routers/user/setting/adopt.go)0
-rw-r--r--routers/web/user/setting/applications.go (renamed from routers/user/setting/applications.go)0
-rw-r--r--routers/web/user/setting/keys.go (renamed from routers/user/setting/keys.go)0
-rw-r--r--routers/web/user/setting/main_test.go (renamed from routers/admin/main_test.go)4
-rw-r--r--routers/web/user/setting/oauth2.go (renamed from routers/user/setting/oauth2.go)0
-rw-r--r--routers/web/user/setting/profile.go (renamed from routers/user/setting/profile.go)0
-rw-r--r--routers/web/user/setting/security.go (renamed from routers/user/setting/security.go)0
-rw-r--r--routers/web/user/setting/security_openid.go (renamed from routers/user/setting/security_openid.go)0
-rw-r--r--routers/web/user/setting/security_twofa.go (renamed from routers/user/setting/security_twofa.go)0
-rw-r--r--routers/web/user/setting/security_u2f.go (renamed from routers/user/setting/security_u2f.go)0
-rw-r--r--routers/web/user/task.go (renamed from routers/user/task.go)0
-rw-r--r--routers/web/web.go (renamed from routers/routes/web.go)132
107 files changed, 940 insertions, 800 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 0d7f90e263..c3dd47ec29 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -70,9 +70,6 @@ issues:
- path: modules/log/
linters:
- errcheck
- - path: routers/routes/web.go
- linters:
- - dupl
- path: routers/api/v1/repo/issue_subscription.go
linters:
- dupl
@@ -114,3 +111,4 @@ issues:
linters:
- staticcheck
text: "svc.IsAnInteractiveSession is deprecated: Use IsWindowsService instead."
+
diff --git a/cmd/web.go b/cmd/web.go
index 9c7d493339..0ba14ae706 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/routers"
- "code.gitea.io/gitea/routers/routes"
+ "code.gitea.io/gitea/routers/install"
context2 "github.com/gorilla/context"
"github.com/urfave/cli"
@@ -88,7 +88,7 @@ func runWeb(ctx *cli.Context) error {
}
// Perform pre-initialization
- needsInstall := routers.PreInstallInit(graceful.GetManager().HammerContext())
+ needsInstall := install.PreloadSettings(graceful.GetManager().HammerContext())
if needsInstall {
// Flag for port number in case first time run conflict
if ctx.IsSet("port") {
@@ -101,7 +101,7 @@ func runWeb(ctx *cli.Context) error {
return err
}
}
- c := routes.InstallRoutes()
+ c := install.Routes()
err := listen(c, false)
select {
case <-graceful.GetManager().IsShutdown():
@@ -134,7 +134,7 @@ func runWeb(ctx *cli.Context) error {
}
// Set up Chi routes
- c := routes.NormalRoutes()
+ c := routers.NormalRoutes()
err := listen(c, true)
<-graceful.GetManager().Done()
log.Info("PID: %d Gitea Web Finished", os.Getpid())
diff --git a/contrib/pr/checkout.go b/contrib/pr/checkout.go
index 9ee692fd35..9ce84f762c 100644
--- a/contrib/pr/checkout.go
+++ b/contrib/pr/checkout.go
@@ -31,7 +31,6 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/routers"
- "code.gitea.io/gitea/routers/routes"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
@@ -116,7 +115,7 @@ func runPR() {
//routers.GlobalInit()
external.RegisterRenderers()
markup.Init()
- c := routes.NormalRoutes()
+ c := routers.NormalRoutes()
log.Printf("[PR] Ready for testing !\n")
log.Printf("[PR] Login with user1, user2, user3, ... with pass: password\n")
diff --git a/integrations/create_no_session_test.go b/integrations/create_no_session_test.go
index c864b9c7ae..46f111b6f7 100644
--- a/integrations/create_no_session_test.go
+++ b/integrations/create_no_session_test.go
@@ -14,7 +14,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
- "code.gitea.io/gitea/routers/routes"
+ "code.gitea.io/gitea/routers"
"gitea.com/go-chi/session"
jsoniter "github.com/json-iterator/go"
@@ -58,7 +58,7 @@ func TestSessionFileCreation(t *testing.T) {
oldSessionConfig := setting.SessionConfig.ProviderConfig
defer func() {
setting.SessionConfig.ProviderConfig = oldSessionConfig
- c = routes.NormalRoutes()
+ c = routers.NormalRoutes()
}()
var config session.Options
@@ -84,7 +84,7 @@ func TestSessionFileCreation(t *testing.T) {
setting.SessionConfig.ProviderConfig = string(newConfigBytes)
- c = routes.NormalRoutes()
+ c = routers.NormalRoutes()
t.Run("NoSessionOnViewIssue", func(t *testing.T) {
defer PrintCurrentTest(t)()
diff --git a/integrations/integration_test.go b/integrations/integration_test.go
index 74227416c4..d755977d1a 100644
--- a/integrations/integration_test.go
+++ b/integrations/integration_test.go
@@ -34,7 +34,6 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers"
- "code.gitea.io/gitea/routers/routes"
"github.com/PuerkitoBio/goquery"
jsoniter "github.com/json-iterator/go"
@@ -88,7 +87,7 @@ func TestMain(m *testing.M) {
defer cancel()
initIntegrationTest()
- c = routes.NormalRoutes()
+ c = routers.NormalRoutes()
// integration test settings...
if setting.Cfg != nil {
diff --git a/integrations/lfs_getobject_test.go b/integrations/lfs_getobject_test.go
index b7423a2dbe..337a93567a 100644
--- a/integrations/lfs_getobject_test.go
+++ b/integrations/lfs_getobject_test.go
@@ -15,7 +15,7 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/routers/routes"
+ "code.gitea.io/gitea/routers/web"
jsoniter "github.com/json-iterator/go"
gzipp "github.com/klauspost/compress/gzip"
@@ -99,7 +99,7 @@ func TestGetLFSLarge(t *testing.T) {
t.Skip()
return
}
- content := make([]byte, routes.GzipMinSize*10)
+ content := make([]byte, web.GzipMinSize*10)
for i := range content {
content[i] = byte(i % 256)
}
@@ -115,7 +115,7 @@ func TestGetLFSGzip(t *testing.T) {
t.Skip()
return
}
- b := make([]byte, routes.GzipMinSize*10)
+ b := make([]byte, web.GzipMinSize*10)
for i := range b {
b[i] = byte(i % 256)
}
@@ -136,7 +136,7 @@ func TestGetLFSZip(t *testing.T) {
t.Skip()
return
}
- b := make([]byte, routes.GzipMinSize*10)
+ b := make([]byte, web.GzipMinSize*10)
for i := range b {
b[i] = byte(i % 256)
}
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 37e02874b4..39a60df33f 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/repofiles"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
- "code.gitea.io/gitea/routers/repo"
+ "code.gitea.io/gitea/routers/common"
)
// GetRawFile get a file by path on a repository
@@ -83,7 +83,7 @@ func GetRawFile(ctx *context.APIContext) {
}
return
}
- if err = repo.ServeBlob(ctx.Context, blob); err != nil {
+ if err = common.ServeBlob(ctx.Context, blob); err != nil {
ctx.Error(http.StatusInternalServerError, "ServeBlob", err)
}
}
@@ -126,7 +126,7 @@ func GetArchive(ctx *context.APIContext) {
ctx.Repo.GitRepo = gitRepo
defer gitRepo.Close()
- repo.Download(ctx.Context)
+ common.Download(ctx.Context)
}
// GetEditorconfig get editor config of a repository
diff --git a/routers/common/db.go b/routers/common/db.go
new file mode 100644
index 0000000000..069a46f64f
--- /dev/null
+++ b/routers/common/db.go
@@ -0,0 +1,39 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "context"
+ "fmt"
+ "time"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/models/migrations"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+// InitDBEngine In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology
+func InitDBEngine(ctx context.Context) (err error) {
+ log.Info("Beginning ORM engine initialization.")
+ for i := 0; i < setting.Database.DBConnectRetries; i++ {
+ select {
+ case <-ctx.Done():
+ return fmt.Errorf("Aborted due to shutdown:\nin retry ORM engine initialization")
+ default:
+ }
+ log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.Database.DBConnectRetries)
+ if err = models.NewEngine(ctx, migrations.Migrate); err == nil {
+ break
+ } else if i == setting.Database.DBConnectRetries-1 {
+ return err
+ }
+ log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.Database.DBConnectRetries, err)
+ log.Info("Backing off for %d seconds", int64(setting.Database.DBConnectBackoff/time.Second))
+ time.Sleep(setting.Database.DBConnectBackoff)
+ }
+ models.HasEngine = true
+ return nil
+}
diff --git a/routers/common/logger.go b/routers/common/logger.go
new file mode 100644
index 0000000000..bc1149543c
--- /dev/null
+++ b/routers/common/logger.go
@@ -0,0 +1,33 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "net/http"
+ "time"
+
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
+)
+
+// LoggerHandler is a handler that will log the routing to the default gitea log
+func LoggerHandler(level log.Level) func(next http.Handler) http.Handler {
+ return func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ start := time.Now()
+
+ _ = log.GetLogger("router").Log(0, level, "Started %s %s for %s", log.ColoredMethod(req.Method), req.URL.RequestURI(), req.RemoteAddr)
+
+ next.ServeHTTP(w, req)
+
+ var status int
+ if v, ok := w.(context.ResponseWriter); ok {
+ status = v.Status()
+ }
+
+ _ = log.GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", log.ColoredMethod(req.Method), req.URL.RequestURI(), log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(status)), log.ColoredTime(time.Since(start)))
+ })
+ }
+}
diff --git a/routers/common/middleware.go b/routers/common/middleware.go
new file mode 100644
index 0000000000..1d96522dd9
--- /dev/null
+++ b/routers/common/middleware.go
@@ -0,0 +1,76 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "fmt"
+ "net/http"
+ "strings"
+
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+
+ "github.com/chi-middleware/proxy"
+ "github.com/go-chi/chi/middleware"
+)
+
+// Middlewares returns common middlewares
+func Middlewares() []func(http.Handler) http.Handler {
+ var handlers = []func(http.Handler) http.Handler{
+ func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ next.ServeHTTP(context.NewResponse(resp), req)
+ })
+ },
+ }
+
+ if setting.ReverseProxyLimit > 0 {
+ opt := proxy.NewForwardedHeadersOptions().
+ WithForwardLimit(setting.ReverseProxyLimit).
+ ClearTrustedProxies()
+ for _, n := range setting.ReverseProxyTrustedProxies {
+ if !strings.Contains(n, "/") {
+ opt.AddTrustedProxy(n)
+ } else {
+ opt.AddTrustedNetwork(n)
+ }
+ }
+ handlers = append(handlers, proxy.ForwardedHeaders(opt))
+ }
+
+ handlers = append(handlers, middleware.StripSlashes)
+
+ if !setting.DisableRouterLog && setting.RouterLogLevel != log.NONE {
+ if log.GetLogger("router").GetLevel() <= setting.RouterLogLevel {
+ handlers = append(handlers, LoggerHandler(setting.RouterLogLevel))
+ }
+ }
+ if setting.EnableAccessLog {
+ handlers = append(handlers, context.AccessLogger())
+ }
+
+ handlers = append(handlers, func(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
+ // Why we need this? The Recovery() will try to render a beautiful
+ // error page for user, but the process can still panic again, and other
+ // middleware like session also may panic then we have to recover twice
+ // and send a simple error page that should not panic any more.
+ defer func() {
+ if err := recover(); err != nil {
+ combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, string(log.Stack(2)))
+ log.Error("%v", combinedErr)
+ if setting.IsProd() {
+ http.Error(resp, http.StatusText(500), 500)
+ } else {
+ http.Error(resp, combinedErr, 500)
+ }
+ }
+ }()
+ next.ServeHTTP(resp, req)
+ })
+ })
+ return handlers
+}
diff --git a/routers/common/repo.go b/routers/common/repo.go
new file mode 100644
index 0000000000..c61b5ec57f
--- /dev/null
+++ b/routers/common/repo.go
@@ -0,0 +1,127 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package common
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "code.gitea.io/gitea/modules/charset"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/httpcache"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/typesniffer"
+ "code.gitea.io/gitea/services/archiver"
+)
+
+// ServeBlob download a git.Blob
+func ServeBlob(ctx *context.Context, blob *git.Blob) error {
+ if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`) {
+ return nil
+ }
+
+ dataRc, err := blob.DataAsync()
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err = dataRc.Close(); err != nil {
+ log.Error("ServeBlob: Close: %v", err)
+ }
+ }()
+
+ return ServeData(ctx, ctx.Repo.TreePath, blob.Size(), dataRc)
+}
+
+// Download an archive of a repository
+func Download(ctx *context.Context) {
+ uri := ctx.Params("*")
+ aReq := archiver.DeriveRequestFrom(ctx, uri)
+
+ if aReq == nil {
+ ctx.Error(http.StatusNotFound)
+ return
+ }
+
+ downloadName := ctx.Repo.Repository.Name + "-" + aReq.GetArchiveName()
+ complete := aReq.IsComplete()
+ if !complete {
+ aReq = archiver.ArchiveRepository(aReq)
+ complete = aReq.WaitForCompletion(ctx)
+ }
+
+ if complete {
+ ctx.ServeFile(aReq.GetArchivePath(), downloadName)
+ } else {
+ ctx.Error(http.StatusNotFound)
+ }
+}
+
+// ServeData download file from io.Reader
+func ServeData(ctx *context.Context, name string, size int64, reader io.Reader) error {
+ buf := make([]byte, 1024)
+ n, err := reader.Read(buf)
+ if err != nil && err != io.EOF {
+ return err
+ }
+ if n >= 0 {
+ buf = buf[:n]
+ }
+
+ ctx.Resp.Header().Set("Cache-Control", "public,max-age=86400")
+
+ if size >= 0 {
+ ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", size))
+ } else {
+ log.Error("ServeData called to serve data: %s with size < 0: %d", name, size)
+ }
+ name = path.Base(name)
+
+ // Google Chrome dislike commas in filenames, so let's change it to a space
+ name = strings.ReplaceAll(name, ",", " ")
+
+ st := typesniffer.DetectContentType(buf)
+
+ if st.IsText() || ctx.QueryBool("render") {
+ cs, err := charset.DetectEncoding(buf)
+ if err != nil {
+ log.Error("Detect raw file %s charset failed: %v, using by default utf-8", name, err)
+ cs = "utf-8"
+ }
+ ctx.Resp.Header().Set("Content-Type", "text/plain; charset="+strings.ToLower(cs))
+ } else {
+ ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
+
+ if (st.IsImage() || st.IsPDF()) && (setting.UI.SVG.Enabled || !st.IsSvgImage()) {
+ ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
+ if st.IsSvgImage() {
+ ctx.Resp.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
+ ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff")
+ ctx.Resp.Header().Set("Content-Type", typesniffer.SvgMimeType)
+ }
+ } else {
+ ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
+ if setting.MimeTypeMap.Enabled {
+ fileExtension := strings.ToLower(filepath.Ext(name))
+ if mimetype, ok := setting.MimeTypeMap.Map[fileExtension]; ok {
+ ctx.Resp.Header().Set("Content-Type", mimetype)
+ }
+ }
+ }
+ }
+
+ _, err = ctx.Resp.Write(buf)
+ if err != nil {
+ return err
+ }
+ _, err = io.Copy(ctx.Resp, reader)
+ return err
+}
diff --git a/routers/home.go b/routers/home.go
deleted file mode 100644
index 7eaebc081f..0000000000
--- a/routers/home.go
+++ /dev/null
@@ -1,413 +0,0 @@
-// Copyright 2014 The Gogs Authors. All rights reserved.
-// Copyright 2019 The Gitea Authors. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package routers
-
-import (
- "bytes"
- "net/http"
- "strings"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
- code_indexer "code.gitea.io/gitea/modules/indexer/code"
- "code.gitea.io/gitea/modules/log"
- "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/user"
-)
-
-const (
- // tplHome home page template
- tplHome base.TplName = "home"
- // tplExploreRepos explore repositories page template
- tplExploreRepos base.TplName = "explore/repos"
- // tplExploreUsers explore users page template
- tplExploreUsers base.TplName = "explore/users"
- // tplExploreOrganizations explore organizations page template
- tplExploreOrganizations base.TplName = "explore/organizations"
- // tplExploreCode explore code page template
- tplExploreCode base.TplName = "explore/code"
-)
-
-// Home render home page
-func Home(ctx *context.Context) {
- if ctx.IsSigned {
- if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
- ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
- ctx.HTML(http.StatusOK, user.TplActivate)
- } else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
- log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
- ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
- ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
- } else if ctx.User.MustChangePassword {
- ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
- ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
- middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
- ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
- } else {
- user.Dashboard(ctx)
- }
- return
- // Check non-logged users landing page.
- } else if setting.LandingPageURL != setting.LandingPageHome {
- ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
- return
- }
-
- // Check auto-login.
- uname := ctx.GetCookie(setting.CookieUserName)
- if len(uname) != 0 {
- ctx.Redirect(setting.AppSubURL + "/user/login")
- return
- }
-
- ctx.Data["PageIsHome"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- ctx.HTML(http.StatusOK, tplHome)
-}
-
-// RepoSearchOptions when calling search repositories
-type RepoSearchOptions struct {
- OwnerID int64
- Private bool
- Restricted bool
- PageSize int
- TplName base.TplName
-}
-
-var (
- nullByte = []byte{0x00}
-)
-
-func isKeywordValid(keyword string) bool {
- return !bytes.Contains([]byte(keyword), nullByte)
-}
-
-// RenderRepoSearch render repositories search page
-func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
- page := ctx.QueryInt("page")
- if page <= 0 {
- page = 1
- }
-
- var (
- repos []*models.Repository
- count int64
- err error
- orderBy models.SearchOrderBy
- )
-
- ctx.Data["SortType"] = ctx.Query("sort")
- switch ctx.Query("sort") {
- case "newest":
- orderBy = models.SearchOrderByNewest
- case "oldest":
- orderBy = models.SearchOrderByOldest
- case "recentupdate":
- orderBy = models.SearchOrderByRecentUpdated
- case "leastupdate":
- orderBy = models.SearchOrderByLeastUpdated
- case "reversealphabetically":
- orderBy = models.SearchOrderByAlphabeticallyReverse
- case "alphabetically":
- orderBy = models.SearchOrderByAlphabetically
- case "reversesize":
- orderBy = models.SearchOrderBySizeReverse
- case "size":
- orderBy = models.SearchOrderBySize
- case "moststars":
- orderBy = models.SearchOrderByStarsReverse
- case "feweststars":
- orderBy = models.SearchOrderByStars
- case "mostforks":
- orderBy = models.SearchOrderByForksReverse
- case "fewestforks":
- orderBy = models.SearchOrderByForks
- default:
- ctx.Data["SortType"] = "recentupdate"
- orderBy = models.SearchOrderByRecentUpdated
- }
-
- keyword := strings.Trim(ctx.Query("q"), " ")
- topicOnly := ctx.QueryBool("topic")
- ctx.Data["TopicOnly"] = topicOnly
-
- repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
- ListOptions: models.ListOptions{
- Page: page,
- PageSize: opts.PageSize,
- },
- Actor: ctx.User,
- OrderBy: orderBy,
- Private: opts.Private,
- Keyword: keyword,
- OwnerID: opts.OwnerID,
- AllPublic: true,
- AllLimited: true,
- TopicOnly: topicOnly,
- IncludeDescription: setting.UI.SearchRepoDescription,
- })
- if err != nil {
- ctx.ServerError("SearchRepository", err)
- return
- }
- ctx.Data["Keyword"] = keyword
- ctx.Data["Total"] = count
- ctx.Data["Repos"] = repos
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- pager := context.NewPagination(int(count), opts.PageSize, page, 5)
- pager.SetDefaultParams(ctx)
- pager.AddParam(ctx, "topic", "TopicOnly")
- ctx.Data["Page"] = pager
-
- ctx.HTML(http.StatusOK, opts.TplName)
-}
-
-// ExploreRepos render explore repositories page
-func ExploreRepos(ctx *context.Context) {
- ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreRepositories"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- var ownerID int64
- if ctx.User != nil && !ctx.User.IsAdmin {
- ownerID = ctx.User.ID
- }
-
- RenderRepoSearch(ctx, &RepoSearchOptions{
- PageSize: setting.UI.ExplorePagingNum,
- OwnerID: ownerID,
- Private: ctx.User != nil,
- TplName: tplExploreRepos,
- })
-}
-
-// RenderUserSearch render user search page
-func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplName base.TplName) {
- opts.Page = ctx.QueryInt("page")
- if opts.Page <= 1 {
- opts.Page = 1
- }
-
- var (
- users []*models.User
- count int64
- err error
- orderBy models.SearchOrderBy
- )
-
- ctx.Data["SortType"] = ctx.Query("sort")
- switch ctx.Query("sort") {
- case "newest":
- orderBy = models.SearchOrderByIDReverse
- case "oldest":
- orderBy = models.SearchOrderByID
- case "recentupdate":
- orderBy = models.SearchOrderByRecentUpdated
- case "leastupdate":
- orderBy = models.SearchOrderByLeastUpdated
- case "reversealphabetically":
- orderBy = models.SearchOrderByAlphabeticallyReverse
- case "alphabetically":
- orderBy = models.SearchOrderByAlphabetically
- default:
- ctx.Data["SortType"] = "alphabetically"
- orderBy = models.SearchOrderByAlphabetically
- }
-
- opts.Keyword = strings.Trim(ctx.Query("q"), " ")
- opts.OrderBy = orderBy
- if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
- users, count, err = models.SearchUsers(opts)
- if err != nil {
- ctx.ServerError("SearchUsers", err)
- return
- }
- }
- ctx.Data["Keyword"] = opts.Keyword
- ctx.Data["Total"] = count
- ctx.Data["Users"] = users
- ctx.Data["UsersTwoFaStatus"] = models.UserList(users).GetTwoFaStatus()
- ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
- pager.SetDefaultParams(ctx)
- ctx.Data["Page"] = pager
-
- ctx.HTML(http.StatusOK, tplName)
-}
-
-// ExploreUsers render explore users page
-func ExploreUsers(ctx *context.Context) {
- if setting.Service.Explore.DisableUsersPage {
- ctx.Redirect(setting.AppSubURL + "/explore/repos")
- return
- }
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreUsers"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- RenderUserSearch(ctx, &models.SearchUserOptions{
- Actor: ctx.User,
- Type: models.UserTypeIndividual,
- ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
- IsActive: util.OptionalBoolTrue,
- Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
- }, tplExploreUsers)
-}
-
-// ExploreOrganizations render explore organizations page
-func ExploreOrganizations(ctx *context.Context) {
- ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreOrganizations"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- visibleTypes := []structs.VisibleType{structs.VisibleTypePublic}
- if ctx.User != nil {
- visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate)
- }
-
- RenderUserSearch(ctx, &models.SearchUserOptions{
- Actor: ctx.User,
- Type: models.UserTypeOrganization,
- ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
- Visible: visibleTypes,
- }, tplExploreOrganizations)
-}
-
-// ExploreCode render explore code page
-func ExploreCode(ctx *context.Context) {
- if !setting.Indexer.RepoIndexerEnabled {
- ctx.Redirect(setting.AppSubURL+"/explore", 302)
- return
- }
-
- ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreCode"] = true
-
- language := strings.TrimSpace(ctx.Query("l"))
- keyword := strings.TrimSpace(ctx.Query("q"))
- page := ctx.QueryInt("page")
- if page <= 0 {
- page = 1
- }
-
- queryType := strings.TrimSpace(ctx.Query("t"))
- isMatch := queryType == "match"
-
- var (
- repoIDs []int64
- err error
- isAdmin bool
- )
- if ctx.User != nil {
- isAdmin = ctx.User.IsAdmin
- }
-
- // guest user or non-admin user
- if ctx.User == nil || !isAdmin {
- repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.User)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
- }
-
- var (
- total int
- searchResults []*code_indexer.Result
- searchResultLanguages []*code_indexer.SearchResultLanguages
- )
-
- // if non-admin login user, we need check UnitTypeCode at first
- if ctx.User != nil && len(repoIDs) > 0 {
- repoMaps, err := models.GetRepositoriesMapByIDs(repoIDs)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- var rightRepoMap = make(map[int64]*models.Repository, len(repoMaps))
- repoIDs = make([]int64, 0, len(repoMaps))
- for id, repo := range repoMaps {
- if repo.CheckUnitUser(ctx.User, models.UnitTypeCode) {
- rightRepoMap[id] = repo
- repoIDs = append(repoIDs, id)
- }
- }
-
- ctx.Data["RepoMaps"] = rightRepoMap
-
- total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
- // if non-login user or isAdmin, no need to check UnitTypeCode
- } else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
- total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- var loadRepoIDs = make([]int64, 0, len(searchResults))
- for _, result := range searchResults {
- var find bool
- for _, id := range loadRepoIDs {
- if id == result.RepoID {
- find = true
- break
- }
- }
- if !find {
- loadRepoIDs = append(loadRepoIDs, result.RepoID)
- }
- }
-
- repoMaps, err := models.GetRepositoriesMapByIDs(loadRepoIDs)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- ctx.Data["RepoMaps"] = repoMaps
- }
-
- ctx.Data["Keyword"] = keyword
- ctx.Data["Language"] = language
- ctx.Data["queryType"] = queryType
- ctx.Data["SearchResults"] = searchResults
- ctx.Data["SearchResultLanguages"] = searchResultLanguages
- ctx.Data["RequireHighlightJS"] = true
- ctx.Data["PageIsViewCode"] = true
-
- pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
- pager.SetDefaultParams(ctx)
- pager.AddParam(ctx, "l", "Language")
- ctx.Data["Page"] = pager
-
- ctx.HTML(http.StatusOK, tplExploreCode)
-}
-
-// NotFound render 404 page
-func NotFound(ctx *context.Context) {
- ctx.Data["Title"] = "Page Not Found"
- ctx.NotFound("home.NotFound", nil)
-}
diff --git a/routers/init.go b/routers/init.go
index 220d87a29d..5e2eca439e 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -6,12 +6,9 @@ package routers
import (
"context"
- "fmt"
"strings"
- "time"
"code.gitea.io/gitea/models"
- "code.gitea.io/gitea/models/migrations"
"code.gitea.io/gitea/modules/auth/sso"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/cron"
@@ -32,6 +29,11 @@ import (
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/task"
"code.gitea.io/gitea/modules/translation"
+ "code.gitea.io/gitea/modules/web"
+ apiv1 "code.gitea.io/gitea/routers/api/v1"
+ "code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/routers/private"
+ web_routers "code.gitea.io/gitea/routers/web"
"code.gitea.io/gitea/services/mailer"
mirror_service "code.gitea.io/gitea/services/mirror"
pull_service "code.gitea.io/gitea/services/pull"
@@ -63,63 +65,6 @@ func NewServices() {
notification.NewContext()
}
-// In case of problems connecting to DB, retry connection. Eg, PGSQL in Docker Container on Synology
-func initDBEngine(ctx context.Context) (err error) {
- log.Info("Beginning ORM engine initialization.")
- for i := 0; i < setting.Database.DBConnectRetries; i++ {
- select {
- case <-ctx.Done():
- return fmt.Errorf("Aborted due to shutdown:\nin retry ORM engine initialization")
- default:
- }
- log.Info("ORM engine initialization attempt #%d/%d...", i+1, setting.Database.DBConnectRetries)
- if err = models.NewEngine(ctx, migrations.Migrate); err == nil {
- break
- } else if i == setting.Database.DBConnectRetries-1 {
- return err
- }
- log.Error("ORM engine initialization attempt #%d/%d failed. Error: %v", i+1, setting.Database.DBConnectRetries, err)
- log.Info("Backing off for %d seconds", int64(setting.Database.DBConnectBackoff/time.Second))
- time.Sleep(setting.Database.DBConnectBackoff)
- }
- models.HasEngine = true
- return nil
-}
-
-// PreInstallInit preloads the configuration to check if we need to run install
-func PreInstallInit(ctx context.Context) bool {
- setting.NewContext()
- if !setting.InstallLock {
- log.Trace("AppPath: %s", setting.AppPath)
- log.Trace("AppWorkPath: %s", setting.AppWorkPath)
- log.Trace("Custom path: %s", setting.CustomPath)
- log.Trace("Log path: %s", setting.LogRootPath)
- log.Trace("Preparing to run install page")
- translation.InitLocales()
- if setting.EnableSQLite3 {
- log.Info("SQLite3 Supported")
- }
- setting.InitDBConfig()
- svg.Init()
- }
-
- return !setting.InstallLock
-}
-
-// PostInstallInit rereads the settings and starts up the database
-func PostInstallInit(ctx context.Context) {
- setting.NewContext()
- setting.InitDBConfig()
- if setting.InstallLock {
- if err := initDBEngine(ctx); err == nil {
- log.Info("ORM engine initialization successful!")
- } else {
- log.Fatal("ORM engine initialization failed: %v", err)
- }
- svg.Init()
- }
-}
-
// GlobalInit is for global configuration reload-able.
func GlobalInit(ctx context.Context) {
setting.NewContext()
@@ -151,7 +96,7 @@ func GlobalInit(ctx context.Context) {
} else if setting.Database.UseSQLite3 {
log.Fatal("SQLite3 is set in settings but NOT Supported")
}
- if err := initDBEngine(ctx); err == nil {
+ if err := common.InitDBEngine(ctx); err == nil {
log.Info("ORM engine initialization successful!")
} else {
log.Fatal("ORM engine initialization failed: %v", err)
@@ -193,3 +138,16 @@ func GlobalInit(ctx context.Context) {
svg.Init()
}
+
+// NormalRoutes represents non install routes
+func NormalRoutes() *web.Route {
+ r := web.NewRoute()
+ for _, middle := range common.Middlewares() {
+ r.Use(middle)
+ }
+
+ r.Mount("/", web_routers.Routes())
+ r.Mount("/api/v1", apiv1.Routes())
+ r.Mount("/api/internal", private.Routes())
+ return r
+}
diff --git a/routers/install.go b/routers/install/install.go
index 6c460a887d..a7040bccad 100644
--- a/routers/install.go
+++ b/routers/install/install.go
@@ -1,8 +1,9 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
+// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package routers
+package install
import (
"fmt"
@@ -38,8 +39,8 @@ const (
tplPostInstall base.TplName = "post-install"
)
-// InstallInit prepare for rendering installation page
-func InstallInit(next http.Handler) http.Handler {
+// Init prepare for rendering installation page
+func Init(next http.Handler) http.Handler {
var rnd = templates.HTMLRenderer()
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
@@ -158,8 +159,8 @@ func Install(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplInstall)
}
-// InstallPost response for submit install items
-func InstallPost(ctx *context.Context) {
+// SubmitInstall response for submit install items
+func SubmitInstall(ctx *context.Context) {
form := *web.GetForm(ctx).(*forms.InstallForm)
var err error
ctx.Data["CurDbOption"] = form.DbType
@@ -409,7 +410,7 @@ func InstallPost(ctx *context.Context) {
}
// Re-read settings
- PostInstallInit(ctx)
+ ReloadSettings(ctx)
// Create admin account
if len(form.AdminName) > 0 {
diff --git a/routers/routes/install.go b/routers/install/routes.go
index 0918da1a4b..36130d4b3f 100644
--- a/routers/routes/install.go
+++ b/routers/install/routes.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 routes
+package install
import (
"fmt"
@@ -15,12 +15,18 @@ import (
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/modules/web/middleware"
- "code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/forms"
"gitea.com/go-chi/session"
)
+type dataStore map[string]interface{}
+
+func (d *dataStore) GetData() map[string]interface{} {
+ return *d
+}
+
func installRecovery() func(next http.Handler) http.Handler {
var rnd = templates.HTMLRenderer()
return func(next http.Handler) http.Handler {
@@ -48,21 +54,19 @@ func installRecovery() func(next http.Handler) http.Handler {
lc := middleware.Locale(w, req)
var store = dataStore{
- Data: templates.Vars{
- "Language": lc.Language(),
- "CurrentURL": setting.AppSubURL + req.URL.RequestURI(),
- "i18n": lc,
- "SignedUserID": int64(0),
- "SignedUserName": "",
- },
+ "Language": lc.Language(),
+ "CurrentURL": setting.AppSubURL + req.URL.RequestURI(),
+ "i18n": lc,
+ "SignedUserID": int64(0),
+ "SignedUserName": "",
}
w.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)
if !setting.IsProd() {
- store.Data["ErrorMsg"] = combinedErr
+ store["ErrorMsg"] = combinedErr
}
- err = rnd.HTML(w, 500, "status/500", templates.BaseVars().Merge(store.Data))
+ err = rnd.HTML(w, 500, "status/500", templates.BaseVars().Merge(store))
if err != nil {
log.Error("%v", err)
}
@@ -74,10 +78,10 @@ func installRecovery() func(next http.Handler) http.Handler {
}
}
-// InstallRoutes registers the install routes
-func InstallRoutes() *web.Route {
+// Routes registers the install routes
+func Routes() *web.Route {
r := web.NewRoute()
- for _, middle := range commonMiddlewares() {
+ for _, middle := range common.Middlewares() {
r.Use(middle)
}
@@ -99,9 +103,9 @@ func InstallRoutes() *web.Route {
}))
r.Use(installRecovery())
- r.Use(routers.InstallInit)
- r.Get("/", routers.Install)
- r.Post("/", web.Bind(forms.InstallForm{}), routers.InstallPost)
+ r.Use(Init)
+ r.Get("/", Install)
+ r.Post("/", web.Bind(forms.InstallForm{}), SubmitInstall)
r.NotFound(func(w http.ResponseWriter, req *http.Request) {
http.Redirect(w, req, setting.AppURL, http.StatusFound)
})
diff --git a/routers/install/setting.go b/routers/install/setting.go
new file mode 100644
index 0000000000..50bb6aa355
--- /dev/null
+++ b/routers/install/setting.go
@@ -0,0 +1,49 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package install
+
+import (
+ "context"
+
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/svg"
+ "code.gitea.io/gitea/modules/translation"
+ "code.gitea.io/gitea/routers/common"
+)
+
+// PreloadSettings preloads the configuration to check if we need to run install
+func PreloadSettings(ctx context.Context) bool {
+ setting.NewContext()
+ if !setting.InstallLock {
+ log.Trace("AppPath: %s", setting.AppPath)
+ log.Trace("AppWorkPath: %s", setting.AppWorkPath)
+ log.Trace("Custom path: %s", setting.CustomPath)
+ log.Trace("Log path: %s", setting.LogRootPath)
+ log.Trace("Preparing to run install page")
+ translation.InitLocales()
+ if setting.EnableSQLite3 {
+ log.Info("SQLite3 Supported")
+ }
+ setting.InitDBConfig()
+ svg.Init()
+ }
+
+ return !setting.InstallLock
+}
+
+// ReloadSettings rereads the settings and starts up the database
+func ReloadSettings(ctx context.Context) {
+ setting.NewContext()
+ setting.InitDBConfig()
+ if setting.InstallLock {
+ if err := common.InitDBEngine(ctx); err == nil {
+ log.Info("ORM engine initialization successful!")
+ } else {
+ log.Fatal("ORM engine initialization failed: %v", err)
+ }
+ svg.Init()
+ }
+}
diff --git a/routers/admin/admin.go b/routers/web/admin/admin.go
index c2d94ab9c9..c2d94ab9c9 100644
--- a/routers/admin/admin.go
+++ b/routers/web/admin/admin.go
diff --git a/routers/admin/admin_test.go b/routers/web/admin/admin_test.go
index da404e50d7..da404e50d7 100644
--- a/routers/admin/admin_test.go
+++ b/routers/web/admin/admin_test.go
diff --git a/routers/admin/auths.go b/routers/web/admin/auths.go
index a2f9ab0a5c..a2f9ab0a5c 100644
--- a/routers/admin/auths.go
+++ b/routers/web/admin/auths.go
diff --git a/routers/admin/emails.go b/routers/web/admin/emails.go
index f7e8c97fb6..f7e8c97fb6 100644
--- a/routers/admin/emails.go
+++ b/routers/web/admin/emails.go
diff --git a/routers/admin/hooks.go b/routers/web/admin/hooks.go
index ff32260cc0..ff32260cc0 100644
--- a/routers/admin/hooks.go
+++ b/routers/web/admin/hooks.go
diff --git a/routers/user/setting/main_test.go b/routers/web/admin/main_test.go
index d343c02f48..352907c737 100644
--- a/routers/user/setting/main_test.go
+++ b/routers/web/admin/main_test.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 setting
+package admin
import (
"path/filepath"
diff --git a/routers/admin/notice.go b/routers/web/admin/notice.go
index e2ebd0d917..e2ebd0d917 100644
--- a/routers/admin/notice.go
+++ b/routers/web/admin/notice.go
diff --git a/routers/admin/orgs.go b/routers/web/admin/orgs.go
index 627f56eaec..618f945704 100644
--- a/routers/admin/orgs.go
+++ b/routers/web/admin/orgs.go
@@ -11,7 +11,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/routers/web/explore"
)
const (
@@ -24,7 +24,7 @@ func Organizations(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminOrganizations"] = true
- routers.RenderUserSearch(ctx, &models.SearchUserOptions{
+ explore.RenderUserSearch(ctx, &models.SearchUserOptions{
Type: models.UserTypeOrganization,
ListOptions: models.ListOptions{
PageSize: setting.UI.Admin.OrgPagingNum,
diff --git a/routers/admin/repos.go b/routers/web/admin/repos.go
index d23f7c3d5a..6128992f5a 100644
--- a/routers/admin/repos.go
+++ b/routers/web/admin/repos.go
@@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
- "code.gitea.io/gitea/routers"
+ "code.gitea.io/gitea/routers/web/explore"
repo_service "code.gitea.io/gitea/services/repository"
)
@@ -32,7 +32,7 @@ func Repos(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminRepositories"] = true
- routers.RenderRepoSearch(ctx, &routers.RepoSearchOptions{
+ explore.RenderRepoSearch(ctx, &explore.RepoSearchOptions{
Private: true,
PageSize: setting.UI.Admin.RepoPagingNum,
TplName: tplRepos,
diff --git a/routers/admin/users.go b/routers/web/admin/users.go
index a71a11dd8a..1b65795865 100644
--- a/routers/admin/users.go
+++ b/routers/web/admin/users.go
@@ -18,8 +18,8 @@ import (
"code.gitea.io/gitea/modules/password"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
- "code.gitea.io/gitea/routers"
- router_user_setting "code.gitea.io/gitea/routers/user/setting"
+ "code.gitea.io/gitea/routers/web/explore"
+ router_user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/mailer"
)
@@ -36,7 +36,7 @@ func Users(ctx *context.Context) {
ctx.Data["PageIsAdmin"] = true
ctx.Data["PageIsAdminUsers"] = true
- routers.RenderUserSearch(ctx, &models.SearchUserOptions{
+ explore.RenderUserSearch(ctx, &models.SearchUserOptions{
Type: models.UserTypeIndividual,
ListOptions: models.ListOptions{
PageSize: setting.UI.Admin.UserPagingNum,
diff --git a/routers/admin/users_test.go b/routers/web/admin/users_test.go
index b19dcb886b..b19dcb886b 100644
--- a/routers/admin/users_test.go
+++ b/routers/web/admin/users_test.go
diff --git a/routers/routes/base.go b/routers/web/base.go
index 0b784508a7..8a44736434 100644
--- a/routers/routes/base.go
+++ b/routers/web/base.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 routes
+package web
import (
"errors"
@@ -13,7 +13,6 @@ import (
"path"
"path/filepath"
"strings"
- "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth/sso"
@@ -28,26 +27,6 @@ import (
"gitea.com/go-chi/session"
)
-// LoggerHandler is a handler that will log the routing to the default gitea log
-func LoggerHandler(level log.Level) func(next http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- start := time.Now()
-
- _ = log.GetLogger("router").Log(0, level, "Started %s %s for %s", log.ColoredMethod(req.Method), req.URL.RequestURI(), req.RemoteAddr)
-
- next.ServeHTTP(w, req)
-
- var status int
- if v, ok := w.(context.ResponseWriter); ok {
- status = v.Status()
- }
-
- _ = log.GetLogger("router").Log(0, level, "Completed %s %s %v %s in %v", log.ColoredMethod(req.Method), req.URL.RequestURI(), log.ColoredStatus(status), log.ColoredStatus(status, http.StatusText(status)), log.ColoredTime(time.Since(start)))
- })
- }
-}
-
func storageHandler(storageSetting setting.Storage, prefix string, objStore storage.ObjectStorage) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
if storageSetting.ServeDirect {
@@ -134,12 +113,10 @@ func storageHandler(storageSetting setting.Storage, prefix string, objStore stor
}
}
-type dataStore struct {
- Data map[string]interface{}
-}
+type dataStore map[string]interface{}
func (d *dataStore) GetData() map[string]interface{} {
- return d.Data
+ return *d
}
// Recovery returns a middleware that recovers from any panics and writes a 500 and a log if so.
@@ -165,11 +142,9 @@ func Recovery() func(next http.Handler) http.Handler {
var lc = middleware.Locale(w, req)
var store = dataStore{
- Data: templates.Vars{
- "Language": lc.Language(),
- "CurrentURL": setting.AppSubURL + req.URL.RequestURI(),
- "i18n": lc,
- },
+ "Language": lc.Language(),
+ "CurrentURL": setting.AppSubURL + req.URL.RequestURI(),
+ "i18n": lc,
}
var user *models.User
@@ -186,22 +161,22 @@ func Recovery() func(next http.Handler) http.Handler {
user = sso.SessionUser(sessionStore)
}
if user != nil {
- store.Data["IsSigned"] = true
- store.Data["SignedUser"] = user
- store.Data["SignedUserID"] = user.ID
- store.Data["SignedUserName"] = user.Name
- store.Data["IsAdmin"] = user.IsAdmin
+ store["IsSigned"] = true
+ store["SignedUser"] = user
+ store["SignedUserID"] = user.ID
+ store["SignedUserName"] = user.Name
+ store["IsAdmin"] = user.IsAdmin
} else {
- store.Data["SignedUserID"] = int64(0)
- store.Data["SignedUserName"] = ""
+ store["SignedUserID"] = int64(0)
+ store["SignedUserName"] = ""
}
w.Header().Set(`X-Frame-Options`, `SAMEORIGIN`)
if !setting.IsProd() {
- store.Data["ErrorMsg"] = combinedErr
+ store["ErrorMsg"] = combinedErr
}
- err = rnd.HTML(w, 500, "status/500", templates.BaseVars().Merge(store.Data))
+ err = rnd.HTML(w, 500, "status/500", templates.BaseVars().Merge(store))
if err != nil {
log.Error("%v", err)
}
diff --git a/routers/dev/template.go b/routers/web/dev/template.go
index de334c4f8b..de334c4f8b 100644
--- a/routers/dev/template.go
+++ b/routers/web/dev/template.go
diff --git a/routers/events/events.go b/routers/web/events/events.go
index b140bf660c..f9cc274851 100644
--- a/routers/events/events.go
+++ b/routers/web/events/events.go
@@ -15,7 +15,7 @@ import (
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/routers/user"
+ "code.gitea.io/gitea/routers/web/user"
jsoniter "github.com/json-iterator/go"
)
diff --git a/routers/web/explore/code.go b/routers/web/explore/code.go
new file mode 100644
index 0000000000..bf15b93cff
--- /dev/null
+++ b/routers/web/explore/code.go
@@ -0,0 +1,139 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package explore
+
+import (
+ "net/http"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ code_indexer "code.gitea.io/gitea/modules/indexer/code"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+const (
+ // tplExploreCode explore code page template
+ tplExploreCode base.TplName = "explore/code"
+)
+
+// Code render explore code page
+func Code(ctx *context.Context) {
+ if !setting.Indexer.RepoIndexerEnabled {
+ ctx.Redirect(setting.AppSubURL+"/explore", 302)
+ return
+ }
+
+ ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+ ctx.Data["Title"] = ctx.Tr("explore")
+ ctx.Data["PageIsExplore"] = true
+ ctx.Data["PageIsExploreCode"] = true
+
+ language := strings.TrimSpace(ctx.Query("l"))
+ keyword := strings.TrimSpace(ctx.Query("q"))
+ page := ctx.QueryInt("page")
+ if page <= 0 {
+ page = 1
+ }
+
+ queryType := strings.TrimSpace(ctx.Query("t"))
+ isMatch := queryType == "match"
+
+ var (
+ repoIDs []int64
+ err error
+ isAdmin bool
+ )
+ if ctx.User != nil {
+ isAdmin = ctx.User.IsAdmin
+ }
+
+ // guest user or non-admin user
+ if ctx.User == nil || !isAdmin {
+ repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.User)
+ if err != nil {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+ }
+
+ var (
+ total int
+ searchResults []*code_indexer.Result
+ searchResultLanguages []*code_indexer.SearchResultLanguages
+ )
+
+ // if non-admin login user, we need check UnitTypeCode at first
+ if ctx.User != nil && len(repoIDs) > 0 {
+ repoMaps, err := models.GetRepositoriesMapByIDs(repoIDs)
+ if err != nil {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+
+ var rightRepoMap = make(map[int64]*models.Repository, len(repoMaps))
+ repoIDs = make([]int64, 0, len(repoMaps))
+ for id, repo := range repoMaps {
+ if repo.CheckUnitUser(ctx.User, models.UnitTypeCode) {
+ rightRepoMap[id] = repo
+ repoIDs = append(repoIDs, id)
+ }
+ }
+
+ ctx.Data["RepoMaps"] = rightRepoMap
+
+ total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
+ if err != nil {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+ // if non-login user or isAdmin, no need to check UnitTypeCode
+ } else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
+ total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
+ if err != nil {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+
+ var loadRepoIDs = make([]int64, 0, len(searchResults))
+ for _, result := range searchResults {
+ var find bool
+ for _, id := range loadRepoIDs {
+ if id == result.RepoID {
+ find = true
+ break
+ }
+ }
+ if !find {
+ loadRepoIDs = append(loadRepoIDs, result.RepoID)
+ }
+ }
+
+ repoMaps, err := models.GetRepositoriesMapByIDs(loadRepoIDs)
+ if err != nil {
+ ctx.ServerError("SearchResults", err)
+ return
+ }
+
+ ctx.Data["RepoMaps"] = repoMaps
+ }
+
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["Language"] = language
+ ctx.Data["queryType"] = queryType
+ ctx.Data["SearchResults"] = searchResults
+ ctx.Data["SearchResultLanguages"] = searchResultLanguages
+ ctx.Data["RequireHighlightJS"] = true
+ ctx.Data["PageIsViewCode"] = true
+
+ pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
+ pager.SetDefaultParams(ctx)
+ pager.AddParam(ctx, "l", "Language")
+ ctx.Data["Page"] = pager
+
+ ctx.HTML(http.StatusOK, tplExploreCode)
+}
diff --git a/routers/web/explore/org.go b/routers/web/explore/org.go
new file mode 100644
index 0000000000..470e0eb853
--- /dev/null
+++ b/routers/web/explore/org.go
@@ -0,0 +1,39 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package explore
+
+import (
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/structs"
+)
+
+const (
+ // tplExploreOrganizations explore organizations page template
+ tplExploreOrganizations base.TplName = "explore/organizations"
+)
+
+// Organizations render explore organizations page
+func Organizations(ctx *context.Context) {
+ ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
+ ctx.Data["Title"] = ctx.Tr("explore")
+ ctx.Data["PageIsExplore"] = true
+ ctx.Data["PageIsExploreOrganizations"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ visibleTypes := []structs.VisibleType{structs.VisibleTypePublic}
+ if ctx.User != nil {
+ visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate)
+ }
+
+ RenderUserSearch(ctx, &models.SearchUserOptions{
+ Actor: ctx.User,
+ Type: models.UserTypeOrganization,
+ ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
+ Visible: visibleTypes,
+ }, tplExploreOrganizations)
+}
diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go
new file mode 100644
index 0000000000..e9efae5688
--- /dev/null
+++ b/routers/web/explore/repo.go
@@ -0,0 +1,131 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package explore
+
+import (
+ "net/http"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+)
+
+const (
+ // tplExploreRepos explore repositories page template
+ tplExploreRepos base.TplName = "explore/repos"
+)
+
+// RepoSearchOptions when calling search repositories
+type RepoSearchOptions struct {
+ OwnerID int64
+ Private bool
+ Restricted bool
+ PageSize int
+ TplName base.TplName
+}
+
+// RenderRepoSearch render repositories search page
+func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
+ page := ctx.QueryInt("page")
+ if page <= 0 {
+ page = 1
+ }
+
+ var (
+ repos []*models.Repository
+ count int64
+ err error
+ orderBy models.SearchOrderBy
+ )
+
+ ctx.Data["SortType"] = ctx.Query("sort")
+ switch ctx.Query("sort") {
+ case "newest":
+ orderBy = models.SearchOrderByNewest
+ case "oldest":
+ orderBy = models.SearchOrderByOldest
+ case "recentupdate":
+ orderBy = models.SearchOrderByRecentUpdated
+ case "leastupdate":
+ orderBy = models.SearchOrderByLeastUpdated
+ case "reversealphabetically":
+ orderBy = models.SearchOrderByAlphabeticallyReverse
+ case "alphabetically":
+ orderBy = models.SearchOrderByAlphabetically
+ case "reversesize":
+ orderBy = models.SearchOrderBySizeReverse
+ case "size":
+ orderBy = models.SearchOrderBySize
+ case "moststars":
+ orderBy = models.SearchOrderByStarsReverse
+ case "feweststars":
+ orderBy = models.SearchOrderByStars
+ case "mostforks":
+ orderBy = models.SearchOrderByForksReverse
+ case "fewestforks":
+ orderBy = models.SearchOrderByForks
+ default:
+ ctx.Data["SortType"] = "recentupdate"
+ orderBy = models.SearchOrderByRecentUpdated
+ }
+
+ keyword := strings.Trim(ctx.Query("q"), " ")
+ topicOnly := ctx.QueryBool("topic")
+ ctx.Data["TopicOnly"] = topicOnly
+
+ repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
+ ListOptions: models.ListOptions{
+ Page: page,
+ PageSize: opts.PageSize,
+ },
+ Actor: ctx.User,
+ OrderBy: orderBy,
+ Private: opts.Private,
+ Keyword: keyword,
+ OwnerID: opts.OwnerID,
+ AllPublic: true,
+ AllLimited: true,
+ TopicOnly: topicOnly,
+ IncludeDescription: setting.UI.SearchRepoDescription,
+ })
+ if err != nil {
+ ctx.ServerError("SearchRepository", err)
+ return
+ }
+ ctx.Data["Keyword"] = keyword
+ ctx.Data["Total"] = count
+ ctx.Data["Repos"] = repos
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ pager := context.NewPagination(int(count), opts.PageSize, page, 5)
+ pager.SetDefaultParams(ctx)
+ pager.AddParam(ctx, "topic", "TopicOnly")
+ ctx.Data["Page"] = pager
+
+ ctx.HTML(http.StatusOK, opts.TplName)
+}
+
+// Repos render explore repositories page
+func Repos(ctx *context.Context) {
+ ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage
+ ctx.Data["Title"] = ctx.Tr("explore")
+ ctx.Data["PageIsExplore"] = true
+ ctx.Data["PageIsExploreRepositories"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ var ownerID int64
+ if ctx.User != nil && !ctx.User.IsAdmin {
+ ownerID = ctx.User.ID
+ }
+
+ RenderRepoSearch(ctx, &RepoSearchOptions{
+ PageSize: setting.UI.ExplorePagingNum,
+ OwnerID: ownerID,
+ Private: ctx.User != nil,
+ TplName: tplExploreRepos,
+ })
+}
diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go
new file mode 100644
index 0000000000..52f543fe66
--- /dev/null
+++ b/routers/web/explore/user.go
@@ -0,0 +1,107 @@
+// Copyright 2021 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package explore
+
+import (
+ "bytes"
+ "net/http"
+ "strings"
+
+ "code.gitea.io/gitea/models"
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/structs"
+ "code.gitea.io/gitea/modules/util"
+)
+
+const (
+ // tplExploreUsers explore users page template
+ tplExploreUsers base.TplName = "explore/users"
+)
+
+var (
+ nullByte = []byte{0x00}
+)
+
+func isKeywordValid(keyword string) bool {
+ return !bytes.Contains([]byte(keyword), nullByte)
+}
+
+// RenderUserSearch render user search page
+func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplName base.TplName) {
+ opts.Page = ctx.QueryInt("page")
+ if opts.Page <= 1 {
+ opts.Page = 1
+ }
+
+ var (
+ users []*models.User
+ count int64
+ err error
+ orderBy models.SearchOrderBy
+ )
+
+ ctx.Data["SortType"] = ctx.Query("sort")
+ switch ctx.Query("sort") {
+ case "newest":
+ orderBy = models.SearchOrderByIDReverse
+ case "oldest":
+ orderBy = models.SearchOrderByID
+ case "recentupdate":
+ orderBy = models.SearchOrderByRecentUpdated
+ case "leastupdate":
+ orderBy = models.SearchOrderByLeastUpdated
+ case "reversealphabetically":
+ orderBy = models.SearchOrderByAlphabeticallyReverse
+ case "alphabetically":
+ orderBy = models.SearchOrderByAlphabetically
+ default:
+ ctx.Data["SortType"] = "alphabetically"
+ orderBy = models.SearchOrderByAlphabetically
+ }
+
+ opts.Keyword = strings.Trim(ctx.Query("q"), " ")
+ opts.OrderBy = orderBy
+ if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
+ users, count, err = models.SearchUsers(opts)
+ if err != nil {
+ ctx.ServerError("SearchUsers", err)
+ return
+ }
+ }
+ ctx.Data["Keyword"] = opts.Keyword
+ ctx.Data["Total"] = count
+ ctx.Data["Users"] = users
+ ctx.Data["UsersTwoFaStatus"] = models.UserList(users).GetTwoFaStatus()
+ ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
+ pager.SetDefaultParams(ctx)
+ ctx.Data["Page"] = pager
+
+ ctx.HTML(http.StatusOK, tplName)
+}
+
+// Users render explore users page
+func Users(ctx *context.Context) {
+ if setting.Service.Explore.DisableUsersPage {
+ ctx.Redirect(setting.AppSubURL + "/explore/repos")
+ return
+ }
+ ctx.Data["Title"] = ctx.Tr("explore")
+ ctx.Data["PageIsExplore"] = true
+ ctx.Data["PageIsExploreUsers"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+
+ RenderUserSearch(ctx, &models.SearchUserOptions{
+ Actor: ctx.User,
+ Type: models.UserTypeIndividual,
+ ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
+ IsActive: util.OptionalBoolTrue,
+ Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
+ }, tplExploreUsers)
+}
diff --git a/routers/routes/goget.go b/routers/web/goget.go
index 518f5e3073..77934e7f55 100644
--- a/routers/routes/goget.go
+++ b/routers/web/goget.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 routes
+package web
import (
"net/http"
diff --git a/routers/web/home.go b/routers/web/home.go
new file mode 100644
index 0000000000..f50197691f
--- /dev/null
+++ b/routers/web/home.go
@@ -0,0 +1,65 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package web
+
+import (
+ "net/http"
+
+ "code.gitea.io/gitea/modules/base"
+ "code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/web/middleware"
+ "code.gitea.io/gitea/routers/web/user"
+)
+
+const (
+ // tplHome home page template
+ tplHome base.TplName = "home"
+)
+
+// Home render home page
+func Home(ctx *context.Context) {
+ if ctx.IsSigned {
+ if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+ ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
+ ctx.HTML(http.StatusOK, user.TplActivate)
+ } else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
+ log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
+ ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
+ ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
+ } else if ctx.User.MustChangePassword {
+ ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
+ ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
+ middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
+ ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
+ } else {
+ user.Dashboard(ctx)
+ }
+ return
+ // Check non-logged users landing page.
+ } else if setting.LandingPageURL != setting.LandingPageHome {
+ ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
+ return
+ }
+
+ // Check auto-login.
+ uname := ctx.GetCookie(setting.CookieUserName)
+ if len(uname) != 0 {
+ ctx.Redirect(setting.AppSubURL + "/user/login")
+ return
+ }
+
+ ctx.Data["PageIsHome"] = true
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+ ctx.HTML(http.StatusOK, tplHome)
+}
+
+// NotFound render 404 page
+func NotFound(ctx *context.Context) {
+ ctx.Data["Title"] = "Page Not Found"
+ ctx.NotFound("home.NotFound", nil)
+}
diff --git a/routers/metrics.go b/routers/web/metrics.go
index db2fb8de44..37558ee337 100644
--- a/routers/metrics.go
+++ b/routers/web/metrics.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 routers
+package web
import (
"crypto/subtle"
diff --git a/routers/org/home.go b/routers/web/org/home.go
index d84ae870ab..d84ae870ab 100644
--- a/routers/org/home.go
+++ b/routers/web/org/home.go
diff --git a/routers/org/members.go b/routers/web/org/members.go
index 934529d7d7..934529d7d7 100644
--- a/routers/org/members.go
+++ b/routers/web/org/members.go
diff --git a/routers/org/org.go b/routers/web/org/org.go
index beba3daca4..beba3daca4 100644
--- a/routers/org/org.go
+++ b/routers/web/org/org.go
diff --git a/routers/org/org_labels.go b/routers/web/org/org_labels.go
index 26e232bcc9..26e232bcc9 100644
--- a/routers/org/org_labels.go
+++ b/routers/web/org/org_labels.go
diff --git a/routers/org/setting.go b/routers/web/org/setting.go
index 0e28a93ace..aed90c66f7 100644
--- a/routers/org/setting.go
+++ b/routers/web/org/setting.go
@@ -15,7 +15,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/web"
- userSetting "code.gitea.io/gitea/routers/user/setting"
+ userSetting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/services/forms"
)
diff --git a/routers/org/teams.go b/routers/web/org/teams.go
index e612cd767c..e612cd767c 100644
--- a/routers/org/teams.go
+++ b/routers/web/org/teams.go
diff --git a/routers/repo/activity.go b/routers/web/repo/activity.go
index dcb7bf57cd..dcb7bf57cd 100644
--- a/routers/repo/activity.go
+++ b/routers/web/repo/activity.go
diff --git a/routers/repo/attachment.go b/routers/web/repo/attachment.go
index f53e7450ae..5becbea271 100644
--- a/routers/repo/attachment.go
+++ b/routers/web/repo/attachment.go
@@ -15,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/upload"
+ "code.gitea.io/gitea/routers/common"
)
// UploadIssueAttachment response for Issue/PR attachments
@@ -152,7 +153,7 @@ func GetAttachment(ctx *context.Context) {
}
defer fr.Close()
- if err = ServeData(ctx, attach.Name, attach.Size, fr); err != nil {
+ if err = common.ServeData(ctx, attach.Name, attach.Size, fr); err != nil {
ctx.ServerError("ServeData", err)
return
}
diff --git a/routers/repo/blame.go b/routers/web/repo/blame.go
index 1a3e1dcb9c..1a3e1dcb9c 100644
--- a/routers/repo/blame.go
+++ b/routers/web/repo/blame.go
diff --git a/routers/repo/branch.go b/routers/web/repo/branch.go
index 4625b1a272..4625b1a272 100644
--- a/routers/repo/branch.go
+++ b/routers/web/repo/branch.go
diff --git a/routers/repo/commit.go b/routers/web/repo/commit.go
index 3e6148bcbb..3e6148bcbb 100644
--- a/routers/repo/commit.go
+++ b/routers/web/repo/commit.go
diff --git a/routers/repo/compare.go b/routers/web/repo/compare.go
index f53a31769d..f53a31769d 100644
--- a/routers/repo/compare.go
+++ b/routers/web/repo/compare.go
diff --git a/routers/repo/download.go b/routers/web/repo/download.go
index bbf4684b2e..6f43d4b839 100644
--- a/routers/repo/download.go
+++ b/routers/web/repo/download.go
@@ -6,102 +6,14 @@
package repo
import (
- "fmt"
- "io"
- "path"
- "path/filepath"
- "strings"
-
- "code.gitea.io/gitea/modules/charset"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/httpcache"
"code.gitea.io/gitea/modules/lfs"
"code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/typesniffer"
+ "code.gitea.io/gitea/routers/common"
)
-// ServeData download file from io.Reader
-func ServeData(ctx *context.Context, name string, size int64, reader io.Reader) error {
- buf := make([]byte, 1024)
- n, err := reader.Read(buf)
- if err != nil && err != io.EOF {
- return err
- }
- if n >= 0 {
- buf = buf[:n]
- }
-
- ctx.Resp.Header().Set("Cache-Control", "public,max-age=86400")
-
- if size >= 0 {
- ctx.Resp.Header().Set("Content-Length", fmt.Sprintf("%d", size))
- } else {
- log.Error("ServeData called to serve data: %s with size < 0: %d", name, size)
- }
- name = path.Base(name)
-
- // Google Chrome dislike commas in filenames, so let's change it to a space
- name = strings.ReplaceAll(name, ",", " ")
-
- st := typesniffer.DetectContentType(buf)
-
- if st.IsText() || ctx.QueryBool("render") {
- cs, err := charset.DetectEncoding(buf)
- if err != nil {
- log.Error("Detect raw file %s charset failed: %v, using by default utf-8", name, err)
- cs = "utf-8"
- }
- ctx.Resp.Header().Set("Content-Type", "text/plain; charset="+strings.ToLower(cs))
- } else {
- ctx.Resp.Header().Set("Access-Control-Expose-Headers", "Content-Disposition")
-
- if (st.IsImage() || st.IsPDF()) && (setting.UI.SVG.Enabled || !st.IsSvgImage()) {
- ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, name))
- if st.IsSvgImage() {
- ctx.Resp.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
- ctx.Resp.Header().Set("X-Content-Type-Options", "nosniff")
- ctx.Resp.Header().Set("Content-Type", typesniffer.SvgMimeType)
- }
- } else {
- ctx.Resp.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, name))
- if setting.MimeTypeMap.Enabled {
- fileExtension := strings.ToLower(filepath.Ext(name))
- if mimetype, ok := setting.MimeTypeMap.Map[fileExtension]; ok {
- ctx.Resp.Header().Set("Content-Type", mimetype)
- }
- }
- }
- }
-
- _, err = ctx.Resp.Write(buf)
- if err != nil {
- return err
- }
- _, err = io.Copy(ctx.Resp, reader)
- return err
-}
-
-// ServeBlob download a git.Blob
-func ServeBlob(ctx *context.Context, blob *git.Blob) error {
- if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`) {
- return nil
- }
-
- dataRc, err := blob.DataAsync()
- if err != nil {
- return err
- }
- defer func() {
- if err = dataRc.Close(); err != nil {
- log.Error("ServeBlob: Close: %v", err)
- }
- }()
-
- return ServeData(ctx, ctx.Repo.TreePath, blob.Size(), dataRc)
-}
-
// ServeBlobOrLFS download a git.Blob redirecting to LFS if necessary
func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`) {
@@ -130,7 +42,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
log.Error("ServeBlobOrLFS: Close: %v", err)
}
closed = true
- return ServeBlob(ctx, blob)
+ return common.ServeBlob(ctx, blob)
}
if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+pointer.Oid+`"`) {
return nil
@@ -144,14 +56,14 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob) error {
log.Error("ServeBlobOrLFS: Close: %v", err)
}
}()
- return ServeData(ctx, ctx.Repo.TreePath, meta.Size, lfsDataRc)
+ return common.ServeData(ctx, ctx.Repo.TreePath, meta.Size, lfsDataRc)
}
if err = dataRc.Close(); err != nil {
log.Error("ServeBlobOrLFS: Close: %v", err)
}
closed = true
- return ServeBlob(ctx, blob)
+ return common.ServeBlob(ctx, blob)
}
// SingleDownload download a file by repos path
@@ -165,7 +77,7 @@ func SingleDownload(ctx *context.Context) {
}
return
}
- if err = ServeBlob(ctx, blob); err != nil {
+ if err = common.ServeBlob(ctx, blob); err != nil {
ctx.ServerError("ServeBlob", err)
}
}
@@ -197,7 +109,7 @@ func DownloadByID(ctx *context.Context) {
}
return
}
- if err = ServeBlob(ctx, blob); err != nil {
+ if err = common.ServeBlob(ctx, blob); err != nil {
ctx.ServerError("ServeBlob", err)
}
}
diff --git a/routers/repo/editor.go b/routers/web/repo/editor.go
index 0f978c7b01..0f978c7b01 100644
--- a/routers/repo/editor.go
+++ b/routers/web/repo/editor.go
diff --git a/routers/repo/editor_test.go b/routers/web/repo/editor_test.go
index ec7aee1e77..ec7aee1e77 100644
--- a/routers/repo/editor_test.go
+++ b/routers/web/repo/editor_test.go
diff --git a/routers/repo/http.go b/routers/web/repo/http.go
index 30d382b8ef..30d382b8ef 100644
--- a/routers/repo/http.go
+++ b/routers/web/repo/http.go
diff --git a/routers/repo/issue.go b/routers/web/repo/issue.go
index fd2877e706..fd2877e706 100644
--- a/routers/repo/issue.go
+++ b/routers/web/repo/issue.go
diff --git a/routers/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go
index 8a83c7bae3..8a83c7bae3 100644
--- a/routers/repo/issue_dependency.go
+++ b/routers/web/repo/issue_dependency.go
diff --git a/routers/repo/issue_label.go b/routers/web/repo/issue_label.go
index 73612606c8..73612606c8 100644
--- a/routers/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
diff --git a/routers/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go
index bf9e72a6f4..bf9e72a6f4 100644
--- a/routers/repo/issue_label_test.go
+++ b/routers/web/repo/issue_label_test.go
diff --git a/routers/repo/issue_lock.go b/routers/web/repo/issue_lock.go
index 36894b4be3..36894b4be3 100644
--- a/routers/repo/issue_lock.go
+++ b/routers/web/repo/issue_lock.go
diff --git a/routers/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go
index b8efb3b841..b8efb3b841 100644
--- a/routers/repo/issue_stopwatch.go
+++ b/routers/web/repo/issue_stopwatch.go
diff --git a/routers/repo/issue_test.go b/routers/web/repo/issue_test.go
index 7fb837fa12..7fb837fa12 100644
--- a/routers/repo/issue_test.go
+++ b/routers/web/repo/issue_test.go
diff --git a/routers/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go
index 3770cd7b4e..3770cd7b4e 100644
--- a/routers/repo/issue_timetrack.go
+++ b/routers/web/repo/issue_timetrack.go
diff --git a/routers/repo/issue_watch.go b/routers/web/repo/issue_watch.go
index dabbff842b..dabbff842b 100644
--- a/routers/repo/issue_watch.go
+++ b/routers/web/repo/issue_watch.go
diff --git a/routers/repo/lfs.go b/routers/web/repo/lfs.go
index 173ffb773f..173ffb773f 100644
--- a/routers/repo/lfs.go
+++ b/routers/web/repo/lfs.go
diff --git a/routers/repo/main_test.go b/routers/web/repo/main_test.go
index 04bbeeb211..47f266365f 100644
--- a/routers/repo/main_test.go
+++ b/routers/web/repo/main_test.go
@@ -12,5 +12,5 @@ import (
)
func TestMain(m *testing.M) {
- models.MainTest(m, filepath.Join("..", ".."))
+ models.MainTest(m, filepath.Join("..", "..", ".."))
}
diff --git a/routers/repo/middlewares.go b/routers/web/repo/middlewares.go
index 1b95a13ba2..1b95a13ba2 100644
--- a/routers/repo/middlewares.go
+++ b/routers/web/repo/middlewares.go
diff --git a/routers/repo/migrate.go b/routers/web/repo/migrate.go
index 24d4ef4099..24d4ef4099 100644
--- a/routers/repo/migrate.go
+++ b/routers/web/repo/migrate.go
diff --git a/routers/repo/milestone.go b/routers/web/repo/milestone.go
index bb6b310cbe..bb6b310cbe 100644
--- a/routers/repo/milestone.go
+++ b/routers/web/repo/milestone.go
diff --git a/routers/repo/projects.go b/routers/web/repo/projects.go
index eb0719995c..eb0719995c 100644
--- a/routers/repo/projects.go
+++ b/routers/web/repo/projects.go
diff --git a/routers/repo/projects_test.go b/routers/web/repo/projects_test.go
index c43cf6d952..c43cf6d952 100644
--- a/routers/repo/projects_test.go
+++ b/routers/web/repo/projects_test.go
diff --git a/routers/repo/pull.go b/routers/web/repo/pull.go
index 28f94c8417..28f94c8417 100644
--- a/routers/repo/pull.go
+++ b/routers/web/repo/pull.go
diff --git a/routers/repo/pull_review.go b/routers/web/repo/pull_review.go
index 9e505c3db3..9e505c3db3 100644
--- a/routers/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
diff --git a/routers/repo/release.go b/routers/web/repo/release.go
index b7730e4ee2..b7730e4ee2 100644
--- a/routers/repo/release.go
+++ b/routers/web/repo/release.go
diff --git a/routers/repo/release_test.go b/routers/web/repo/release_test.go
index 004a6ef540..004a6ef540 100644
--- a/routers/repo/release_test.go
+++ b/routers/web/repo/release_test.go
diff --git a/routers/repo/repo.go b/routers/web/repo/repo.go
index 69471a83d3..f149e92a8b 100644
--- a/routers/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -364,30 +364,6 @@ func RedirectDownload(ctx *context.Context) {
ctx.Error(http.StatusNotFound)
}
-// Download an archive of a repository
-func Download(ctx *context.Context) {
- uri := ctx.Params("*")
- aReq := archiver_service.DeriveRequestFrom(ctx, uri)
-
- if aReq == nil {
- ctx.Error(http.StatusNotFound)
- return
- }
-
- downloadName := ctx.Repo.Repository.Name + "-" + aReq.GetArchiveName()
- complete := aReq.IsComplete()
- if !complete {
- aReq = archiver_service.ArchiveRepository(aReq)
- complete = aReq.WaitForCompletion(ctx)
- }
-
- if complete {
- ctx.ServeFile(aReq.GetArchivePath(), downloadName)
- } else {
- ctx.Error(http.StatusNotFound)
- }
-}
-
// InitiateDownload will enqueue an archival request, as needed. It may submit
// a request that's already in-progress, but the archiver service will just
// kind of drop it on the floor if this is the case.
diff --git a/routers/repo/search.go b/routers/web/repo/search.go
index d9604bade0..d9604bade0 100644
--- a/routers/repo/search.go
+++ b/routers/web/repo/search.go
diff --git a/routers/repo/setting.go b/routers/web/repo/setting.go
index 21a82491fe..21a82491fe 100644
--- a/routers/repo/setting.go
+++ b/routers/web/repo/setting.go
diff --git a/routers/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go
index fba2c095cf..fba2c095cf 100644
--- a/routers/repo/setting_protected_branch.go
+++ b/routers/web/repo/setting_protected_branch.go
diff --git a/routers/repo/settings_test.go b/routers/web/repo/settings_test.go
index 5190f12d5d..5190f12d5d 100644
--- a/routers/repo/settings_test.go
+++ b/routers/web/repo/settings_test.go
diff --git a/routers/repo/topic.go b/routers/web/repo/topic.go
index 1d99b65094..1d99b65094 100644
--- a/routers/repo/topic.go
+++ b/routers/web/repo/topic.go
diff --git a/routers/repo/view.go b/routers/web/repo/view.go
index cd5b0f43ed..cd5b0f43ed 100644
--- a/routers/repo/view.go
+++ b/routers/web/repo/view.go
diff --git a/routers/repo/webhook.go b/routers/web/repo/webhook.go
index fe16d249eb..fe16d249eb 100644
--- a/routers/repo/webhook.go
+++ b/routers/web/repo/webhook.go
diff --git a/routers/repo/wiki.go b/routers/web/repo/wiki.go
index 1bdd06dce5..cceb8451e5 100644
--- a/routers/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -24,6 +24,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
+ "code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/forms"
wiki_service "code.gitea.io/gitea/services/wiki"
)
@@ -558,7 +559,7 @@ func WikiRaw(ctx *context.Context) {
}
if entry != nil {
- if err = ServeBlob(ctx, entry.Blob()); err != nil {
+ if err = common.ServeBlob(ctx, entry.Blob()); err != nil {
ctx.ServerError("ServeBlob", err)
}
return
diff --git a/routers/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index 8934a6619f..8934a6619f 100644
--- a/routers/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
diff --git a/routers/swagger_json.go b/routers/web/swagger_json.go
index 78c7fb1e24..82d72698c6 100644
--- a/routers/swagger_json.go
+++ b/routers/web/swagger_json.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 routers
+package web
import (
"net/http"
diff --git a/routers/user/auth.go b/routers/web/user/auth.go
index 827b7cdef0..827b7cdef0 100644
--- a/routers/user/auth.go
+++ b/routers/web/user/auth.go
diff --git a/routers/user/auth_openid.go b/routers/web/user/auth_openid.go
index 1a73a08c48..1a73a08c48 100644
--- a/routers/user/auth_openid.go
+++ b/routers/web/user/auth_openid.go
diff --git a/routers/user/avatar.go b/routers/web/user/avatar.go
index 4287589d1a..4287589d1a 100644
--- a/routers/user/avatar.go
+++ b/routers/web/user/avatar.go
diff --git a/routers/user/home.go b/routers/web/user/home.go
index acf73f82fe..acf73f82fe 100644
--- a/routers/user/home.go
+++ b/routers/web/user/home.go
diff --git a/routers/user/home_test.go b/routers/web/user/home_test.go
index b0109c354f..b0109c354f 100644
--- a/routers/user/home_test.go
+++ b/routers/web/user/home_test.go
diff --git a/routers/user/main_test.go b/routers/web/user/main_test.go
index ed0724dc77..be17dd1f31 100644
--- a/routers/user/main_test.go
+++ b/routers/web/user/main_test.go
@@ -12,5 +12,5 @@ import (
)
func TestMain(m *testing.M) {
- models.MainTest(m, filepath.Join("..", ".."))
+ models.MainTest(m, filepath.Join("..", "..", ".."))
}
diff --git a/routers/user/notification.go b/routers/web/user/notification.go
index 523e945db9..523e945db9 100644
--- a/routers/user/notification.go
+++ b/routers/web/user/notification.go
diff --git a/routers/user/oauth.go b/routers/web/user/oauth.go
index 3ef5a56c01..3ef5a56c01 100644
--- a/routers/user/oauth.go
+++ b/routers/web/user/oauth.go
diff --git a/routers/user/profile.go b/routers/web/user/profile.go
index 8ff1ee24ad..e66820e131 100644
--- a/routers/user/profile.go
+++ b/routers/web/user/profile.go
@@ -17,7 +17,7 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
- "code.gitea.io/gitea/routers/org"
+ "code.gitea.io/gitea/routers/web/org"
)
// GetUserByName get user by name
diff --git a/routers/user/setting/account.go b/routers/web/user/setting/account.go
index 48ab37d936..48ab37d936 100644
--- a/routers/user/setting/account.go
+++ b/routers/web/user/setting/account.go
diff --git a/routers/user/setting/account_test.go b/routers/web/user/setting/account_test.go
index 25b68da762..25b68da762 100644
--- a/routers/user/setting/account_test.go
+++ b/routers/web/user/setting/account_test.go
diff --git a/routers/user/setting/adopt.go b/routers/web/user/setting/adopt.go
index b2d918784f..b2d918784f 100644
--- a/routers/user/setting/adopt.go
+++ b/routers/web/user/setting/adopt.go
diff --git a/routers/user/setting/applications.go b/routers/web/user/setting/applications.go
index 4161efdea4..4161efdea4 100644
--- a/routers/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
diff --git a/routers/user/setting/keys.go b/routers/web/user/setting/keys.go
index e56a33afcb..e56a33afcb 100644
--- a/routers/user/setting/keys.go
+++ b/routers/web/user/setting/keys.go
diff --git a/routers/admin/main_test.go b/routers/web/user/setting/main_test.go
index 9a7191d471..daa3f7fe5b 100644
--- a/routers/admin/main_test.go
+++ b/routers/web/user/setting/main_test.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 admin
+package setting
import (
"path/filepath"
@@ -12,5 +12,5 @@ import (
)
func TestMain(m *testing.M) {
- models.MainTest(m, filepath.Join("..", ".."))
+ models.MainTest(m, filepath.Join("..", "..", "..", ".."))
}
diff --git a/routers/user/setting/oauth2.go b/routers/web/user/setting/oauth2.go
index c8db6e87f2..c8db6e87f2 100644
--- a/routers/user/setting/oauth2.go
+++ b/routers/web/user/setting/oauth2.go
diff --git a/routers/user/setting/profile.go b/routers/web/user/setting/profile.go
index 20042caca4..20042caca4 100644
--- a/routers/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
diff --git a/routers/user/setting/security.go b/routers/web/user/setting/security.go
index 7753c5c161..7753c5c161 100644
--- a/routers/user/setting/security.go
+++ b/routers/web/user/setting/security.go
diff --git a/routers/user/setting/security_openid.go b/routers/web/user/setting/security_openid.go
index 74dba12825..74dba12825 100644
--- a/routers/user/setting/security_openid.go
+++ b/routers/web/user/setting/security_openid.go
diff --git a/routers/user/setting/security_twofa.go b/routers/web/user/setting/security_twofa.go
index 7b08a05939..7b08a05939 100644
--- a/routers/user/setting/security_twofa.go
+++ b/routers/web/user/setting/security_twofa.go
diff --git a/routers/user/setting/security_u2f.go b/routers/web/user/setting/security_u2f.go
index f9e35549fb..f9e35549fb 100644
--- a/routers/user/setting/security_u2f.go
+++ b/routers/web/user/setting/security_u2f.go
diff --git a/routers/user/task.go b/routers/web/user/task.go
index b8df5d99c7..b8df5d99c7 100644
--- a/routers/user/task.go
+++ b/routers/web/user/task.go
diff --git a/routers/routes/web.go b/routers/web/web.go
index fbc41d547d..6c0141eef3 100644
--- a/routers/routes/web.go
+++ b/routers/web/web.go
@@ -2,15 +2,13 @@
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
-package routes
+package web
import (
"encoding/gob"
- "fmt"
"net/http"
"os"
"path"
- "strings"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
@@ -23,17 +21,16 @@ import (
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
- "code.gitea.io/gitea/routers"
- "code.gitea.io/gitea/routers/admin"
- apiv1 "code.gitea.io/gitea/routers/api/v1"
"code.gitea.io/gitea/routers/api/v1/misc"
- "code.gitea.io/gitea/routers/dev"
- "code.gitea.io/gitea/routers/events"
- "code.gitea.io/gitea/routers/org"
- "code.gitea.io/gitea/routers/private"
- "code.gitea.io/gitea/routers/repo"
- "code.gitea.io/gitea/routers/user"
- userSetting "code.gitea.io/gitea/routers/user/setting"
+ "code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/routers/web/admin"
+ "code.gitea.io/gitea/routers/web/dev"
+ "code.gitea.io/gitea/routers/web/events"
+ "code.gitea.io/gitea/routers/web/explore"
+ "code.gitea.io/gitea/routers/web/org"
+ "code.gitea.io/gitea/routers/web/repo"
+ "code.gitea.io/gitea/routers/web/user"
+ userSetting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/lfs"
"code.gitea.io/gitea/services/mailer"
@@ -44,7 +41,6 @@ import (
"gitea.com/go-chi/captcha"
"gitea.com/go-chi/session"
"github.com/NYTimes/gziphandler"
- "github.com/chi-middleware/proxy"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
"github.com/prometheus/client_golang/prometheus"
@@ -56,74 +52,10 @@ const (
GzipMinSize = 1400
)
-func commonMiddlewares() []func(http.Handler) http.Handler {
- var handlers = []func(http.Handler) http.Handler{
- func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- next.ServeHTTP(context.NewResponse(resp), req)
- })
- },
- }
-
- if setting.ReverseProxyLimit > 0 {
- opt := proxy.NewForwardedHeadersOptions().
- WithForwardLimit(setting.ReverseProxyLimit).
- ClearTrustedProxies()
- for _, n := range setting.ReverseProxyTrustedProxies {
- if !strings.Contains(n, "/") {
- opt.AddTrustedProxy(n)
- } else {
- opt.AddTrustedNetwork(n)
- }
- }
- handlers = append(handlers, proxy.ForwardedHeaders(opt))
- }
-
- handlers = append(handlers, middleware.StripSlashes)
-
- if !setting.DisableRouterLog && setting.RouterLogLevel != log.NONE {
- if log.GetLogger("router").GetLevel() <= setting.RouterLogLevel {
- handlers = append(handlers, LoggerHandler(setting.RouterLogLevel))
- }
- }
- if setting.EnableAccessLog {
- handlers = append(handlers, context.AccessLogger())
- }
-
- handlers = append(handlers, func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
- // Why we need this? The Recovery() will try to render a beautiful
- // error page for user, but the process can still panic again, and other
- // middleware like session also may panic then we have to recover twice
- // and send a simple error page that should not panic any more.
- defer func() {
- if err := recover(); err != nil {
- combinedErr := fmt.Sprintf("PANIC: %v\n%s", err, string(log.Stack(2)))
- log.Error("%v", combinedErr)
- if setting.IsProd() {
- http.Error(resp, http.StatusText(500), 500)
- } else {
- http.Error(resp, combinedErr, 500)
- }
- }
- }()
- next.ServeHTTP(resp, req)
- })
- })
- return handlers
-}
-
-var corsHandler func(http.Handler) http.Handler
-
-// NormalRoutes represents non install routes
-func NormalRoutes() *web.Route {
- r := web.NewRoute()
- for _, middle := range commonMiddlewares() {
- r.Use(middle)
- }
-
+// CorsHandler return a http handler who set CORS options if enabled by config
+func CorsHandler() func(next http.Handler) http.Handler {
if setting.CORSConfig.Enabled {
- corsHandler = cors.Handler(cors.Options{
+ return cors.Handler(cors.Options{
//Scheme: setting.CORSConfig.Scheme, // FIXME: the cors middleware needs scheme option
AllowedOrigins: setting.CORSConfig.AllowDomain,
//setting.CORSConfig.AllowSubdomain // FIXME: the cors middleware needs allowSubdomain option
@@ -131,26 +63,21 @@ func NormalRoutes() *web.Route {
AllowCredentials: setting.CORSConfig.AllowCredentials,
MaxAge: int(setting.CORSConfig.MaxAge.Seconds()),
})
- } else {
- corsHandler = func(next http.Handler) http.Handler {
- return next
- }
}
- r.Mount("/", WebRoutes())
- r.Mount("/api/v1", apiv1.Routes())
- r.Mount("/api/internal", private.Routes())
- return r
+ return func(next http.Handler) http.Handler {
+ return next
+ }
}
-// WebRoutes returns all web routes
-func WebRoutes() *web.Route {
+// Routes returns all web routes
+func Routes() *web.Route {
routes := web.NewRoute()
routes.Use(public.AssetsHandler(&public.Options{
Directory: path.Join(setting.StaticRootPath, "public"),
Prefix: "/assets",
- CorsHandler: corsHandler,
+ CorsHandler: CorsHandler(),
}))
routes.Use(session.Sessioner(session.Options{
@@ -216,7 +143,7 @@ func WebRoutes() *web.Route {
c := metrics.NewCollector()
prometheus.MustRegister(c)
- routes.Get("/metrics", append(common, routers.Metrics)...)
+ routes.Get("/metrics", append(common, Metrics)...)
}
// Removed: toolbox.Toolboxer middleware will provide debug informations which seems unnecessary
@@ -297,16 +224,16 @@ func RegisterRoutes(m *web.Route) {
// Especially some AJAX requests, we can reduce middleware number to improve performance.
// Routers.
// for health check
- m.Get("/", routers.Home)
+ m.Get("/", Home)
m.Get("/.well-known/openid-configuration", user.OIDCWellKnown)
m.Group("/explore", func() {
m.Get("", func(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/explore/repos")
})
- m.Get("/repos", routers.ExploreRepos)
- m.Get("/users", routers.ExploreUsers)
- m.Get("/organizations", routers.ExploreOrganizations)
- m.Get("/code", routers.ExploreCode)
+ m.Get("/repos", explore.Repos)
+ m.Get("/users", explore.Users)
+ m.Get("/organizations", explore.Organizations)
+ m.Get("/code", explore.Code)
}, ignExploreSignIn)
m.Get("/issues", reqSignIn, user.Issues)
m.Get("/pulls", reqSignIn, user.Pulls)
@@ -363,7 +290,7 @@ func RegisterRoutes(m *web.Route) {
m.Post("/authorize", bindIgnErr(forms.AuthorizationForm{}), user.AuthorizeOAuth)
}, ignSignInAndCsrf, reqSignIn)
m.Get("/login/oauth/userinfo", ignSignInAndCsrf, user.InfoOAuth)
- m.Post("/login/oauth/access_token", corsHandler, bindIgnErr(forms.AccessTokenForm{}), ignSignInAndCsrf, user.AccessTokenOAuth)
+ m.Post("/login/oauth/access_token", CorsHandler(), bindIgnErr(forms.AccessTokenForm{}), ignSignInAndCsrf, user.AccessTokenOAuth)
m.Group("/user/settings", func() {
m.Get("", userSetting.Profile)
@@ -956,7 +883,7 @@ func RegisterRoutes(m *web.Route) {
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(models.UnitTypeCode))
m.Group("/archive", func() {
- m.Get("/*", repo.Download)
+ m.Get("/*", common.Download)
m.Post("/*", repo.InitiateDownload)
}, repo.MustBeNotEmpty, reqRepoCodeReader)
@@ -1091,9 +1018,6 @@ func RegisterRoutes(m *web.Route) {
}, reqSignIn)
if setting.API.EnableSwagger {
- m.Get("/swagger.v1.json", routers.SwaggerV1Json)
+ m.Get("/swagger.v1.json", SwaggerV1Json)
}
-
- // Not found handler.
- m.NotFound(web.Wrap(routers.NotFound))
}