Skip to content

feat: add GWS_API_BASE_URL for custom/mock endpoint support#97

Closed
xdotli wants to merge 2 commits intogoogleworkspace:mainfrom
benchflow-ai:feat/custom-endpoint-override
Closed

feat: add GWS_API_BASE_URL for custom/mock endpoint support#97
xdotli wants to merge 2 commits intogoogleworkspace:mainfrom
benchflow-ai:feat/custom-endpoint-override

Conversation

@xdotli
Copy link

@xdotli xdotli commented Mar 5, 2026

Summary

Adds a GWS_API_BASE_URL environment variable that redirects all API requests to a custom endpoint (e.g., a mock server). When set:

  • The real Discovery Document is still fetched so the CLI command tree works normally
  • root_url and base_url in the Discovery Document are rewritten to the custom endpoint
  • OAuth authentication is automatically skipped (mock servers don't need it)
  • Works in both CLI mode and MCP server mode

Motivation

Testing agents and skills against mock API servers is a common need for development and CI. The gog CLI already supports this via GOG_ENDPOINT. This PR brings the same capability to gws.

Example usage

# Point gws at a local mock Gmail server
export GWS_API_BASE_URL=http://localhost:8099

# All commands now hit the mock server, no auth needed
gws gmail users messages list --params '{"userId": "me", "q": "is:unread"}'

Changes

  • src/discovery.rs: Add custom_api_base_url() helper; rewrite Discovery Document URLs when env var is set
  • src/executor.rs: Add resolve_auth() that skips OAuth for custom endpoints
  • src/main.rs, src/mcp_server.rs: Use resolve_auth() for consistent behavior

Test plan

  • cargo check passes
  • Manual testing against a mock Gmail API server
  • Verify MCP server mode also respects the env var
  • Verify normal operation (no env var) is unaffected

🤖 Generated with Claude Code

When GWS_API_BASE_URL is set (e.g., http://localhost:8099), all API
requests are redirected to the custom endpoint and OAuth authentication
is skipped automatically. The real Discovery Document is still fetched
so the CLI command tree remains fully functional — only root_url and
base_url are rewritten to point at the custom endpoint.

This enables testing against mock API servers without any code changes
to agents or skills. Similar to gog CLI's GOG_ENDPOINT pattern.

Changes:
- discovery.rs: add custom_api_base_url() helper; rewrite doc URLs
  when env var is set
- executor.rs: add resolve_auth() that skips OAuth for custom endpoints
- main.rs, mcp_server.rs: use resolve_auth() for consistent behavior

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xdotli xdotli requested a review from jpoehnelt as a code owner March 5, 2026 04:10
@changeset-bot
Copy link

changeset-bot bot commented Mar 5, 2026

⚠️ No Changeset found

Latest commit: acd99c6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the gws tool by adding robust support for custom API endpoints, primarily to facilitate testing against mock servers. It introduces an environment variable, GWS_API_BASE_URL, which intelligently redirects API traffic and bypasses OAuth, streamlining development and CI workflows without affecting the core functionality of the Discovery Document or command structure.

Highlights

  • Custom API Endpoint Support: Introduced support for a GWS_API_BASE_URL environment variable, allowing all API requests to be redirected to a custom endpoint, such as a mock server.
  • Discovery Document URL Rewriting: When GWS_API_BASE_URL is set, the root_url and base_url within the fetched Discovery Document are rewritten to point to the custom endpoint, ensuring the CLI command tree remains functional while requests hit the mock server.
  • Automatic OAuth Skipping: OAuth authentication is automatically skipped when GWS_API_BASE_URL is configured, as mock servers typically do not require or support Google OAuth.
  • Consistent Behavior Across Modes: The custom endpoint and OAuth skipping functionality work consistently in both the CLI mode and the MCP server mode.
Changelog
  • src/discovery.rs
    • Introduced custom_api_base_url function to check for the GWS_API_BASE_URL environment variable.
    • Implemented logic within fetch_discovery_document to rewrite root_url and base_url of the Discovery Document when GWS_API_BASE_URL is set.
  • src/executor.rs
    • Introduced resolve_auth function to centralize authentication logic, automatically skipping OAuth when a custom API endpoint is configured.
  • src/main.rs
    • Updated authentication flow to use the new executor::resolve_auth helper.
  • src/mcp_server.rs
    • Updated authentication flow for the MCP server to use the new crate::executor::resolve_auth helper.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@google-cla
Copy link

google-cla bot commented Mar 5, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a GWS_API_BASE_URL environment variable to support custom API endpoints, which is a great feature for testing against mock servers. The implementation is solid: it correctly rewrites discovery document URLs, skips authentication for custom endpoints, and centralizes the new logic in helper functions for better maintainability. The changes are consistently applied across both CLI and MCP server modes. I have one suggestion to further improve the implementation by reading the environment variable only once.

Comment on lines +186 to +194
/// Returns the custom API base URL override, if set.
///
/// When `GWS_API_BASE_URL` is set (e.g., `http://localhost:8099`), all API
/// requests are directed to this endpoint instead of the real Google APIs.
/// Authentication is skipped automatically. This is useful for testing against
/// mock API servers.
pub fn custom_api_base_url() -> Option<String> {
std::env::var("GWS_API_BASE_URL").ok().filter(|s| !s.is_empty())
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better performance and to ensure consistency, it's a good practice to read the GWS_API_BASE_URL environment variable only once. You can use the once_cell crate to achieve this with a Lazy static. This avoids repeated environment variable lookups on every call.

You'll need to add once_cell = "1" to your Cargo.toml dependencies.

Suggested change
/// Returns the custom API base URL override, if set.
///
/// When `GWS_API_BASE_URL` is set (e.g., `http://localhost:8099`), all API
/// requests are directed to this endpoint instead of the real Google APIs.
/// Authentication is skipped automatically. This is useful for testing against
/// mock API servers.
pub fn custom_api_base_url() -> Option<String> {
std::env::var("GWS_API_BASE_URL").ok().filter(|s| !s.is_empty())
}
use once_cell::sync::Lazy; // Add to file imports
static GWS_API_BASE_URL: Lazy<Option<String>> =
Lazy::new(|| std::env::var("GWS_API_BASE_URL").ok().filter(|s| !s.is_empty()));
/// Returns the custom API base URL override, if set.
///
/// When `GWS_API_BASE_URL` is set (e.g., `http://localhost:8099`), all API
/// requests are directed to this endpoint instead of the real Google APIs.
/// Authentication is skipped automatically. This is useful for testing against
/// mock API servers.
pub fn custom_api_base_url() -> Option<String> {
GWS_API_BASE_URL.as_ref().cloned()
}

Read the environment variable once at startup instead of on every call.
Uses std::sync::LazyLock (stable since Rust 1.80) — no external crate needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@xdotli xdotli closed this Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant