Created
January 15, 2021 00:48
-
-
Save browny/4a0eaf92c52e1980441ef9e8bd647339 to your computer and use it in GitHub Desktop.
gcs-proxy.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"context" | |
"fmt" | |
"io/ioutil" | |
"net/http" | |
"strconv" | |
"strings" | |
"sync" | |
"github.com/gorilla/mux" | |
"cloud.google.com/go/storage" | |
) | |
type storageConnection struct { | |
Client *storage.Client | |
} | |
var ( | |
client *storageConnection | |
once sync.Once | |
) | |
const ( | |
// GCSBucket name | |
GCSBucket = "gcs-cdn-test-02" | |
// ProjectID Google Project ID name | |
ProjectID = "gcs-cdn-test-01" | |
delimitor = "_" | |
) | |
// GetGCSClient gets singleton object for Google Storage | |
func GetGCSClient(ctx context.Context) (*storage.Client, error) { | |
var clientErr error | |
once.Do(func() { | |
storageClient, err := storage.NewClient(ctx) | |
if err != nil { | |
clientErr = fmt.Errorf("Failed to create GCS client ERROR:%s", err.Error()) | |
} else { | |
client = &storageConnection{ | |
Client: storageClient, | |
} | |
} | |
}) | |
return client.Client, clientErr | |
} | |
// Download gets a file from GCS bucket, Takes file path as a path param from request | |
func Download(w http.ResponseWriter, r *http.Request) { | |
fmt.Println("Calling download") | |
clientCtx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
dir := mux.Vars(r)["dir"] | |
filename := mux.Vars(r)["filename"] | |
filePath := fmt.Sprintf("%s/%s", dir, filename) | |
client, err := GetGCSClient(clientCtx) | |
reader, err := client.Bucket(GCSBucket).UserProject(ProjectID).Object(filePath).NewReader(clientCtx) | |
if err != nil { | |
fmt.Println("Error ", err.Error()) | |
return | |
} | |
defer reader.Close() | |
contentType := reader.ContentType() | |
size := strconv.FormatInt(reader.Size(), 10) | |
content, err := ioutil.ReadAll(reader) | |
if err != nil { | |
fmt.Println("Error ", err.Error()) | |
return | |
} | |
w.Header().Set("Content-Type", contentType) | |
disposition := "attachment" | |
if strings.Contains(contentType, "image") || strings.Contains(contentType, "pdf") { | |
disposition = "inline" | |
} | |
// The header field Content-Disposition helps the client(Browser) | |
// to decide whether the content can be rendered on the browser or downloaded. | |
w.Header().Set("Content-Disposition", disposition+"; filename="+filename) | |
w.Header().Set("Content-Length", size) | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") | |
w.WriteHeader(http.StatusOK) | |
w.Write(content) | |
} | |
func healtcheck(w http.ResponseWriter, r *http.Request) { | |
w.Write([]byte("OK")) | |
} | |
func main() { | |
router := mux.NewRouter().StrictSlash(true) | |
router.HandleFunc("/healthz", healtcheck).Methods("GET", "HEAD") | |
router.HandleFunc("/file/{dir}/{filename}", Download).Methods("GET") | |
http.ListenAndServe(":8081", router) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment