Never use /api/v1 from Gitea UI Pages (#19318)
Reusing `/api/v1` from Gitea UI Pages have pros and cons. Pros: 1) Less code copy Cons: 1) API/v1 have to support shared session with page requests. 2) You need to consider for each other when you want to change something about api/v1 or page. This PR moves all dependencies to API/v1 from UI Pages. Partially replace #16052
This commit is contained in:
parent
bb7e0619c3
commit
783a021889
32 changed files with 1082 additions and 74 deletions
|
@ -191,22 +191,6 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
|
|||
}
|
||||
}
|
||||
|
||||
// SetTotalCountHeader set "X-Total-Count" header
|
||||
func (ctx *APIContext) SetTotalCountHeader(total int64) {
|
||||
ctx.RespHeader().Set("X-Total-Count", fmt.Sprint(total))
|
||||
ctx.AppendAccessControlExposeHeaders("X-Total-Count")
|
||||
}
|
||||
|
||||
// AppendAccessControlExposeHeaders append headers by name to "Access-Control-Expose-Headers" header
|
||||
func (ctx *APIContext) AppendAccessControlExposeHeaders(names ...string) {
|
||||
val := ctx.RespHeader().Get("Access-Control-Expose-Headers")
|
||||
if len(val) != 0 {
|
||||
ctx.RespHeader().Set("Access-Control-Expose-Headers", fmt.Sprintf("%s, %s", val, strings.Join(names, ", ")))
|
||||
} else {
|
||||
ctx.RespHeader().Set("Access-Control-Expose-Headers", strings.Join(names, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
// RequireCSRF requires a validated a CSRF token
|
||||
func (ctx *APIContext) RequireCSRF() {
|
||||
headerToken := ctx.Req.Header.Get(ctx.csrf.GetHeaderName())
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"io"
|
||||
|
@ -21,6 +22,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
|
@ -577,6 +579,22 @@ func (ctx *Context) Value(key interface{}) interface{} {
|
|||
return ctx.Req.Context().Value(key)
|
||||
}
|
||||
|
||||
// SetTotalCountHeader set "X-Total-Count" header
|
||||
func (ctx *Context) SetTotalCountHeader(total int64) {
|
||||
ctx.RespHeader().Set("X-Total-Count", fmt.Sprint(total))
|
||||
ctx.AppendAccessControlExposeHeaders("X-Total-Count")
|
||||
}
|
||||
|
||||
// AppendAccessControlExposeHeaders append headers by name to "Access-Control-Expose-Headers" header
|
||||
func (ctx *Context) AppendAccessControlExposeHeaders(names ...string) {
|
||||
val := ctx.RespHeader().Get("Access-Control-Expose-Headers")
|
||||
if len(val) != 0 {
|
||||
ctx.RespHeader().Set("Access-Control-Expose-Headers", fmt.Sprintf("%s, %s", val, strings.Join(names, ", ")))
|
||||
} else {
|
||||
ctx.RespHeader().Set("Access-Control-Expose-Headers", strings.Join(names, ", "))
|
||||
}
|
||||
}
|
||||
|
||||
// Handler represents a custom handler
|
||||
type Handler func(*Context)
|
||||
|
||||
|
@ -780,3 +798,21 @@ func Contexter() func(next http.Handler) http.Handler {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// SearchOrderByMap represents all possible search order
|
||||
var SearchOrderByMap = map[string]map[string]db.SearchOrderBy{
|
||||
"asc": {
|
||||
"alpha": db.SearchOrderByAlphabetically,
|
||||
"created": db.SearchOrderByOldest,
|
||||
"updated": db.SearchOrderByLeastUpdated,
|
||||
"size": db.SearchOrderBySize,
|
||||
"id": db.SearchOrderByID,
|
||||
},
|
||||
"desc": {
|
||||
"alpha": db.SearchOrderByAlphabeticallyReverse,
|
||||
"created": db.SearchOrderByNewest,
|
||||
"updated": db.SearchOrderByRecentUpdated,
|
||||
"size": db.SearchOrderBySizeReverse,
|
||||
"id": db.SearchOrderByIDReverse,
|
||||
},
|
||||
}
|
||||
|
|
56
modules/context/utils.go
Normal file
56
modules/context/utils.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2017 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 context
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetQueryBeforeSince return parsed time (unix format) from URL query's before and since
|
||||
func GetQueryBeforeSince(ctx *Context) (before, since int64, err error) {
|
||||
qCreatedBefore, err := prepareQueryArg(ctx, "before")
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
qCreatedSince, err := prepareQueryArg(ctx, "since")
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
before, err = parseTime(qCreatedBefore)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
since, err = parseTime(qCreatedSince)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return before, since, nil
|
||||
}
|
||||
|
||||
// parseTime parse time and return unix timestamp
|
||||
func parseTime(value string) (int64, error) {
|
||||
if len(value) != 0 {
|
||||
t, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if !t.IsZero() {
|
||||
return t.Unix(), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// prepareQueryArg unescape and trim a query arg
|
||||
func prepareQueryArg(ctx *Context, name string) (value string, err error) {
|
||||
value, err = url.PathUnescape(ctx.FormString(name))
|
||||
value = strings.TrimSpace(value)
|
||||
return
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue