From 964e537479c497a5ba42799a1c1a7c430720e990 Mon Sep 17 00:00:00 2001 From: Gogs Date: Sun, 23 Mar 2014 18:13:23 +0800 Subject: [PATCH] append route to web --- conf/app.ini | 8 +- models/user.go | 2 +- modules/avatar/avatar.go | 137 +++++++++++++++++++--------------- modules/avatar/avatar_test.go | 41 +++++++--- modules/base/tool.go | 2 +- public/img/avatar/default.jpg | Bin 0 -> 17379 bytes web.go | 5 +- 7 files changed, 118 insertions(+), 77 deletions(-) create mode 100644 public/img/avatar/default.jpg diff --git a/conf/app.ini b/conf/app.ini index ecb0d2511f4..160aef0ffe5 100644 --- a/conf/app.ini +++ b/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. ["1@example.com","2@example.com"] -RECEIVERS = \ No newline at end of file +RECEIVERS = diff --git a/models/user.go b/models/user.go index 3c110912858..cedf3424968 100644 --- a/models/user.go +++ b/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. diff --git a/modules/avatar/avatar.go b/modules/avatar/avatar.go index 55d1e13d94f..1a18d8a7ec2 100644 --- a/modules/avatar/avatar.go +++ b/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 +} + +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 +} + +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, this.cacheDir) + avatar.AlterImage = this.altImage + if avatar.Expired() { + err := avatar.UpdateTimeout(time.Millisecond * 500) + if err != nil { + 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) + } } // 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 - } - } - 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 - - 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) - if err != nil { - log.Println(err) - w.WriteHeader(500) - } +func HttpHandler(cacheDir string, defaultImgPath string) http.Handler { + return &avatarHandler{ + cacheDir: cacheDir, + altImage: defaultImgPath, } } -func init() { - http.HandleFunc("/", HttpHandler("./")) - log.Fatal(http.ListenAndServe(":8001", nil)) -} - +// 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") diff --git a/modules/avatar/avatar_test.go b/modules/avatar/avatar_test.go index 49f8f91f354..a337959c6fb 100644 --- a/modules/avatar/avatar_test.go +++ b/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("ssx205@gmail.com") - 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("ssx205@gmail.com") + 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) + "ssx205@gmail.com") - avatar := New(hash, "./") - avatar.Update() + hash := avatar.HashEmail(strconv.Itoa(i) + "ssx205@gmail.com") + 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) +} +*/ diff --git a/modules/base/tool.go b/modules/base/tool.go index 8fabb8c531d..8d0d38216dc 100644 --- a/modules/base/tool.go +++ b/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 diff --git a/public/img/avatar/default.jpg b/public/img/avatar/default.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c5a698da91f00405ca92b87252def7a5425ecd4b GIT binary patch literal 17379 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 DbPBAW literal 0 HcmV?d00001 diff --git a/web.go b/web.go index bb316a67246..637ee7ce957 100644 --- a/web.go +++ b/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)