Skip to content

Commit

Permalink
fix(client): ensure urls have trailing slashes (#361)
Browse files Browse the repository at this point in the history
* fix(client): ensure urls have trailing slashes

Some API routes need to have a trailing slash on the end. If they don't,
you can see errors such as 404, 405, 307, etc.

Closes https://linear.app/prefect/issue/PLA-948/workspace-create-fails-with-404-when-endpoint-is-set

Closes #359

* Add script to check for trailing slash routes

Adds a script to help check which routes have trailing slashes.

* Flows: put trailing slash on the right field

* Add note to contributing docs
  • Loading branch information
mitchnielsen authored Jan 31, 2025
1 parent c2f14e1 commit 532de87
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 4 deletions.
11 changes: 11 additions & 0 deletions _about/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,14 @@ A helper function named `validateCloudEndpoint` in the `internal/client` package
to validate that a `workspace_id` is configured, and provide an informative error if not.

If the API endpoint does not require a `workspace_id`, such as `accounts`, you can omit this helper function.

### API route considerations

Certain API routes require a traling slash (`/`). These are most often for `POST` methods used
for creating resources.

If the trailing slash is not provided, it can lead to errors such as 404, 405, 307, etc.

A helper script is available in `../scripts/trailing-slash-routes`. Running this will produce JSON output that
lists which routes end with a slash, along with the method and description to more easily identify which functions
to check under `../internal/client/*.go`.
2 changes: 1 addition & 1 deletion internal/client/deployments.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (c *Client) Deployments(accountID uuid.UUID, workspaceID uuid.UUID) (api.De
func (c *DeploymentsClient) Create(ctx context.Context, data api.DeploymentCreate) (*api.Deployment, error) {
cfg := requestConfig{
method: http.MethodPost,
url: c.routePrefix,
url: c.routePrefix + "/",
body: &data,
apiKey: c.apiKey,
successCodes: successCodesStatusCreated,
Expand Down
2 changes: 1 addition & 1 deletion internal/client/flows.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (c *Client) Flows(accountID uuid.UUID, workspaceID uuid.UUID) (api.FlowsCli
func (c *FlowsClient) Create(ctx context.Context, data api.FlowCreate) (*api.Flow, error) {
cfg := requestConfig{
method: http.MethodPost,
url: c.routePrefix,
url: c.routePrefix + "/",
body: &data,
apiKey: c.apiKey,
successCodes: successCodesStatusCreated,
Expand Down
2 changes: 1 addition & 1 deletion internal/client/workspace_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (c *Client) WorkspaceRoles(accountID uuid.UUID) (api.WorkspaceRolesClient,
func (c *WorkspaceRolesClient) Create(ctx context.Context, data api.WorkspaceRoleUpsert) (*api.WorkspaceRole, error) {
cfg := requestConfig{
method: http.MethodPost,
url: c.routePrefix,
url: c.routePrefix + "/",
body: &data,
apiKey: c.apiKey,
successCodes: successCodesStatusCreated,
Expand Down
2 changes: 1 addition & 1 deletion internal/client/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (c *Client) Workspaces(accountID uuid.UUID) (api.WorkspacesClient, error) {
func (c *WorkspacesClient) Create(ctx context.Context, data api.WorkspaceCreate) (*api.Workspace, error) {
cfg := requestConfig{
method: http.MethodPost,
url: c.routePrefix,
url: c.routePrefix + "/",
body: &data,
apiKey: c.apiKey,
successCodes: successCodesStatusCreated,
Expand Down
36 changes: 36 additions & 0 deletions scripts/trailing-slash-routes
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash

# This script checks for all endpoints that require a trailing slash.
# Files in internal/client/*.go should be checked to confirm that any
# `url` fields in the request configuration include the trailing slash
# when needed.
#
# This helps avoid errors like https://github.com/PrefectHQ/terraform-provider-prefect/issues/359.
#
# It can be helpful to redirect the output to a file for further analysis:
#
# ./scripts/trailing-slash-routes > trailing-slash-routes.json
#
# You can then use tools like `jq` to parse the results.
#
# Example output:
#
# [
# {
# "path": "/api/accounts/{account_id}/teams/",
# "method": "post",
# "desc": "Create or update a team's metadata.\n\nRequired account permissions: `create:team`"
# },
# {
# "path": "/api/accounts/{account_id}/bots/",
# "method": "post",
# "desc": "Create a Bot\n\nRequired account permissions: `create:bot`"
# },
# ...
# }

curl -s https://api.prefect.cloud/api/openapi.json |
jq '.paths
| to_entries
| map({path: .key, method: (.value | to_entries[0].key), desc: (.value | to_entries[0].value.description)})
| map(select(.path | test("/$")))'

0 comments on commit 532de87

Please sign in to comment.