소스 검색

append route to web

Gogs 11 년 전
부모
커밋
964e537479
7개의 변경된 파일111개의 추가작업 그리고 70개의 파일을 삭제
  1. 4 4
      conf/app.ini
  2. 1 1
      models/user.go
  3. 70 53
      modules/avatar/avatar.go
  4. 31 10
      modules/avatar/avatar_test.go
  5. 1 1
      modules/base/tool.go
  6. BIN
      public/img/avatar/default.jpg
  7. 4 1
      web.go

+ 4 - 4
conf/app.ini

@@ -7,7 +7,7 @@ RUN_USER = lunny
 RUN_MODE = dev
 
 [repository]
-ROOT = /Users/%(RUN_USER)s/git/gogs-repositories
+ROOT = /home/work/%(RUN_USER)s/git/gogs-repositories
 LANG_IGNS = Google Go|C|C++|Python|Ruby|C Sharp
 LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|BSD (3-Clause) License
 
@@ -15,7 +15,7 @@ LICENSES = Apache v2 License|GPL v2|MIT License|Affero GPL|Artistic License 2.0|
 DOMAIN = localhost
 ROOT_URL = http://%(DOMAIN)s:%(HTTP_PORT)s/
 HTTP_ADDR = 
-HTTP_PORT = 3000
+HTTP_PORT = 8002
 
 [database]
 ; Either "mysql", "postgres" or "sqlite3"(binary release only), it's your choice
@@ -23,7 +23,7 @@ DB_TYPE = mysql
 HOST = 
 NAME = gogs
 USER = root
-PASSWD =
+PASSWD = toor
 ; For "postgres" only, either "disable", "require" or "verify-full"
 SSL_MODE = disable
 ; For "sqlite3" only
@@ -120,4 +120,4 @@ HOST =
 USER = 
 PASSWD =
 ; Receivers, can be one or more, e.g. ["[email protected]","[email protected]"]
-RECEIVERS = 
+RECEIVERS = 

+ 1 - 1
models/user.go

@@ -72,7 +72,7 @@ func (user *User) HomeLink() string {
 
 // AvatarLink returns the user gravatar link.
 func (user *User) AvatarLink() string {
-	return "http://1.gravatar.com/avatar/" + user.Avatar
+	return "/avatar/" + user.Avatar
 }
 
 // NewGitSig generates and returns the signature of given user.

+ 70 - 53
modules/avatar/avatar.go

@@ -1,3 +1,8 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// for www.gravatar.com image cache
 package avatar
 
 import (
@@ -22,11 +27,17 @@ import (
 )
 
 var (
-	gravatar         = "http://www.gravatar.com/avatar"
-	defaultImagePath = "./default.jpg"
+	gravatar = "http://www.gravatar.com/avatar"
 )
 
+func debug(a ...interface{}) {
+	if true {
+		log.Println(a...)
+	}
+}
+
 // hash email to md5 string
+// keep this func in order to make this package indenpent
 func HashEmail(email string) string {
 	h := md5.New()
 	h.Write([]byte(strings.ToLower(email)))
@@ -35,6 +46,7 @@ func HashEmail(email string) string {
 
 type Avatar struct {
 	Hash           string
+	AlterImage     string // image path
 	cacheDir       string // image save dir
 	reqParams      string
 	imagePath      string
@@ -54,7 +66,7 @@ func New(hash string, cacheDir string) *Avatar {
 	}
 }
 
-func (this *Avatar) InCache() bool {
+func (this *Avatar) HasCache() bool {
 	fileInfo, err := os.Stat(this.imagePath)
 	return err == nil && fileInfo.Mode().IsRegular()
 }
@@ -68,11 +80,8 @@ func (this *Avatar) Modtime() (modtime time.Time, err error) {
 }
 
 func (this *Avatar) Expired() bool {
-	if !this.InCache() {
-		return true
-	}
-	fileInfo, err := os.Stat(this.imagePath)
-	return err != nil || time.Since(fileInfo.ModTime()) > this.expireDuration
+	modtime, err := this.Modtime()
+	return err != nil || time.Since(modtime) > this.expireDuration
 }
 
 // default image format: jpeg
@@ -92,8 +101,11 @@ func (this *Avatar) Encode(wr io.Writer, size int) (err error) {
 		return
 	}
 	imgPath := this.imagePath
-	if !this.InCache() {
-		imgPath = defaultImagePath
+	if !this.HasCache() {
+		if this.AlterImage == "" {
+			return errors.New("request image failed, and no alt image offered")
+		}
+		imgPath = this.AlterImage
 	}
 	img, err = decodeImageFile(imgPath)
 	if err != nil {
@@ -120,61 +132,66 @@ func (this *Avatar) UpdateTimeout(timeout time.Duration) error {
 	return err
 }
 
-func init() {
-	log.SetFlags(log.Lshortfile | log.LstdFlags)
+type avatarHandler struct {
+	cacheDir string
+	altImage string
 }
 
-// http.Handle("/avatar/", avatar.HttpHandler("./cache"))
-func HttpHandler(cacheDir string) func(w http.ResponseWriter, r *http.Request) {
-	MustInt := func(r *http.Request, defaultValue int, keys ...string) int {
-		var v int
-		for _, k := range keys {
-			if _, err := fmt.Sscanf(r.FormValue(k), "%d", &v); err == nil {
-				defaultValue = v
-			}
+func (this *avatarHandler) mustInt(r *http.Request, defaultValue int, keys ...string) int {
+	var v int
+	for _, k := range keys {
+		if _, err := fmt.Sscanf(r.FormValue(k), "%d", &v); err == nil {
+			defaultValue = v
 		}
-		return defaultValue
 	}
+	return defaultValue
+}
 
-	return func(w http.ResponseWriter, r *http.Request) {
-		urlPath := r.URL.Path
-		hash := urlPath[strings.LastIndex(urlPath, "/")+1:]
-		hash = HashEmail(hash)
-		size := MustInt(r, 80, "s", "size") // size = 80*80
+func (this *avatarHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	urlPath := r.URL.Path
+	hash := urlPath[strings.LastIndex(urlPath, "/")+1:]
+	//hash = HashEmail(hash)
+	size := this.mustInt(r, 80, "s", "size") // size = 80*80
 
-		avatar := New(hash, cacheDir)
-		if avatar.Expired() {
-			err := avatar.UpdateTimeout(time.Millisecond * 500)
-			if err != nil {
-				log.Println(err)
-			}
-		}
-		if modtime, err := avatar.Modtime(); err == nil {
-			etag := fmt.Sprintf("size(%d)", size)
-			if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) && etag == r.Header.Get("If-None-Match") {
-				h := w.Header()
-				delete(h, "Content-Type")
-				delete(h, "Content-Length")
-				w.WriteHeader(http.StatusNotModified)
-				return
-			}
-			w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat))
-			w.Header().Set("ETag", etag)
-		}
-		w.Header().Set("Content-Type", "image/jpeg")
-		err := avatar.Encode(w, size)
+	avatar := New(hash, this.cacheDir)
+	avatar.AlterImage = this.altImage
+	if avatar.Expired() {
+		err := avatar.UpdateTimeout(time.Millisecond * 500)
 		if err != nil {
-			log.Println(err)
-			w.WriteHeader(500)
+			debug(err)
+			//log.Trace("avatar update error: %v", err)
+		}
+	}
+	if modtime, err := avatar.Modtime(); err == nil {
+		etag := fmt.Sprintf("size(%d)", size)
+		if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && modtime.Before(t.Add(1*time.Second)) && etag == r.Header.Get("If-None-Match") {
+			h := w.Header()
+			delete(h, "Content-Type")
+			delete(h, "Content-Length")
+			w.WriteHeader(http.StatusNotModified)
+			return
 		}
+		w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat))
+		w.Header().Set("ETag", etag)
+	}
+	w.Header().Set("Content-Type", "image/jpeg")
+	err := avatar.Encode(w, size)
+	if err != nil {
+		//log.Warn("avatar encode error: %v", err) // will panic when err != nil
+		debug(err)
+		w.WriteHeader(500)
 	}
 }
 
-func init() {
-	http.HandleFunc("/", HttpHandler("./"))
-	log.Fatal(http.ListenAndServe(":8001", nil))
+// http.Handle("/avatar/", avatar.HttpHandler("./cache"))
+func HttpHandler(cacheDir string, defaultImgPath string) http.Handler {
+	return &avatarHandler{
+		cacheDir: cacheDir,
+		altImage: defaultImgPath,
+	}
 }
 
+// thunder downloader
 var thunder = &Thunder{QueueSize: 10}
 
 type Thunder struct {
@@ -234,7 +251,7 @@ func (this *thunderTask) Fetch() {
 var client = &http.Client{}
 
 func (this *thunderTask) fetch() error {
-	log.Println("thunder, fetch", this.Url)
+	//log.Println("thunder, fetch", this.Url)
 	req, _ := http.NewRequest("GET", this.Url, nil)
 	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
 	req.Header.Set("Accept-Encoding", "gzip,deflate,sdch")

+ 31 - 10
modules/avatar/avatar_test.go

@@ -1,29 +1,41 @@
-package avatar
+// Copyright 2014 The Gogs 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 avatar_test
 
 import (
 	"log"
+	"os"
 	"strconv"
 	"testing"
 	"time"
+
+	"github.com/gogits/gogs/modules/avatar"
 )
 
+const TMPDIR = "test-avatar"
+
 func TestFetch(t *testing.T) {
-	hash := HashEmail("[email protected]")
-	avatar := New(hash, "./")
-	//avatar.Update()
-	avatar.UpdateTimeout(time.Millisecond * 200)
-	time.Sleep(5 * time.Second)
+	os.Mkdir(TMPDIR, 0755)
+	defer os.RemoveAll(TMPDIR)
+
+	hash := avatar.HashEmail("[email protected]")
+	a := avatar.New(hash, TMPDIR)
+	a.UpdateTimeout(time.Millisecond * 200)
 }
 
 func TestFetchMany(t *testing.T) {
+	os.Mkdir(TMPDIR, 0755)
+	defer os.RemoveAll(TMPDIR)
+
 	log.Println("start")
-	var n = 50
+	var n = 5
 	ch := make(chan bool, n)
 	for i := 0; i < n; i++ {
 		go func(i int) {
-			hash := HashEmail(strconv.Itoa(i) + "[email protected]")
-			avatar := New(hash, "./")
-			avatar.Update()
+			hash := avatar.HashEmail(strconv.Itoa(i) + "[email protected]")
+			a := avatar.New(hash, TMPDIR)
+			a.Update()
 			log.Println("finish", hash)
 			ch <- true
 		}(i)
@@ -33,3 +45,12 @@ func TestFetchMany(t *testing.T) {
 	}
 	log.Println("end")
 }
+
+// cat
+// wget http://www.artsjournal.com/artfulmanager/wp/wp-content/uploads/2013/12/200x200xmirror_cat.jpg.pagespeed.ic.GOZSv6v1_H.jpg -O default.jpg
+/*
+func TestHttp(t *testing.T) {
+	http.Handle("/", avatar.HttpHandler("./", "default.jpg"))
+	http.ListenAndServe(":8001", nil)
+}
+*/

+ 1 - 1
modules/base/tool.go

@@ -98,7 +98,7 @@ func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string
 
 // AvatarLink returns avatar link by given e-mail.
 func AvatarLink(email string) string {
-	return "http://1.gravatar.com/avatar/" + EncodeMd5(email)
+	return "/avatar/" + EncodeMd5(email)
 }
 
 // Seconds-based time units

BIN
public/img/avatar/default.jpg


+ 4 - 1
web.go

@@ -18,6 +18,7 @@ import (
 
 	"github.com/gogits/gogs/models"
 	"github.com/gogits/gogs/modules/auth"
+	"github.com/gogits/gogs/modules/avatar"
 	"github.com/gogits/gogs/modules/base"
 	"github.com/gogits/gogs/modules/log"
 	"github.com/gogits/gogs/modules/mailer"
@@ -114,6 +115,9 @@ func runWeb(*cli.Context) {
 
 	m.Get("/help", routers.Help)
 
+	avatarHandler := avatar.HttpHandler("public/img/avatar", "public/img/avatar/default.jpg")
+	m.Get("/avatar/:hash", avatarHandler.ServeHTTP)
+
 	adminReq := middleware.AdminRequire()
 	m.Get("/admin", reqSignIn, adminReq, admin.Dashboard)
 	m.Get("/admin/users", reqSignIn, adminReq, admin.Users)
@@ -136,7 +140,6 @@ func runWeb(*cli.Context) {
 		ignSignIn, middleware.RepoAssignment(true), repo.Single)
 	m.Get("/:username/:reponame/commit/:commitid/**", ignSignIn, middleware.RepoAssignment(true), repo.Single)
 	m.Get("/:username/:reponame/commit/:commitid", ignSignIn, middleware.RepoAssignment(true), repo.Single)
-
 	m.Get("/:username/:reponame", ignSignIn, middleware.RepoAssignment(true), repo.Single)
 
 	m.Any("/:username/:reponame/**", ignSignIn, repo.Http)