Skip to content

fix: pass port and https flag to WorkOS SDK when base URL requires it#140

Merged
nicknisi merged 1 commit intoworkos:mainfrom
Langleu:main
May 5, 2026
Merged

fix: pass port and https flag to WorkOS SDK when base URL requires it#140
nicknisi merged 1 commit intoworkos:mainfrom
Langleu:main

Conversation

@Langleu
Copy link
Copy Markdown
Contributor

@Langleu Langleu commented May 4, 2026

I've been playing around a bit with the WorkOS emulator that's included in the CLI and started to grow on it, but it wasn't possible to run the CLI easily against the emulator.

Emulator runs by default on port 4100.

workos env add \
    --name emulator \
    --api-key sk_test_default \
    --endpoint http://localhost:4100

Using the cli with the env above would result for any command in

Unexpected error: TypeError: fetch failed

since it would try to talk to localhost:443 as the 443 is populated by the SDK, probably also had some issues with protocol.
The description of endpoint does not suggest anything against my understanding of the value.

--endpoint Custom API endpoint [string]`

Tested it locally:

# ./dist/bin.js env list
    Name                     Type          Endpoint
▸   emulator                 Sandbox       http://localhost:4100
# ./dist/bin.js org list
ID                              Name     Domains
───────────────────────────────────────────────────
org_01KQSNC2T5N9BXRCV4RYWTXTF1  Example  example.com

Probably could take this even further and say that by default it runs against itself but that's maybe room for improvement from maintainer site.

Summary by CodeRabbit

  • Bug Fixes
    • Improved WorkOS client URL initialization to properly handle hostname, port, and protocol configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

📝 Walkthrough

Walkthrough

The WorkOS SDK initialization in createWorkOSClient is enhanced to parse the base URL and conditionally configure apiHostname, port, and https settings based on the URL structure, replacing the prior hostname-only approach.

Changes

WorkOS SDK Configuration

Layer / File(s) Summary
Core Implementation
src/lib/workos-client.ts
The base URL is parsed into a URL object. The WorkOS SDK is initialized with apiHostname from url.hostname, conditionally includes port: Number(url.port) when present, and sets https: false for http: protocol schemes.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: pass port and https flag to WorkOS SDK when base URL requires it' accurately describes the main change: modifying how the WorkOS client passes configuration (port and protocol) to the SDK based on the provided base URL.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 4, 2026

Greptile Summary

This PR fixes SDK initialization in createWorkOSClient to correctly pass port and https: false to the WorkOS Node SDK when the configured base URL includes an explicit port or uses the http: protocol. Previously, only the hostname was forwarded, so pointing the CLI at a local emulator (e.g. http://localhost:4100) caused requests to silently target localhost:443 over HTTPS and fail with a network error.

The fix is minimal and correct: url.port is only spread when non-empty (avoiding overriding SDK defaults for standard ports), and https: false is only set when the protocol is explicitly http:.

Confidence Score: 5/5

Safe to merge — minimal, targeted fix with no regressions on the standard HTTPS path.

The change is a 4-line addition that correctly conditions port and https options on the parsed URL. Default ports (80/443) are not overridden because url.port returns an empty string for them. https: false is only applied when the user explicitly configured an http: URL, matching user intent. No existing behavior is altered for the production HTTPS path.

No files require special attention.

Important Files Changed

Filename Overview
src/lib/workos-client.ts SDK init now extracts port and protocol from the base URL and passes them to WorkOS constructor options; logic is correct and edge cases (no port, default ports, HTTPS) are handled properly.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI Command
    participant CWC as createWorkOSClient
    participant URL as URL parser
    participant SDK as WorkOS SDK

    CLI->>CWC: createWorkOSClient(apiKey, baseUrl)
    CWC->>URL: new URL(base)
    URL-->>CWC: { hostname, port, protocol }
    Note over CWC: Before fix: only hostname forwarded<br/>After fix: port + https flag also forwarded
    CWC->>SDK: new WorkOS(key, { apiHostname, port?, https? })
    SDK-->>CWC: sdk instance
    CWC-->>CLI: { sdk, webhooks, redirectUris, ... }
    CLI->>SDK: sdk.organizations.list()
    SDK-->>CLI: Response from correct host:port
Loading

Reviews (1): Last reviewed commit: "fix: pass port and https flag to WorkOS ..." | Re-trigger Greptile

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b716e84d-f625-42af-93d7-61b745060b33

📥 Commits

Reviewing files that changed from the base of the PR and between 9179874 and cd44c5f.

📒 Files selected for processing (1)
  • src/lib/workos-client.ts

Comment thread src/lib/workos-client.ts
Comment on lines +63 to +68
const url = new URL(base);
const sdk = new WorkOS(key, {
apiHostname: url.hostname,
...(url.port && { port: Number(url.port) }),
...(url.protocol === 'http:' && { https: false }),
});
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 4, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate base format before using new URL to avoid opaque runtime failures.

At Line 63, new URL(base) assumes base is a full http(s) URL. Because endpoint values are user-provided and currently unvalidated upstream, malformed or shorthand inputs can throw/misparse and later fail as generic fetch failed. Add protocol/hostname validation with a clear error message at this boundary.

Suggested fix
-  const url = new URL(base);
+  let url: URL;
+  try {
+    url = new URL(base);
+  } catch {
+    throw new Error(`Invalid API base URL "${base}". Expected a full URL like "https://api.workos.com" or "http://localhost:4100".`);
+  }
+
+  if (!['http:', 'https:'].includes(url.protocol) || !url.hostname) {
+    throw new Error(`Invalid API base URL "${base}". Only http/https URLs with a hostname are supported.`);
+  }
+
   const sdk = new WorkOS(key, {
     apiHostname: url.hostname,
     ...(url.port && { port: Number(url.port) }),
     ...(url.protocol === 'http:' && { https: false }),
   });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const url = new URL(base);
const sdk = new WorkOS(key, {
apiHostname: url.hostname,
...(url.port && { port: Number(url.port) }),
...(url.protocol === 'http:' && { https: false }),
});
let url: URL;
try {
url = new URL(base);
} catch {
throw new Error(`Invalid API base URL "${base}". Expected a full URL like "https://api.workos.com" or "http://localhost:4100".`);
}
if (!['http:', 'https:'].includes(url.protocol) || !url.hostname) {
throw new Error(`Invalid API base URL "${base}". Only http/https URLs with a hostname are supported.`);
}
const sdk = new WorkOS(key, {
apiHostname: url.hostname,
...(url.port && { port: Number(url.port) }),
...(url.protocol === 'http:' && { https: false }),
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it's a pre-existing issue of the code, it currently doesn't handle it either and just crashes with ERR_INVALID_URL

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@Langleu, that's a fair point — the previous new URL(base).hostname call had the exact same behaviour, so this PR doesn't regress anything there. I'll withdraw the concern for this PR.

Would you like me to open a follow-up GitHub issue to track adding proper URL validation (with a user-friendly error message) as a future improvement? It'd be a clean, standalone change that won't block this fix.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

so it's already letting a user know that's not what is expected.
I think the better fix would be to adjust whatever is expected by the CLI in the first place vs just Custom API endpoint.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

Good point — improving the prompt/placeholder/description at the input level is a cleaner UX fix. Let me find where that prompt lives in the codebase.


🏁 Script executed:

#!/bin/bash
rg -rn "Custom API endpoint" --type ts -C5
rg -rn "Custom API endpoint" --type js -C5
rg -rn "baseUrl\|base_url\|apiEndpoint\|endpoint" --type ts -n -C3 | grep -i "prompt\|input\|question\|placeholder\|label" | head -40

Length of output: 1284


🏁 Script executed:

#!/bin/bash
# Find env command file
fd -e ts env src/commands/
# Look at the full env command
cat src/commands/env.ts 2>/dev/null || fd -e ts -e js "env" src/commands/ --exec cat {}
# Check bin.ts around endpoint option
rg -n "endpoint" src/bin.ts -C3

Length of output: 8944


@Langleu, agreed — improving the CLI-level description is the right place for this. Looking at the code, there are two spots that could be made more explicit:

  1. src/bin.ts Line 369 — the --endpoint flag description is just 'Custom API endpoint', which doesn't hint at the expected format:

    // before
    .option('endpoint', { type: 'string', describe: 'Custom API endpoint' })
    
    // after
    .option('endpoint', { type: 'string', describe: 'Custom API endpoint URL, e.g. http://localhost:4100' })
  2. src/utils/help-json.ts — the endpoint description there also appears to be a stale/truncated artifact ('n URL'), which would be worth fixing alongside.

  3. Interactive env add flow in src/commands/env.ts — the interactive wizard currently doesn't prompt for endpoint at all (only name, type, and API key). If the target audience for this is local emulator users who run workos env add interactively, it may be worth adding an optional prompt there too, with placeholder text showing the expected format:

    const endpointResult = await clack.text({
      message: 'Custom API endpoint URL (optional, e.g. http://localhost:4100)',
      placeholder: 'Leave blank for default (https://api.workos.com)',
    });
    if (!clack.isCancel(endpointResult) && endpointResult) {
      endpoint = endpointResult;
    }

Would you like me to open a follow-up issue to track the interactive-prompt gap and the help-json.ts description fix?

@Langleu
Copy link
Copy Markdown
Contributor Author

Langleu commented May 4, 2026

Generally interested what the plans are further for this cli / emulator topic?
Feature flags I saw are somewhat implemented but are missing actual endpoints to create via either cli / api / seed file.

I'd like to utilize the emulator topic for local development in dev environments as well as for temporary preview environments.
While WorkOS has environments it's all "click-ops" as there are no API endpoints for the environment (creation / deletion). This emulator is great for ephemeral environments.

@nicknisi
Copy link
Copy Markdown
Member

nicknisi commented May 4, 2026

Thanks for this, I'll take a look today.

Yes! The plan is to support this specifically to make it easier to test in offline/ephemeral environments. It's kind of stealth-shipped right now while we work out all the issues and ensure stability.

@Langleu
Copy link
Copy Markdown
Contributor Author

Langleu commented May 4, 2026

Thanks, I appreciate it!

Nice, makes sense. I only stumbled upon the emulator by accident after I read through the whole README, as workos dev wasn't listed among the commands, but I've got it working so far to replace the cloud environment.

Some sort of stickiness would be nice for the IDs, to have proper drop-in, but it might as well be on me to properly use external_id instead 😄.

@nicknisi nicknisi merged commit b7909e8 into workos:main May 5, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants