从此
📄文章 #️⃣专题 🌐酷站 👨‍💻技术 📺 📱

谷歌客户端API、Alphabet Google API SDK、GCP、GAE

Alphabet Google API SDK

综述

通用:
  CNAME 值 ghs.googlehosted.com 是 ghs.google.com 的替代者,后者仅用于遗留项目;2025年2月亲测联通宽带未被墙。

  Google API报“WARNING: Application name is not set. Call Builder#setApplicationName.”,指未设置业务应用名(至User-Agent头),该名称便于区分自家业务应用和日志排查。
    var ib = new Indexing.Builder(transport,GsonFactory.getDefaultInstance(), httpRequestInitializer);
    ib.setApplicationName("gae").build(); // new Indexing(...) 形式则无此方法。

GAE

GAE Java runtime版本:JDK 21 + Servlet 6.0
判断是否 GAE 环境:
  if (System.getenv().containsKey("GAE_RUNTIME")) { System.getenv("GAE_RUNTIME"); } // java21

[2025年起GAE已不存在该问题了] 百度统计代码会添加Cookie至裸域名,GAE的RFC 6265规范遇到Cookie值写入分号会报错NPE+500状态码(规范不允许逗号但浏览器允许写入/百度从分号变逗号了?):
  Hm_lvt_32323232323232323232323232323232=1735197349,1735197378

Google Cloud Run Functions

内嵌编辑器创建的函数写死了主函数至运行容器,故无法接管HTTP Server:<mainClass>com.google.cloud.functions.invoker.runner.Invoker</mainClass>
接管HTTP Server方式:基于“从现有容器映像部署”。
h2c可避免请求降级至HTTP/1.1 - 网络->“启用 http/2 连接”:
    var hc = new HttpConfiguration();
    var sc = new ServerConnector(server, new HttpConnectionFactory(hc),
      // curl -i --http2-prior-knowledge http://localhost:8080
      new HTTP2CServerConnectionFactory(hc));
    sc.setPort(Integer.parseInt(System.getenv("PORT")));
    server.addConnector(sc);

SDK

SDK Credential
    注意 - googleCredentials.createScoped(scopes)返回的是新对象,故应暂存变量里再gc.refreshIfExpired();
        var gc = GoogleAuth.gcWithCloudDefaultScopes;
        try { gc.refreshIfExpired(); } catch (IOException ex) { ex.printStackTrace(System.err); }
        var at = gc.getAccessToken().getTokenValue();

    public static boolean credential(List scopes) {
        // 控制台需启用对应“API和服务”项;无范围应指定默认范围“../cloud-platform”。
        var scopes = Arrays.asList("https://www.googleapis.com/auth/cloud-platform");
        // 可选方法 createDelegated(...) 只用于 Google Workspace。
        return GoogleCredential.fromStream(new FileInputStream("D:\\sa.json"))
                .createDelegated("google_workspace@domain.name").createScoped(scopes);
    }

  Java 本地测试 Google API 接口 OAuth2 验证实例:

    //  implementation 'com.google.oauth-client:google-oauth-client-jetty:1.34.1'   GCP -> 凭据 -> OAuth 客户端 ID -> 桌面应用
    //  https://developers.google.com/api-client-library/java/google-api-java-client/oauth2?hl=zh-cn#installed_applications
    private static Credential auth() throws IOException, GeneralSecurityException {
        var JSON_FACTORY = GsonFactory.getDefaultInstance(); var cs = GoogleClientSecrets.load(JSON_FACTORY, 
        new InputStreamReader(new FileInputStream("D:\\temp\\client_secret_11111111111-xxx.apps.googleusercontent.com.json")));
        var flow = new GoogleAuthorizationCodeFlow.Builder(GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY,
                cs, List.of("https://www.googleapis.com/auth/youtube.upload", "https://www.googleapis.com/auth/youtube"))
                .setDataStoreFactory(new FileDataStoreFactory(new File(System.getProperty("user.home"), ".store/x/"))).build();
        var c = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
        System.out.println(c.getAccessToken()); return c; // Token有效期为1个小时。
    }
    
People SDK
        var scopes = Arrays.asList(PeopleServiceScopes.CONTACTS_READONLY);
        var s = new PeopleService.Builder(GoogleNetHttpTransport.newTrustedTransport(),
                GsonFactory.getDefaultInstance(), credential(scopes)).build();
        var r = s.people().connections().list("people/me").setPageSize(100)
                .setPersonFields("names,emailAddresses,phoneNumbers").execute();
    

API

Google API Explorer

支持API keys的服务:Cloud Vision API(免费千次)、Calendar API(免费)、Firebase API(免费)、Maps API、Gemini API(免费/Vertex AI Gemini API不支持)、Cloud Natural Language API

如果所处环境为 GCE 和 GAE ,可直接获取 access_token credential:
  curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
    -H "Metadata-Flavor: Google"

fetch("https://content-vision.googleapis.com/v1/images:annotate?alt=json&key=[ApiKey]", {
  "method": "POST", "headers": { "content-type": "application/json" },
  "body": `{"requests":[{"features":[{"type":"TEXT_DETECTION"}],"image":{"source":{"imageUri":"gs://cloud-samples-data/vision/ocr/sign.jpg"}}}]}`
});

  curl "https://language.googleapis.com/v1/documents:analyzeEntities" \
    -X POST \
    -H "X-Goog-Api-Key: $GOOGLE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"document":{"content":"The rain in Spain stays mainly in the plain.", "type":"PLAIN_TEXT"}}' \
    -i