Link Client
A CLI-style gRPC client that creates multiple short links, looks them up, and cleans up after itself.
package main
import (
"context"
"fmt"
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
"shortener/pb"
)
func main() {
conn, err := grpc.NewClient("localhost:50051",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client := pb.NewLinkServiceClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Shorten a batch of URLs
urls := []string{
"https://go.dev/doc/effective_go",
"https://protobuf.dev/programming-guides/proto3/",
"https://grpc.io/docs/languages/go/quickstart/",
}
var codes_created []string
fmt.Println("=== Creating links ===")
for _, url := range urls {
resp, err := client.CreateLink(ctx, &pb.CreateLinkRequest{Url: url})
if err != nil {
log.Fatalf("CreateLink(%s): %v", url, err)
}
link := resp.GetLink()
codes_created = append(codes_created, link.GetShortCode())
fmt.Printf(" %s -> %s\n", link.GetShortCode(), link.GetUrl())
}
// Resolve each short code back to the original URL
fmt.Println("\n=== Resolving links ===")
for _, code := range codes_created {
resp, err := client.GetLink(ctx, &pb.GetLinkRequest{ShortCode: code})
if err != nil {
log.Fatalf("GetLink(%s): %v", code, err)
}
fmt.Printf(" %s resolves to %s\n", code, resp.GetLink().GetUrl())
}
// Delete the first link and verify it's gone
fmt.Println("\n=== Deleting first link ===")
_, err = client.DeleteLink(ctx, &pb.DeleteLinkRequest{ShortCode: codes_created[0]})
if err != nil {
log.Fatal(err)
}
fmt.Printf(" deleted %s\n", codes_created[0])
_, err = client.GetLink(ctx, &pb.GetLinkRequest{ShortCode: codes_created[0]})
if err != nil {
st, _ := status.FromError(err)
if st.Code() == codes.NotFound {
fmt.Printf(" confirmed: %s is gone\n", codes_created[0])
}
}
// The other links still work
fmt.Println("\n=== Remaining links still resolve ===")
for _, code := range codes_created[1:] {
resp, err := client.GetLink(ctx, &pb.GetLinkRequest{ShortCode: code})
if err != nil {
log.Fatalf("GetLink(%s): %v", code, err)
}
fmt.Printf(" %s -> %s\n", code, resp.GetLink().GetUrl())
}
}Expected output:
=== Creating links ===
a3f9wq -> https://go.dev/doc/effective_go
k7m2px -> https://protobuf.dev/programming-guides/proto3/
zt04bn -> https://grpc.io/docs/languages/go/quickstart/
=== Resolving links ===
a3f9wq resolves to https://go.dev/doc/effective_go
k7m2px resolves to https://protobuf.dev/programming-guides/proto3/
zt04bn resolves to https://grpc.io/docs/languages/go/quickstart/
=== Deleting first link ===
deleted a3f9wq
confirmed: a3f9wq is gone
=== Remaining links still resolve ===
k7m2px -> https://protobuf.dev/programming-guides/proto3/
zt04bn -> https://grpc.io/docs/languages/go/quickstart/Short codes will differ each run (they're randomly generated).
⚠️ Start the link server first (
go run .), then run this client (go run ./cmd/client).