blob: 16cdc07616fb02b45eae120a788100b8b70580b3 [file] [log] [blame]
Serge Bazanskibee272f2022-09-13 13:52:42 +02001package server
2
3import (
4 "bytes"
5 "context"
6 "encoding/binary"
7 "fmt"
8 "net/http"
9 "strconv"
10 "testing"
11
12 "google.golang.org/grpc/codes"
13 "google.golang.org/protobuf/proto"
14
15 apb "source.monogon.dev/cloud/api"
16 "source.monogon.dev/cloud/lib/component"
17)
18
19// TestPublicSimple ensures the public grpc-web listener is working.
20func TestPublicSimple(t *testing.T) {
21 s := Server{
22 Config: Config{
23 Configuration: component.Configuration{
24 GRPCListenAddress: ":0",
25 DevCerts: true,
26 DevCertsPath: "/tmp/foo",
27 },
28 PublicListenAddress: ":0",
29 },
30 }
31
32 ctx := context.Background()
33 s.Start(ctx)
34
35 // Craft a gRPC-Web request from scratch. There doesn't seem to be a
36 // well-supported library to do this.
37
38 // The request is \0 ++ uint32be(len(req)) ++ req.
39 msgBytes, err := proto.Marshal(&apb.WhoAmIRequest{})
40 if err != nil {
41 t.Fatalf("Could not marshal request body: %v", err)
42 }
43 buf := bytes.NewBuffer(nil)
44 binary.Write(buf, binary.BigEndian, byte(0))
45 binary.Write(buf, binary.BigEndian, uint32(len(msgBytes)))
46 buf.Write(msgBytes)
47
48 // Perform the request. Set minimum headers required for gRPC-Web to recognize
49 // this as a gRPC-Web request.
50 req, err := http.NewRequest("POST", fmt.Sprintf("http://%s/cloud.api.IAM/WhoAmI", s.ListenPublic), buf)
51 if err != nil {
52 t.Fatalf("Could not create request: %v", err)
53 }
54 req.Header.Set("Content-Type", "application/grpc-web+proto")
55 req.Header.Set("X-Grpc-Web", "1")
56
57 res, err := http.DefaultClient.Do(req)
58 if err != nil {
59 t.Fatalf("Could not perform request: %v", err)
60 }
61 // Regardless for RPC status, 200 should always be returned.
62 if want, got := 200, res.StatusCode; want != got {
63 t.Errorf("Wanted code %d, got %d", want, got)
64 }
65
66 // Expect endpoint to return 'unimplemented'.
67 code, _ := strconv.Atoi(res.Header.Get("Grpc-Status"))
68 if want, got := uint32(codes.Unimplemented), uint32(code); want != got {
69 t.Errorf("Wanted code %d, got %d", want, got)
70 }
71 if want, got := "unimplemented", res.Header.Get("Grpc-Message"); want != got {
72 t.Errorf("Wanted message %q, got %q", want, got)
73 }
74}