Blob storage service (gRPC)#
Service for storing and retrieving blobs in object storage with workspace-based authorization.
Endpoints#
Get signed URL for blob#
gRPC /nominal.blob_storage_service.v1.BlobStorageService/GetSignedUrlForBlob
Retrieve a signed URL for downloading a blob. The URL is valid for 15 minutes.
Request: GetSignedUrlForBlobRequest
owning_ridResourceIdentifierrequired
Fields of
ResourceIdentifierridstring requiredMatches
^ri\.[a-z][a-z0-9\-]*\.([a-z0-9][a-z0-9\-]*)?\.[a-z][a-z0-9\-]*\.[a-zA-Z0-9\-\._]+$.
file_namestring required
Response: GetSignedUrlForBlobResponse
urlstringThis is a short lived signed url that can be used by the client to retrieve the object
Request
import grpc
from nominal.protos.blob_storage_service.v1 import blob_storage_service_pb2, blob_storage_service_pb2_grpc
channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
blob_storage_service = blob_storage_service_pb2_grpc.BlobStorageServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]
request = blob_storage_service_pb2.GetSignedUrlForBlobRequest(
owning_rid={"rid": "<rid>"},
file_name="<file name>",
)
response = blob_storage_service.GetSignedUrlForBlob(request, metadata=auth)
print(response)
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
blob_storage_servicev1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/blob_storage_service/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
)
func main() {
conn, err := grpc.NewClient("api.gov.nominal.io:443",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
if err != nil {
log.Fatal(err)
}
defer conn.Close()
blobStorageService := blob_storage_servicev1.NewBlobStorageServiceClient(conn)
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")
request := &blob_storage_servicev1.GetSignedUrlForBlobRequest{
OwningRid: &blob_storage_servicev1.ResourceIdentifier{
Rid: "<rid>",
},
FileName: "<file name>",
}
response, err := blobStorageService.GetSignedUrlForBlob(ctx, request)
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
}
Response
{
"url": "<url>"
}
Upload blob stream#
gRPC /nominal.blob_storage_service.v1.BlobStorageService/UploadBlobStream client streaming
Upload a blob using streaming. The blob will be stored with authorization checks based on the provided owningRid.
Request: a stream of UploadBlobStreamRequest
owning_ridResourceIdentifierrequired
Fields of
ResourceIdentifierridstring requiredMatches
^ri\.[a-z][a-z0-9\-]*\.([a-z0-9][a-z0-9\-]*)?\.[a-z][a-z0-9\-]*\.[a-zA-Z0-9\-\._]+$.
file_namestring required
ensure_uniqueboolean requiredwhen set to true, ensure_unique will attach the current timestamp to the file name this will ensure that we do not overwrite an existing file in blob storage
contentbytes required
Response: UploadBlobStreamResponse
file_namestringThis is the key that can be used in a retrieve blob request in order to retrieve this specific blob. If ensure_unique is not set, this will match the file name provided in UploadBlobStreamRequest
Request
import grpc
from nominal.protos.blob_storage_service.v1 import blob_storage_service_pb2, blob_storage_service_pb2_grpc
channel = grpc.secure_channel("api.gov.nominal.io:443", grpc.ssl_channel_credentials())
blob_storage_service = blob_storage_service_pb2_grpc.BlobStorageServiceStub(channel)
auth = [("authorization", "Bearer <api key>")]
request = blob_storage_service_pb2.UploadBlobStreamRequest(
owning_rid={"rid": "<rid>"},
file_name="<file name>",
ensure_unique=True,
content=b"<content>",
)
response = blob_storage_service.UploadBlobStream(iter([request]), metadata=auth)
print(response)
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
blob_storage_servicev1 "github.com/nominal-io/nominal-api-protos-go/nominal/protos/blob_storage_service/v1"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
)
func main() {
conn, err := grpc.NewClient("api.gov.nominal.io:443",
grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{})))
if err != nil {
log.Fatal(err)
}
defer conn.Close()
blobStorageService := blob_storage_servicev1.NewBlobStorageServiceClient(conn)
ctx := metadata.AppendToOutgoingContext(context.Background(), "authorization", "Bearer <api key>")
request := &blob_storage_servicev1.UploadBlobStreamRequest{
OwningRid: &blob_storage_servicev1.ResourceIdentifier{
Rid: "<rid>",
},
FileName: "<file name>",
EnsureUnique: true,
Content: []byte("<content>"),
}
stream, err := blobStorageService.UploadBlobStream(ctx)
if err != nil {
log.Fatal(err)
}
if err := stream.Send(request); err != nil {
log.Fatal(err)
}
response, err := stream.CloseAndRecv()
if err != nil {
log.Fatal(err)
}
fmt.Println(response)
}
Response
{
"file_name": "<file name>"
}
Types#
ResourceIdentifier#
This is used to identify any type of blob that will be in object storage.
ridstring requiredMatches
^ri\.[a-z][a-z0-9\-]*\.([a-z0-9][a-z0-9\-]*)?\.[a-z][a-z0-9\-]*\.[a-zA-Z0-9\-\._]+$.
Page design based on Scalar, MIT License.