Created
February 4, 2025 17:14
-
-
Save nohe427/59eb70bf511d6e942c0ccc45bff2dfe2 to your computer and use it in GitHub Desktop.
A go file for generating signed urls
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 hello | |
import ( | |
"context" | |
"encoding/json" | |
"fmt" | |
"net/http" | |
"path/filepath" | |
"time" | |
"cloud.google.com/go/compute/metadata" | |
"cloud.google.com/go/logging" | |
"cloud.google.com/go/storage" | |
"github.com/GoogleCloudPlatform/functions-framework-go/functions" | |
"github.com/google/uuid" | |
) | |
func init() { | |
functions.HTTP("UploadImgTrip", GenerateUploadURL) | |
} | |
var ( | |
projectId string = "projectId" // Only if you are not using metadata service | |
folder string = "srt" | |
folderPrefix string = "" //"object" | |
folderOfInterest string = folder // filepath.Join(folderPrefix, folder) | |
bucketName string = "PROJECTID.appspot.com" | |
) | |
func initLogger() *logging.Client { | |
ctx := context.Background() | |
client, err := logging.NewClient(ctx, logging.DetectProjectID) | |
if err != nil { | |
return nil | |
} | |
return client | |
} | |
// HelloHTTP is an HTTP Cloud Function with a request parameter. | |
func GenerateUploadURL(w http.ResponseWriter, r *http.Request) { | |
type o struct { | |
Uploadlocation string `json:"uploadLocation"` | |
DownloadLocation string `json:"downloadLocation"` | |
} | |
id := uuid.New() | |
outputName := filepath.Join(folder, id.String()) | |
mimeType := r.Header.Get("mime") | |
v, err := generateV4PutObjectSignedURL(bucketName, outputName, mimeType) | |
if err != nil { | |
fmt.Printf("Could not sign object %s", err) | |
fmt.Fprintf(w, "Could not generate URL") | |
return | |
} | |
d, _ := generateV4GetObjectSignedURL(bucketName, outputName) | |
O := o{Uploadlocation: v, DownloadLocation: d} | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
w.Header().Set("Access-Control-Allow-Methods", "*") | |
w.Header().Set("Access-Control-Allow-Headers", "*") | |
w.Header().Set("Content-Type", "application/json") | |
encoder := json.NewEncoder(w) | |
encoder.SetEscapeHTML(false) | |
encoder.Encode(O) | |
} | |
// generateV4GetObjectSignedURL generates object signed URL with GET method. | |
func generateV4GetObjectSignedURL(bucket, object string) (string, error) { | |
ctx := context.Background() | |
client, err := storage.NewClient(ctx) | |
if err != nil { | |
return "", fmt.Errorf("storage.NewClient: %w", err) | |
} | |
defer client.Close() | |
// Signing a URL requires credentials authorized to sign a URL. You can pass | |
// these in through SignedURLOptions with one of the following options: | |
// a. a Google service account private key, obtainable from the Google Developers Console | |
// b. a Google Access ID with iam.serviceAccounts.signBlob permissions | |
// c. a SignBytes function implementing custom signing. | |
// In this example, none of these options are used, which means the SignedURL | |
// function attempts to use the same authentication that was used to instantiate | |
// the Storage client. This authentication must include a private key or have | |
// iam.serviceAccounts.signBlob permissions. | |
opts := &storage.SignedURLOptions{ | |
Scheme: storage.SigningSchemeV4, | |
Method: "GET", | |
Expires: time.Now().Add(15 * time.Minute), | |
} | |
u, err := client.Bucket(bucket).SignedURL(object, opts) | |
if err != nil { | |
return "", fmt.Errorf("Bucket(%q).SignedURL: %w", bucket, err) | |
} | |
fmt.Println("Generated GET signed URL:") | |
fmt.Printf("%q\n", u) | |
fmt.Println("You can use this URL with any user agent, for example:") | |
fmt.Printf("curl %q\n", u) | |
return u, nil | |
} | |
// generateV4GetObjectSignedURL generates object signed URL with PUT method. | |
func generateV4PutObjectSignedURL(bucket, object, mimeType string) (string, error) { | |
if mimeType == "" { | |
mimeType = "application/octet-stream" | |
} | |
ctx := context.Background() | |
client, err := storage.NewClient(ctx) | |
if err != nil { | |
return "", fmt.Errorf("storage.NewClient: %w", err) | |
} | |
defer client.Close() | |
// Signing a URL requires credentials authorized to sign a URL. You can pass | |
// these in through SignedURLOptions with one of the following options: | |
// a. a Google service account private key, obtainable from the Google Developers Console | |
// b. a Google Access ID with iam.serviceAccounts.signBlob permissions | |
// c. a SignBytes function implementing custom signing. | |
// In this example, none of these options are used, which means the SignedURL | |
// function attempts to use the same authentication that was used to instantiate | |
// the Storage client. This authentication must include a private key or have | |
// iam.serviceAccounts.signBlob permissions. | |
opts := &storage.SignedURLOptions{ | |
Scheme: storage.SigningSchemeV4, | |
Method: "PUT", | |
Headers: []string{ | |
fmt.Sprintf("Content-Type:%s", mimeType), | |
}, | |
Expires: time.Now().Add(15 * time.Minute), | |
} | |
u, err := client.Bucket(bucket).SignedURL(object, opts) | |
if err != nil { | |
return "", fmt.Errorf("Bucket(%q).SignedURL: %w", bucket, err) | |
} | |
return u, nil | |
} | |
func fetchProjId() string { | |
id, err := metadata.ProjectID() | |
if err != nil { | |
fmt.Printf("Error getting metadata project id : %v", err) | |
id = projectId | |
} | |
return id | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment