-
Notifications
You must be signed in to change notification settings - Fork 33
Tips, Tricks, and Gotchas
This page serves to hold helpful information that may not be easily categorized or doesn't seem to belong anywhere else.
The following test program uses the (deprecated) Discovery Format-based Go client to request a spec body. It fails in a surprising way.
package main
import (
"context"
"log"
apigeeregistry "google.golang.org/api/apigeeregistry/v1"
)
func main() {
ctx := context.TODO()
apigeeregistryService, err := apigeeregistry.NewService(ctx)
if err != nil {
log.Fatalf("%s", err)
}
result, err := apigeeregistryService.Projects.Locations.Apis.Versions.Specs.GetContents("projects/test/locations/global/apis/petstore/versions/v1/specs/openapi").Do()
if err != nil {
log.Fatalf("error: %s", err)
}
log.Printf("%T %+v", result, result)
}
If the spec body is JSON, it seems to run just fine, but returns an HttpBody
object with the ContentType
and Data
fields empty:
go run main.go
2023/04/04 09:59:47 *apigeeregistry.HttpBody &{ContentType: Data: Extensions:[] ServerResponse:{HTTPStatusCode:200 Header:map[Alt-Svc:[h3=":443"; ma=2592000,h3-29=":443"; ma=2592000] Content-Length:[4375] Content-Type:[application/x.openapi;version=3] Date:[Tue, 04 Apr 2023 16:59:47 GMT] Server:[ESF] Vary:[Origin X-Origin Referer] X-Content-Type-Options:[nosniff] X-Frame-Options:[SAMEORIGIN] X-Xss-Protection:[0]]} ForceSendFields:[] NullFields:[]}
If the spec body is something else (e.g. YAML), we see a more obvious error message:
$ go run main.go
2023/04/04 10:01:39 error: invalid character '#' looking for beginning of value
exit status 1
It appears that the Go client library is trying to interpret the HTTP response as a JSON struct containing the ContentType
and Data
fields. It doesn't complain when they are missing and ignores fields that it doesn't recognize, but "succeeds" as long as the response is valid JSON.
Filter expressions are written in the CEL language, which is documented here.
Using the registry
tool, a filtered request could be made like this:
registry get apis -o yaml --filter "'apihub-team' in labels && labels['apihub-team'] == 'demo'"
The first part ('apihub-team' in labels &&
) could be omitted if every API has an apihub-team
label defined, but it's a good precaution because the CEL evaluation will throw an error if any API doesn't have a value for apihub-team
. That error looks like this:
Error: rpc error: code = InvalidArgument desc = no such key: apihub-team
So 'apihub-team' in labels
is just verifying that the apihub-team
label is defined before we try to read it with labels['apihub-team']
.
You could make this same request in an HTTP request as follows (after setting PROJECT
to your project ID):
curl "https://apigeeregistry.googleapis.com/v1/projects/${PROJECT}/locations/global/apis?filter=%27apihub-team%27%20in%20labels%20%26%26%20labels%5B%27apihub-team%27%5D%20%3D%3D%20%demo%27" \
-H "Authorization: Bearer `gcloud auth print-access-token`"
Note that the filter argument is the URL-escaped equivalent of the filter expression that we passed to the registry
tool.