mirror of
https://github.com/Luzifer/cloudkeys-go.git
synced 2024-11-08 14:10:05 +00:00
introduced context to all http handlers and use a specific http client
for S3 requests
This commit is contained in:
parent
54526cff4c
commit
84d1c7e741
9 changed files with 59 additions and 45 deletions
21
ajax.go
21
ajax.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -23,16 +24,16 @@ func (a ajaxResponse) Bytes() []byte {
|
|||
return out
|
||||
}
|
||||
|
||||
func ajaxGetHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
func ajaxGetHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
user, _ := checkLogin(r, session)
|
||||
user, _ := checkLogin(c, r, session)
|
||||
|
||||
if user == nil || !storage.IsPresent(user.UserFile) {
|
||||
if user == nil || !storage.IsPresent(c, user.UserFile) {
|
||||
res.Write(ajaxResponse{Error: true}.Bytes())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userFileRaw, err := storage.Read(user.UserFile)
|
||||
userFileRaw, err := storage.Read(c, user.UserFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not read user file from storage")
|
||||
res.Write(ajaxResponse{Error: true}.Bytes())
|
||||
|
@ -45,21 +46,21 @@ func ajaxGetHandler(res http.ResponseWriter, r *http.Request, session *sessions.
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func ajaxPostHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
func ajaxPostHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
res.Header().Set("Content-Type", "application/json")
|
||||
user, _ := checkLogin(r, session)
|
||||
user, _ := checkLogin(c, r, session)
|
||||
|
||||
if user == nil {
|
||||
res.Write(ajaxResponse{Error: true, Type: "login"}.Bytes())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if !storage.IsPresent(user.UserFile) {
|
||||
if !storage.IsPresent(c, user.UserFile) {
|
||||
res.Write(ajaxResponse{Error: true, Type: "register"}.Bytes())
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
userFileRaw, err := storage.Read(user.UserFile)
|
||||
userFileRaw, err := storage.Read(c, user.UserFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not read user file from storage")
|
||||
res.Write(ajaxResponse{Error: true, Type: "storage_error"}.Bytes())
|
||||
|
@ -84,7 +85,7 @@ func ajaxPostHandler(res http.ResponseWriter, r *http.Request, session *sessions
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
if err := storage.Backup(user.UserFile); err != nil {
|
||||
if err := storage.Backup(c, user.UserFile); err != nil {
|
||||
log.WithError(err).Error("Could not create backup of user file")
|
||||
res.Write(ajaxResponse{Error: true, Type: "storage_error"}.Bytes())
|
||||
return nil, nil
|
||||
|
@ -95,7 +96,7 @@ func ajaxPostHandler(res http.ResponseWriter, r *http.Request, session *sessions
|
|||
|
||||
d, _ := userFile.GetData()
|
||||
|
||||
if err := storage.Write(user.UserFile, d); err != nil {
|
||||
if err := storage.Write(c, user.UserFile, d); err != nil {
|
||||
log.WithError(err).Error("Could not write user file to storage")
|
||||
res.Write(ajaxResponse{Error: true, Type: "storage_error"}.Bytes())
|
||||
return nil, nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/flosch/pongo2"
|
||||
|
@ -8,7 +9,7 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type httpHelperFunc func(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error)
|
||||
type httpHelperFunc func(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error)
|
||||
|
||||
func httpHelper(f httpHelperFunc) http.HandlerFunc {
|
||||
return func(res http.ResponseWriter, r *http.Request) {
|
||||
|
@ -19,7 +20,9 @@ func httpHelper(f httpHelperFunc) http.HandlerFunc {
|
|||
ctx["error"] = errFlash[0].(string)
|
||||
}
|
||||
|
||||
template, err := f(res, r, sess, &ctx)
|
||||
c := getContext(r)
|
||||
|
||||
template, err := f(c, res, r, sess, &ctx)
|
||||
if err != nil {
|
||||
http.Error(res, "An error ocurred.", http.StatusInternalServerError)
|
||||
log.WithError(err).Error("Unable to execute template")
|
||||
|
@ -27,8 +30,7 @@ func httpHelper(f httpHelperFunc) http.HandlerFunc {
|
|||
}
|
||||
|
||||
if template != nil {
|
||||
ts := pongo2.NewSet("frontend")
|
||||
ts.SetBaseDirectory("templates")
|
||||
ts := pongo2.NewSet("frontend", pongo2.MustNewLocalFileSystemLoader("templates"))
|
||||
tpl, err := ts.FromFile(*template)
|
||||
if err != nil {
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
|
@ -52,7 +54,7 @@ func httpHelper(f httpHelperFunc) http.HandlerFunc {
|
|||
}
|
||||
|
||||
func simpleTemplateOutput(template string) httpHelperFunc {
|
||||
return func(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
return func(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
return &template, nil
|
||||
}
|
||||
}
|
||||
|
|
11
login.go
11
login.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
@ -15,19 +16,19 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func loginHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
func loginHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
var (
|
||||
username = strings.ToLower(r.FormValue("username"))
|
||||
password = r.FormValue("password")
|
||||
deprecatedPassword = fmt.Sprintf("%x", sha1.Sum([]byte(cfg.PasswordSalt+r.FormValue("password")))) // Here for backwards compatibility
|
||||
)
|
||||
|
||||
if !storage.IsPresent(createUserFilename(username)) {
|
||||
if !storage.IsPresent(c, createUserFilename(username)) {
|
||||
(*ctx)["error"] = true
|
||||
return stringPointer("login.html"), nil
|
||||
}
|
||||
|
||||
userFileRaw, err := storage.Read(createUserFilename(username))
|
||||
userFileRaw, err := storage.Read(c, createUserFilename(username))
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Unable to read user file")
|
||||
(*ctx)["error"] = true
|
||||
|
@ -68,14 +69,14 @@ func loginHandler(res http.ResponseWriter, r *http.Request, session *sessions.Se
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
func logoutHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
func logoutHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
session.Values["authorizedAccounts"] = authorizedAccounts{}
|
||||
session.Save(r, res)
|
||||
http.Redirect(res, r, "overview", http.StatusFound)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func checkLogin(r *http.Request, session *sessions.Session) (*authorizedAccount, error) {
|
||||
func checkLogin(c context.Context, r *http.Request, session *sessions.Session) (*authorizedAccount, error) {
|
||||
vars := mux.Vars(r)
|
||||
idx, err := strconv.ParseInt(vars["userIndex"], 10, 64)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
func overviewHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
user, _ := checkLogin(r, session)
|
||||
func overviewHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
user, _ := checkLogin(c, r, session)
|
||||
|
||||
if user == nil || !storage.IsPresent(user.UserFile) {
|
||||
if user == nil || !storage.IsPresent(c, user.UserFile) {
|
||||
http.Redirect(res, r, "../../login", http.StatusFound)
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func registerHandler(res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
func registerHandler(c context.Context, res http.ResponseWriter, r *http.Request, session *sessions.Session, ctx *pongo2.Context) (*string, error) {
|
||||
var (
|
||||
username = strings.ToLower(r.FormValue("username"))
|
||||
password = r.FormValue("password")
|
||||
|
@ -22,7 +23,7 @@ func registerHandler(res http.ResponseWriter, r *http.Request, session *sessions
|
|||
return stringPointer("register.html"), nil
|
||||
}
|
||||
|
||||
if storage.IsPresent(createUserFilename(username)) {
|
||||
if storage.IsPresent(c, createUserFilename(username)) {
|
||||
(*ctx)["exists"] = true
|
||||
return stringPointer("register.html"), nil
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ func registerHandler(res http.ResponseWriter, r *http.Request, session *sessions
|
|||
d.MetaData.Password = string(hashedPassword)
|
||||
data, _ := d.GetData()
|
||||
|
||||
if err := storage.Write(createUserFilename(username), data); err != nil {
|
||||
if err := storage.Write(c, createUserFilename(username), data); err != nil {
|
||||
log.WithError(err).Error("Could not write user file to storage")
|
||||
(*ctx)["error"] = true
|
||||
return stringPointer("register.html"), nil
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
|
@ -11,10 +12,10 @@ var (
|
|||
)
|
||||
|
||||
type storageAdapter interface {
|
||||
Write(identifier string, data io.Reader) error
|
||||
Read(identifier string) (io.Reader, error)
|
||||
IsPresent(identifier string) bool
|
||||
Backup(identifier string) error
|
||||
Write(ctx context.Context, identifier string, data io.Reader) error
|
||||
Read(ctx context.Context, identifier string) (io.Reader, error)
|
||||
IsPresent(ctx context.Context, identifier string) bool
|
||||
Backup(ctx context.Context, identifier string) error
|
||||
}
|
||||
type storageAdapterInitializer func(*url.URL) (storageAdapter, error)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
|
@ -37,7 +38,7 @@ func newLocalStorage(u *url.URL) (storageAdapter, error) {
|
|||
}
|
||||
|
||||
// Write store the data of a dataObject into the storage
|
||||
func (l *LocalStorage) Write(identifier string, data io.Reader) error {
|
||||
func (l *LocalStorage) Write(ctx context.Context, identifier string, data io.Reader) error {
|
||||
f, err := os.Create(path.Join(l.path, identifier))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -49,18 +50,18 @@ func (l *LocalStorage) Write(identifier string, data io.Reader) error {
|
|||
}
|
||||
|
||||
// Read reads the data of a dataObject from the storage
|
||||
func (l *LocalStorage) Read(identifier string) (io.Reader, error) {
|
||||
func (l *LocalStorage) Read(ctx context.Context, identifier string) (io.Reader, error) {
|
||||
return os.Open(path.Join(l.path, identifier))
|
||||
}
|
||||
|
||||
// IsPresent checks for the presence of an userfile identifier
|
||||
func (l *LocalStorage) IsPresent(identifier string) bool {
|
||||
func (l *LocalStorage) IsPresent(ctx context.Context, identifier string) bool {
|
||||
_, err := os.Stat(path.Join(l.path, identifier))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Backup creates a backup of the old data
|
||||
func (l *LocalStorage) Backup(identifier string) error {
|
||||
func (l *LocalStorage) Backup(ctx context.Context, identifier string) error {
|
||||
ts := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
o, err := os.Open(path.Join(l.path, identifier))
|
||||
|
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
|
@ -38,7 +39,7 @@ func newRedisStorage(u *url.URL) (storageAdapter, error) {
|
|||
}
|
||||
|
||||
// Write store the data of a dataObject into the storage
|
||||
func (r *RedisStorage) Write(identifier string, data io.Reader) error {
|
||||
func (r *RedisStorage) Write(ctx context.Context, identifier string, data io.Reader) error {
|
||||
d, err := ioutil.ReadAll(data)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -48,13 +49,13 @@ func (r *RedisStorage) Write(identifier string, data io.Reader) error {
|
|||
}
|
||||
|
||||
// Read reads the data of a dataObject from the storage
|
||||
func (r *RedisStorage) Read(identifier string) (io.Reader, error) {
|
||||
func (r *RedisStorage) Read(ctx context.Context, identifier string) (io.Reader, error) {
|
||||
content, err := r.conn.Get(r.prefix + identifier)
|
||||
return bytes.NewReader(content), err
|
||||
}
|
||||
|
||||
// IsPresent checks for the presence of an userfile identifier
|
||||
func (r *RedisStorage) IsPresent(identifier string) bool {
|
||||
func (r *RedisStorage) IsPresent(ctx context.Context, identifier string) bool {
|
||||
e, err := r.conn.Exists(r.prefix + identifier)
|
||||
if err != nil {
|
||||
log.WithError(err).WithFields(log.Fields{
|
||||
|
@ -66,12 +67,12 @@ func (r *RedisStorage) IsPresent(identifier string) bool {
|
|||
}
|
||||
|
||||
// Backup creates a backup of the old data
|
||||
func (r *RedisStorage) Backup(identifier string) error {
|
||||
func (r *RedisStorage) Backup(ctx context.Context, identifier string) error {
|
||||
ts := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
data, err := r.Read(identifier)
|
||||
data, err := r.Read(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return r.Write(identifier+":backup:"+ts, data)
|
||||
return r.Write(ctx, identifier+":backup:"+ts, data)
|
||||
}
|
||||
|
|
15
storageS3.go
15
storageS3.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
|
@ -35,10 +36,11 @@ func newS3Storage(u *url.URL) (storageAdapter, error) {
|
|||
}
|
||||
|
||||
// Write store the data of a dataObject into the storage
|
||||
func (s *S3Storage) Write(identifier string, data io.Reader) error {
|
||||
func (s *S3Storage) Write(ctx context.Context, identifier string, data io.Reader) error {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
io.Copy(buf, data)
|
||||
|
||||
s.conn.Config.HTTPClient = getHTTPClient(ctx)
|
||||
_, err := s.conn.PutObject(&s3.PutObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Body: bytes.NewReader(buf.Bytes()),
|
||||
|
@ -48,7 +50,8 @@ func (s *S3Storage) Write(identifier string, data io.Reader) error {
|
|||
}
|
||||
|
||||
// Read reads the data of a dataObject from the storage
|
||||
func (s *S3Storage) Read(identifier string) (io.Reader, error) {
|
||||
func (s *S3Storage) Read(ctx context.Context, identifier string) (io.Reader, error) {
|
||||
s.conn.Config.HTTPClient = getHTTPClient(ctx)
|
||||
out, err := s.conn.GetObject(&s3.GetObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path.Join(s.path, identifier)),
|
||||
|
@ -62,7 +65,8 @@ func (s *S3Storage) Read(identifier string) (io.Reader, error) {
|
|||
}
|
||||
|
||||
// IsPresent checks for the presence of an userfile identifier
|
||||
func (s *S3Storage) IsPresent(identifier string) bool {
|
||||
func (s *S3Storage) IsPresent(ctx context.Context, identifier string) bool {
|
||||
s.conn.Config.HTTPClient = getHTTPClient(ctx)
|
||||
out, err := s.conn.HeadObject(&s3.HeadObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path.Join(s.path, identifier)),
|
||||
|
@ -72,12 +76,13 @@ func (s *S3Storage) IsPresent(identifier string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
return *out.ContentLength > 0
|
||||
return aws.Int64Value(out.ContentLength) > 0 || aws.StringValue(out.ContentType) == "binary/octet-stream"
|
||||
}
|
||||
|
||||
// Backup creates a backup of the old data
|
||||
func (s *S3Storage) Backup(identifier string) error {
|
||||
func (s *S3Storage) Backup(ctx context.Context, identifier string) error {
|
||||
ts := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
s.conn.Config.HTTPClient = getHTTPClient(ctx)
|
||||
_, err := s.conn.CopyObject(&s3.CopyObjectInput{
|
||||
Bucket: aws.String(s.bucket),
|
||||
Key: aws.String(path.Join(s.path, "backup", fmt.Sprintf("%s.%s", identifier, ts))),
|
||||
|
|
Loading…
Reference in a new issue