1
0
mirror of https://github.com/Luzifer/cloudkeys-go.git synced 2024-09-16 14:18:32 +00:00

introduced context to all http handlers and use a specific http client

for S3 requests
This commit is contained in:
Martin Thielecke 2017-12-28 01:40:20 +00:00
parent 54526cff4c
commit 84d1c7e741
9 changed files with 59 additions and 45 deletions

21
ajax.go
View File

@ -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

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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
}

View File

@ -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

View File

@ -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)

View File

@ -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))

View File

@ -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)
}

View File

@ -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))),