fix: url escape path components

Signed-off-by: Babak K. Shandiz <babakks@github.com>
This commit is contained in:
Babak K. Shandiz 2026-04-22 15:55:02 +01:00
parent 3ad29588b8
commit 74054c0f71
No known key found for this signature in database
GPG key ID: 9472CAEFF56C742E
11 changed files with 41 additions and 31 deletions

View file

@ -374,10 +374,10 @@ func (a *API) ListCodespaces(ctx context.Context, opts ListCodespacesOptions) (c
orgName := opts.OrgName
if opts.UserName != "" {
userName := opts.UserName
listURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces?per_page=%d", a.githubAPI, orgName, userName, perPage)
listURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces?per_page=%d", a.githubAPI, url.PathEscape(orgName), url.PathEscape(userName), perPage)
spanName = "/orgs/*/members/*/codespaces"
} else {
listURL = fmt.Sprintf("%s/orgs/%s/codespaces?per_page=%d", a.githubAPI, orgName, perPage)
listURL = fmt.Sprintf("%s/orgs/%s/codespaces?per_page=%d", a.githubAPI, url.PathEscape(orgName), perPage)
spanName = "/orgs/*/codespaces"
}
} else {
@ -445,7 +445,7 @@ func findNextPage(linkValue string) string {
func (a *API) GetOrgMemberCodespace(ctx context.Context, orgName string, userName string, codespaceName string) (*Codespace, error) {
perPage := 100
listURL := fmt.Sprintf("%s/orgs/%s/members/%s/codespaces?per_page=%d", a.githubAPI, orgName, userName, perPage)
listURL := fmt.Sprintf("%s/orgs/%s/members/%s/codespaces?per_page=%d", a.githubAPI, url.PathEscape(orgName), url.PathEscape(userName), perPage)
for {
req, err := http.NewRequest(http.MethodGet, listURL, nil)
@ -569,10 +569,10 @@ func (a *API) StopCodespace(ctx context.Context, codespaceName string, orgName s
var spanName string
if orgName != "" {
stopURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s/stop", a.githubAPI, orgName, userName, codespaceName)
stopURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s/stop", a.githubAPI, url.PathEscape(orgName), url.PathEscape(userName), url.PathEscape(codespaceName))
spanName = "/orgs/*/members/*/codespaces/*/stop"
} else {
stopURL = fmt.Sprintf("%s/user/codespaces/%s/stop", a.githubAPI, codespaceName)
stopURL = fmt.Sprintf("%s/user/codespaces/%s/stop", a.githubAPI, url.PathEscape(codespaceName))
spanName = "/user/codespaces/*/stop"
}
@ -976,10 +976,10 @@ func (a *API) DeleteCodespace(ctx context.Context, codespaceName string, orgName
var spanName string
if orgName != "" && userName != "" {
deleteURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s", a.githubAPI, orgName, userName, codespaceName)
deleteURL = fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s", a.githubAPI, url.PathEscape(orgName), url.PathEscape(userName), url.PathEscape(codespaceName))
spanName = "/orgs/*/members/*/codespaces/*"
} else {
deleteURL = a.githubAPI + "/user/codespaces/" + codespaceName
deleteURL = a.githubAPI + "/user/codespaces/" + url.PathEscape(codespaceName)
spanName = "/user/codespaces/*"
}

View file

@ -7,6 +7,7 @@ import (
"fmt"
"math/rand"
"net/http"
"net/url"
"strings"
"time"
@ -156,7 +157,7 @@ func createLabel(client *http.Client, repo ghrepo.Interface, opts *createOptions
}
func updateLabel(apiClient *api.Client, repo ghrepo.Interface, opts *editOptions) error {
path := fmt.Sprintf("repos/%s/%s/labels/%s", repo.RepoOwner(), repo.RepoName(), opts.Name)
path := fmt.Sprintf("repos/%s/%s/labels/%s", repo.RepoOwner(), repo.RepoName(), url.PathEscape(opts.Name))
properties := map[string]string{}
if opts.Description != "" {
properties["description"] = opts.Description

View file

@ -3,6 +3,7 @@ package label
import (
"fmt"
"net/http"
"net/url"
"github.com/cli/cli/v2/api"
"github.com/cli/cli/v2/internal/ghrepo"
@ -94,7 +95,7 @@ func deleteRun(opts *deleteOptions) error {
func deleteLabel(client *http.Client, repo ghrepo.Interface, name string) error {
apiClient := api.NewClientFromHTTP(client)
path := fmt.Sprintf("repos/%s/%s/labels/%s", repo.RepoOwner(), repo.RepoName(), name)
path := fmt.Sprintf("repos/%s/%s/labels/%s", repo.RepoOwner(), repo.RepoName(), url.PathEscape(name))
return apiClient.REST(repo.RepoHost(), "DELETE", path, nil, nil)
}

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"net/url"
"strings"
"github.com/cli/cli/v2/api"
@ -254,7 +255,7 @@ func (r *ownerResponse) IsOrganization() bool {
func resolveOwner(client *api.Client, hostname, orgName string) (*ownerResponse, error) {
var response ownerResponse
err := client.REST(hostname, "GET", fmt.Sprintf("users/%s", orgName), nil, &response)
err := client.REST(hostname, "GET", fmt.Sprintf("users/%s", url.PathEscape(orgName)), nil, &response)
return &response, err
}
@ -268,7 +269,7 @@ type teamResponse struct {
func resolveOrganizationTeam(client *api.Client, hostname, orgName, teamSlug string) (*teamResponse, error) {
var response teamResponse
err := client.REST(hostname, "GET", fmt.Sprintf("orgs/%s/teams/%s", orgName, teamSlug), nil, &response)
err := client.REST(hostname, "GET", fmt.Sprintf("orgs/%s/teams/%s", url.PathEscape(orgName), url.PathEscape(teamSlug)), nil, &response)
return &response, err
}

View file

@ -3,6 +3,7 @@ package view
import (
"fmt"
"net/http"
"net/url"
"github.com/cli/cli/v2/api"
"github.com/cli/cli/v2/internal/ghrepo"
@ -15,7 +16,7 @@ func viewRepoRuleset(httpClient *http.Client, repo ghrepo.Interface, databaseId
}
func viewOrgRuleset(httpClient *http.Client, orgLogin string, databaseId string, host string) (*shared.RulesetREST, error) {
path := fmt.Sprintf("orgs/%s/rulesets/%s", orgLogin, databaseId)
path := fmt.Sprintf("orgs/%s/rulesets/%s", url.PathEscape(orgLogin), databaseId)
return viewRuleset(httpClient, host, path)
}

View file

@ -3,6 +3,7 @@ package delete
import (
"fmt"
"net/http"
"net/url"
"os"
"github.com/MakeNowJust/heredoc"
@ -127,16 +128,16 @@ func removeRun(opts *DeleteOptions) error {
var host string
switch secretEntity {
case shared.Organization:
path = fmt.Sprintf("orgs/%s/%s/secrets/%s", orgName, secretApp, opts.SecretName)
path = fmt.Sprintf("orgs/%s/%s/secrets/%s", url.PathEscape(orgName), secretApp, url.PathEscape(opts.SecretName))
host, _ = cfg.Authentication().DefaultHost()
case shared.Environment:
path = fmt.Sprintf("repos/%s/environments/%s/secrets/%s", ghrepo.FullName(baseRepo), envName, opts.SecretName)
path = fmt.Sprintf("repos/%s/environments/%s/secrets/%s", ghrepo.FullName(baseRepo), url.PathEscape(envName), url.PathEscape(opts.SecretName))
host = baseRepo.RepoHost()
case shared.User:
path = fmt.Sprintf("user/codespaces/secrets/%s", opts.SecretName)
path = fmt.Sprintf("user/codespaces/secrets/%s", url.PathEscape(opts.SecretName))
host, _ = cfg.Authentication().DefaultHost()
case shared.Repository:
path = fmt.Sprintf("repos/%s/%s/secrets/%s", ghrepo.FullName(baseRepo), secretApp, opts.SecretName)
path = fmt.Sprintf("repos/%s/%s/secrets/%s", ghrepo.FullName(baseRepo), secretApp, url.PathEscape(opts.SecretName))
host = baseRepo.RepoHost()
}

View file

@ -3,6 +3,7 @@ package list
import (
"fmt"
"net/http"
"net/url"
"os"
"slices"
"strings"
@ -248,7 +249,7 @@ func fmtVisibility(s Secret) string {
}
func getOrgSecrets(client *http.Client, host, orgName string, showSelectedRepoInfo bool, app shared.App) ([]Secret, error) {
secrets, err := getSecrets(client, host, fmt.Sprintf("orgs/%s/%s/secrets", orgName, app))
secrets, err := getSecrets(client, host, fmt.Sprintf("orgs/%s/%s/secrets", url.PathEscape(orgName), app))
if err != nil {
return nil, err
}
@ -279,7 +280,7 @@ func getUserSecrets(client *http.Client, host string, showSelectedRepoInfo bool)
}
func getEnvSecrets(client *http.Client, repo ghrepo.Interface, envName string) ([]Secret, error) {
path := fmt.Sprintf("repos/%s/environments/%s/secrets", ghrepo.FullName(repo), envName)
path := fmt.Sprintf("repos/%s/environments/%s/secrets", ghrepo.FullName(repo), url.PathEscape(envName))
return getSecrets(client, repo.RepoHost(), path)
}

View file

@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"strconv"
"github.com/cli/cli/v2/api"
@ -40,7 +41,7 @@ func getPubKey(client *api.Client, host, path string) (*PubKey, error) {
}
func getOrgPublicKey(client *api.Client, host, orgName string, app shared.App) (*PubKey, error) {
return getPubKey(client, host, fmt.Sprintf("orgs/%s/%s/secrets/public-key", orgName, app))
return getPubKey(client, host, fmt.Sprintf("orgs/%s/%s/secrets/public-key", url.PathEscape(orgName), app))
}
func getUserPublicKey(client *api.Client, host string) (*PubKey, error) {
@ -54,7 +55,7 @@ func getRepoPubKey(client *api.Client, repo ghrepo.Interface, app shared.App) (*
func getEnvPubKey(client *api.Client, repo ghrepo.Interface, envName string) (*PubKey, error) {
return getPubKey(client, repo.RepoHost(), fmt.Sprintf("repos/%s/environments/%s/secrets/public-key",
ghrepo.FullName(repo), envName))
ghrepo.FullName(repo), url.PathEscape(envName)))
}
func putSecret(client *api.Client, host, path string, payload interface{}) error {
@ -68,7 +69,7 @@ func putSecret(client *api.Client, host, path string, payload interface{}) error
}
func putOrgSecret(client *api.Client, host string, pk *PubKey, orgName, visibility, secretName, eValue string, repositoryIDs []int64, app shared.App) error {
path := fmt.Sprintf("orgs/%s/%s/secrets/%s", orgName, app, secretName)
path := fmt.Sprintf("orgs/%s/%s/secrets/%s", url.PathEscape(orgName), app, url.PathEscape(secretName))
if app == shared.Dependabot {
repos := make([]string, len(repositoryIDs))
@ -111,7 +112,7 @@ func putEnvSecret(client *api.Client, pk *PubKey, repo ghrepo.Interface, envName
EncryptedValue: eValue,
KeyID: pk.ID,
}
path := fmt.Sprintf("repos/%s/environments/%s/secrets/%s", ghrepo.FullName(repo), envName, secretName)
path := fmt.Sprintf("repos/%s/environments/%s/secrets/%s", ghrepo.FullName(repo), url.PathEscape(envName), url.PathEscape(secretName))
return putSecret(client, repo.RepoHost(), path, payload)
}
@ -120,6 +121,6 @@ func putRepoSecret(client *api.Client, pk *PubKey, repo ghrepo.Interface, secret
EncryptedValue: eValue,
KeyID: pk.ID,
}
path := fmt.Sprintf("repos/%s/%s/secrets/%s", ghrepo.FullName(repo), app, secretName)
path := fmt.Sprintf("repos/%s/%s/secrets/%s", ghrepo.FullName(repo), app, url.PathEscape(secretName))
return putSecret(client, repo.RepoHost(), path, payload)
}

View file

@ -3,6 +3,7 @@ package delete
import (
"fmt"
"net/http"
"net/url"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/api"
@ -100,13 +101,13 @@ func removeRun(opts *DeleteOptions) error {
var host string
switch variableEntity {
case shared.Organization:
path = fmt.Sprintf("orgs/%s/actions/variables/%s", orgName, opts.VariableName)
path = fmt.Sprintf("orgs/%s/actions/variables/%s", url.PathEscape(orgName), url.PathEscape(opts.VariableName))
host, _ = cfg.Authentication().DefaultHost()
case shared.Environment:
path = fmt.Sprintf("repos/%s/environments/%s/variables/%s", ghrepo.FullName(baseRepo), envName, opts.VariableName)
path = fmt.Sprintf("repos/%s/environments/%s/variables/%s", ghrepo.FullName(baseRepo), url.PathEscape(envName), url.PathEscape(opts.VariableName))
host = baseRepo.RepoHost()
case shared.Repository:
path = fmt.Sprintf("repos/%s/actions/variables/%s", ghrepo.FullName(baseRepo), opts.VariableName)
path = fmt.Sprintf("repos/%s/actions/variables/%s", ghrepo.FullName(baseRepo), url.PathEscape(opts.VariableName))
host = baseRepo.RepoHost()
}

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/api"
@ -101,13 +102,13 @@ func getRun(opts *GetOptions) error {
var host string
switch variableEntity {
case shared.Organization:
path = fmt.Sprintf("orgs/%s/actions/variables/%s", orgName, opts.VariableName)
path = fmt.Sprintf("orgs/%s/actions/variables/%s", url.PathEscape(orgName), url.PathEscape(opts.VariableName))
host, _ = cfg.Authentication().DefaultHost()
case shared.Environment:
path = fmt.Sprintf("repos/%s/environments/%s/variables/%s", ghrepo.FullName(baseRepo), envName, opts.VariableName)
path = fmt.Sprintf("repos/%s/environments/%s/variables/%s", ghrepo.FullName(baseRepo), url.PathEscape(envName), url.PathEscape(opts.VariableName))
host = baseRepo.RepoHost()
case shared.Repository:
path = fmt.Sprintf("repos/%s/actions/variables/%s", ghrepo.FullName(baseRepo), opts.VariableName)
path = fmt.Sprintf("repos/%s/actions/variables/%s", ghrepo.FullName(baseRepo), url.PathEscape(opts.VariableName))
host = baseRepo.RepoHost()
}

View file

@ -3,6 +3,7 @@ package list
import (
"fmt"
"net/http"
"net/url"
"slices"
"strings"
"time"
@ -197,12 +198,12 @@ func getRepoVariables(client *http.Client, repo ghrepo.Interface) ([]shared.Vari
}
func getEnvVariables(client *http.Client, repo ghrepo.Interface, envName string) ([]shared.Variable, error) {
path := fmt.Sprintf("repos/%s/environments/%s/variables", ghrepo.FullName(repo), envName)
path := fmt.Sprintf("repos/%s/environments/%s/variables", ghrepo.FullName(repo), url.PathEscape(envName))
return getVariables(client, repo.RepoHost(), path)
}
func getOrgVariables(client *http.Client, host, orgName string, showSelectedRepoInfo bool) ([]shared.Variable, error) {
variables, err := getVariables(client, host, fmt.Sprintf("orgs/%s/actions/variables", orgName))
variables, err := getVariables(client, host, fmt.Sprintf("orgs/%s/actions/variables", url.PathEscape(orgName)))
if err != nil {
return nil, err
}