mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-10-21 19:48:21 +00:00
Merge branch 'master' into bitbucketserver
Moving git username and password to the url Removing un-needed setting of Allows Moving log.Fatal to log.Error Removing panics Moving to https for gravatar # Conflicts: # remote/remote.go
This commit is contained in:
22
router/middleware/cache.go
Normal file
22
router/middleware/cache.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/drone/drone/cache"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/ianschenck/envflag"
|
||||
)
|
||||
|
||||
var ttl = envflag.Duration("CACHE_TTL", time.Minute*15, "")
|
||||
|
||||
// Cache is a middleware function that initializes the Cache and attaches to
|
||||
// the context of every http.Request.
|
||||
func Cache() gin.HandlerFunc {
|
||||
cc := cache.NewTTL(*ttl)
|
||||
return func(c *gin.Context) {
|
||||
cache.ToContext(c, cc)
|
||||
c.Next()
|
||||
}
|
||||
}
|
14
router/middleware/cache/cache.go
vendored
14
router/middleware/cache/cache.go
vendored
@@ -1,14 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/cache"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func Default() gin.HandlerFunc {
|
||||
cc := cache.Default()
|
||||
return func(c *gin.Context) {
|
||||
cache.ToContext(c, cc)
|
||||
c.Next()
|
||||
}
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/engine"
|
||||
"github.com/drone/drone/remote"
|
||||
"github.com/drone/drone/store"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func SetStore(s store.Store) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
store.ToContext(c, s)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func SetRemote(remote remote.Remote) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Set("remote", remote)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func Remote(c *gin.Context) remote.Remote {
|
||||
return c.MustGet("remote").(remote.Remote)
|
||||
}
|
||||
|
||||
func SetEngine(engine engine.Engine) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Set("engine", engine)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func Engine(c *gin.Context) engine.Engine {
|
||||
return c.MustGet("engine").(engine.Engine)
|
||||
}
|
28
router/middleware/engine.go
Normal file
28
router/middleware/engine.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/drone/drone/engine"
|
||||
"github.com/drone/drone/store"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Engine is a middleware function that initializes the Engine and attaches to
|
||||
// the context of every http.Request.
|
||||
func Engine() gin.HandlerFunc {
|
||||
var once sync.Once
|
||||
var engine_ engine.Engine
|
||||
|
||||
return func(c *gin.Context) {
|
||||
|
||||
once.Do(func() {
|
||||
store_ := store.FromContext(c)
|
||||
engine_ = engine.Load(store_)
|
||||
})
|
||||
|
||||
engine.ToContext(c, engine_)
|
||||
c.Next()
|
||||
}
|
||||
}
|
@@ -1,95 +0,0 @@
|
||||
package location
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Resolve is a middleware function that resolves the hostname
|
||||
// and scheme for the http.Request and adds to the context.
|
||||
func Resolve(c *gin.Context) {
|
||||
c.Set("host", resolveHost(c.Request))
|
||||
c.Set("scheme", resolveScheme(c.Request))
|
||||
c.Next()
|
||||
}
|
||||
|
||||
// parseHeader parses non unique headers value
|
||||
// from a http.Request and return a slice of the values
|
||||
// queried from the header
|
||||
func parseHeader(r *http.Request, header string, token string) (val []string) {
|
||||
for _, v := range r.Header[header] {
|
||||
options := strings.Split(v, ";")
|
||||
for _, o := range options {
|
||||
keyvalue := strings.Split(o, "=")
|
||||
var key, value string
|
||||
if len(keyvalue) > 1 {
|
||||
key, value = strings.TrimSpace(keyvalue[0]), strings.TrimSpace(keyvalue[1])
|
||||
}
|
||||
key = strings.ToLower(key)
|
||||
if key == token {
|
||||
val = append(val, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// resolveScheme is a helper function that evaluates the http.Request
|
||||
// and returns the scheme, HTTP or HTTPS. It is able to detect,
|
||||
// using the X-Forwarded-Proto, if the original request was HTTPS
|
||||
// and routed through a reverse proxy with SSL termination.
|
||||
func resolveScheme(r *http.Request) string {
|
||||
switch {
|
||||
case r.URL.Scheme == "https":
|
||||
return "https"
|
||||
case r.TLS != nil:
|
||||
return "https"
|
||||
case strings.HasPrefix(r.Proto, "HTTPS"):
|
||||
return "https"
|
||||
case r.Header.Get("X-Forwarded-Proto") == "https":
|
||||
return "https"
|
||||
case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "proto")) != 0 && parseHeader(r, "Forwarded", "proto")[0] == "https":
|
||||
return "https"
|
||||
default:
|
||||
return "http"
|
||||
}
|
||||
}
|
||||
|
||||
// resolveHost is a helper function that evaluates the http.Request
|
||||
// and returns the hostname. It is able to detect, using the
|
||||
// X-Forarded-For header, the original hostname when routed
|
||||
// through a reverse proxy.
|
||||
func resolveHost(r *http.Request) string {
|
||||
switch {
|
||||
case len(r.Host) != 0:
|
||||
return r.Host
|
||||
case len(r.URL.Host) != 0:
|
||||
return r.URL.Host
|
||||
case len(r.Header.Get("X-Forwarded-For")) != 0:
|
||||
return r.Header.Get("X-Forwarded-For")
|
||||
case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "for")) != 0:
|
||||
return parseHeader(r, "Forwarded", "for")[0]
|
||||
case len(r.Header.Get("X-Host")) != 0:
|
||||
return r.Header.Get("X-Host")
|
||||
case len(r.Header.Get("Forwarded")) != 0 && len(parseHeader(r, "Forwarded", "host")) != 0:
|
||||
return parseHeader(r, "Forwarded", "host")[0]
|
||||
case len(r.Header.Get("XFF")) != 0:
|
||||
return r.Header.Get("XFF")
|
||||
case len(r.Header.Get("X-Real-IP")) != 0:
|
||||
return r.Header.Get("X-Real-IP")
|
||||
default:
|
||||
return "localhost:8000"
|
||||
}
|
||||
}
|
||||
|
||||
// Hostname returns the hostname associated with
|
||||
// the current context.
|
||||
func Hostname(c *gin.Context) (host string) {
|
||||
v, ok := c.Get("host")
|
||||
if ok {
|
||||
host = v.(string)
|
||||
}
|
||||
return
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
package location
|
||||
|
||||
import (
|
||||
"github.com/franela/goblin"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var mockHeader []string
|
||||
var mockRequest *http.Request
|
||||
|
||||
var wronglyFormedHeader []string
|
||||
var wronglyFormedRequest *http.Request
|
||||
|
||||
func init() {
|
||||
mockHeader = []string{"For= 110.0.2.2", "for = \"[::1]\"; Host=example.com; foR=10.2.3.4; pRoto =https ; By = 127.0.0.1"}
|
||||
mockRequest = &http.Request{Header: map[string][]string{"Forwarded": mockHeader}}
|
||||
wronglyFormedHeader = []string{"Fro= 110.0.2.2", "for = \"[:1]\"% Host=example:.com| foR=10.278.3.4% poto =https | Bi % 127.0.0.1", ""}
|
||||
wronglyFormedRequest = &http.Request{Header: map[string][]string{"Forwarded": wronglyFormedHeader}}
|
||||
}
|
||||
|
||||
func TestParseForwardedHeadersProto(t *testing.T) {
|
||||
g := goblin.Goblin(t)
|
||||
|
||||
g.Describe("Parse proto Forwarded Headers", func() {
|
||||
g.It("Should parse a normal proto Forwarded header", func() {
|
||||
parsedHeader := parseHeader(mockRequest, "Forwarded", "proto")
|
||||
g.Assert("https" == parsedHeader[0]).IsTrue()
|
||||
})
|
||||
g.It("Should parse a normal for Forwarded header", func() {
|
||||
parsedHeader := parseHeader(mockRequest, "Forwarded", "for")
|
||||
g.Assert(reflect.DeepEqual([]string{"110.0.2.2", "\"[::1]\"", "10.2.3.4"}, parsedHeader)).IsTrue()
|
||||
})
|
||||
g.It("Should parse a normal host Forwarded header", func() {
|
||||
parsedHeader := parseHeader(mockRequest, "Forwarded", "host")
|
||||
g.Assert("example.com" == parsedHeader[0]).IsTrue()
|
||||
})
|
||||
g.It("Should parse a normal by Forwarded header", func() {
|
||||
parsedHeader := parseHeader(mockRequest, "Forwarded", "by")
|
||||
g.Assert("127.0.0.1" == parsedHeader[0]).IsTrue()
|
||||
})
|
||||
g.It("Should not crash if a wrongly formed Forwarder header is sent", func() {
|
||||
parsedHeader := parseHeader(wronglyFormedRequest, "Forwarded", "by")
|
||||
g.Assert(len(parsedHeader) == 0).IsTrue()
|
||||
})
|
||||
})
|
||||
}
|
48
router/middleware/remote.go
Normal file
48
router/middleware/remote.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/remote"
|
||||
"github.com/drone/drone/remote/bitbucket"
|
||||
"github.com/drone/drone/remote/github"
|
||||
"github.com/drone/drone/remote/gitlab"
|
||||
"github.com/drone/drone/remote/gogs"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/ianschenck/envflag"
|
||||
"github.com/drone/drone/remote/bitbucketserver"
|
||||
)
|
||||
|
||||
var (
|
||||
driver = envflag.String("REMOTE_DRIVER", "", "")
|
||||
config = envflag.String("REMOTE_CONFIG", "", "")
|
||||
)
|
||||
|
||||
// Remote is a middleware function that initializes the Remote and attaches to
|
||||
// the context of every http.Request.
|
||||
func Remote() gin.HandlerFunc {
|
||||
|
||||
logrus.Infof("using remote driver %s", *driver)
|
||||
logrus.Infof("using remote config %s", *config)
|
||||
|
||||
var remote_ remote.Remote
|
||||
switch *driver {
|
||||
case "github":
|
||||
remote_ = github.Load(*config)
|
||||
case "bitbucket":
|
||||
remote_ = bitbucket.Load(*config)
|
||||
case "gogs":
|
||||
remote_ = gogs.Load(*config)
|
||||
case "gitlab":
|
||||
remote_ = gitlab.Load(*config)
|
||||
case "bitbucketserver":
|
||||
remote_ = bitbucketserver.Load(*config)
|
||||
default:
|
||||
logrus.Fatalln("remote configuraiton not found")
|
||||
}
|
||||
|
||||
return func(c *gin.Context) {
|
||||
remote.ToContext(c, remote_)
|
||||
c.Next()
|
||||
}
|
||||
}
|
29
router/middleware/store.go
Normal file
29
router/middleware/store.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/store"
|
||||
"github.com/drone/drone/store/datastore"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/ianschenck/envflag"
|
||||
)
|
||||
|
||||
var (
|
||||
database = envflag.String("DATABASE_DRIVER", "sqlite3", "")
|
||||
datasource = envflag.String("DATABASE_CONFIG", "drone.sqlite", "")
|
||||
)
|
||||
|
||||
// Store is a middleware function that initializes the Datastore and attaches to
|
||||
// the context of every http.Request.
|
||||
func Store() gin.HandlerFunc {
|
||||
db := datastore.New(*database, *datasource)
|
||||
|
||||
logrus.Infof("using database driver %s", *database)
|
||||
logrus.Infof("using database config %s", *datasource)
|
||||
|
||||
return func(c *gin.Context) {
|
||||
store.ToContext(c, db)
|
||||
c.Next()
|
||||
}
|
||||
}
|
14
router/middleware/version.go
Normal file
14
router/middleware/version.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/drone/drone/version"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Version is a middleware function that appends the Drone
|
||||
// version information to the HTTP response. This is intended
|
||||
// for debugging and troubleshooting.
|
||||
func Version(c *gin.Context) {
|
||||
c.Header("X-DRONE-VERSION", version.Version)
|
||||
c.Next()
|
||||
}
|
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/drone/drone/api"
|
||||
"github.com/drone/drone/router/middleware/header"
|
||||
"github.com/drone/drone/router/middleware/location"
|
||||
"github.com/drone/drone/router/middleware/session"
|
||||
"github.com/drone/drone/router/middleware/token"
|
||||
"github.com/drone/drone/static"
|
||||
@@ -17,11 +16,12 @@ import (
|
||||
)
|
||||
|
||||
func Load(middleware ...gin.HandlerFunc) http.Handler {
|
||||
e := gin.Default()
|
||||
e := gin.New()
|
||||
e.Use(gin.Recovery())
|
||||
|
||||
e.SetHTMLTemplate(template.Load())
|
||||
e.StaticFS("/static", static.FileSystem())
|
||||
|
||||
e.Use(location.Resolve)
|
||||
e.Use(header.NoCache)
|
||||
e.Use(header.Options)
|
||||
e.Use(header.Secure)
|
||||
@@ -140,6 +140,13 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
||||
stream.GET("/:owner/:name/:build/:number", web.GetStream)
|
||||
}
|
||||
|
||||
bots := e.Group("/bots")
|
||||
{
|
||||
bots.Use(session.MustUser())
|
||||
bots.POST("/slack", web.Slack)
|
||||
bots.POST("/slack/:command", web.Slack)
|
||||
}
|
||||
|
||||
auth := e.Group("/authorize")
|
||||
{
|
||||
auth.GET("", web.GetLogin)
|
||||
@@ -170,7 +177,7 @@ func normalize(h http.Handler) http.Handler {
|
||||
|
||||
parts := strings.Split(r.URL.Path, "/")[1:]
|
||||
switch parts[0] {
|
||||
case "settings", "repos", "api", "login", "logout", "", "authorize", "hook", "static", "gitlab":
|
||||
case "settings", "bots", "repos", "api", "login", "logout", "", "authorize", "hook", "static", "gitlab":
|
||||
// no-op
|
||||
default:
|
||||
|
||||
|
Reference in New Issue
Block a user