package s3browser import ( "context" "fmt" "io" "mime" "net/http" "path/filepath" "github.com/graph-gophers/dataloader" "github.com/graphql-go/graphql" "github.com/graphql-go/handler" "github.com/minio/minio-go/v7" ) // initHttp setup and start the http server. Blocking func initHttp(schema graphql.Schema, resolveContext context.Context) { h := handler.New(&handler.Config{ Schema: &schema, Pretty: true, GraphiQL: false, Playground: true, }) http.HandleFunc("/graphql", func(rw http.ResponseWriter, r *http.Request) { h.ContextHandler(resolveContext, rw, r) }) http.HandleFunc("/api/file", func(rw http.ResponseWriter, r *http.Request) { if r.Method == "GET" { httpGetFile(resolveContext, rw, r) return } if r.Method == "POST" { httpPostFile(resolveContext, rw, r) return } }) http.ListenAndServe(":8080", nil) } func httpGetFile(ctx context.Context, rw http.ResponseWriter, r *http.Request) { s3Client := ctx.Value("s3Client").(*minio.Client) id := r.URL.Query().Get("id") objInfo, err := s3Client.StatObject(context.Background(), bucketName, id, minio.GetObjectOptions{}) if err != nil { rw.WriteHeader(500) return } reqEtag := r.Header.Get("If-None-Match") if reqEtag == objInfo.ETag { rw.WriteHeader(304) return } obj, err := s3Client.GetObject(context.Background(), bucketName, id, minio.GetObjectOptions{}) if err != nil { rw.WriteHeader(500) return } rw.Header().Set("Cache-Control", "must-revalidate") rw.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base((objInfo.Key)))) rw.Header().Set("Content-Type", objInfo.ContentType) rw.Header().Set("ETag", objInfo.ETag) io.Copy(rw, obj) } func httpPostFile(ctx context.Context, rw http.ResponseWriter, r *http.Request) { s3Client := ctx.Value("s3Client").(*minio.Client) loader := ctx.Value("loader").(map[string]*dataloader.Loader) id := r.URL.Query().Get("id") contentType := r.Header.Get("Content-Type") mimeType, _, _ := mime.ParseMediaType(contentType) s3Client.PutObject(context.Background(), bucketName, id, r.Body, r.ContentLength, minio.PutObjectOptions{ ContentType: mimeType, }) // Invalidate cache loader["getFile"].Clear(ctx, dataloader.StringKey(id)) loader["listObjects"].Clear(ctx, dataloader.StringKey(id)) loader["getFiles"].Clear(ctx, dataloader.StringKey(filepath.Dir(id))) }