diff --git a/api/acl.go b/api/acl.go index 0f44494dda..c3038e3898 100644 --- a/api/acl.go +++ b/api/acl.go @@ -552,7 +552,7 @@ func (a *ACL) Update(acl *ACLEntry, q *WriteOptions) (*WriteMeta, error) { // // Deprecated: Use TokenDelete instead. func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/destroy/"+id) + r := a.c.newRequest("PUT", "/v1/acl/destroy/"+url.PathEscape(id)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -571,7 +571,7 @@ func (a *ACL) Destroy(id string, q *WriteOptions) (*WriteMeta, error) { // // Deprecated: Use TokenClone instead. func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { - r := a.c.newRequest("PUT", "/v1/acl/clone/"+id) + r := a.c.newRequest("PUT", "/v1/acl/clone/"+url.PathEscape(id)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -594,7 +594,7 @@ func (a *ACL) Clone(id string, q *WriteOptions) (string, *WriteMeta, error) { // // Deprecated: Use TokenRead instead. func (a *ACL) Info(id string, q *QueryOptions) (*ACLEntry, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/info/"+id) + r := a.c.newRequest("GET", "/v1/acl/info/"+url.PathEscape(id)) r.setQueryOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -696,7 +696,7 @@ func (a *ACL) TokenUpdate(token *ACLToken, q *WriteOptions) (*ACLToken, *WriteMe if token.AccessorID == "" { return nil, nil, fmt.Errorf("Must specify an AccessorID for Token Updating") } - r := a.c.newRequest("PUT", "/v1/acl/token/"+token.AccessorID) + r := a.c.newRequest("PUT", "/v1/acl/token/"+url.PathEscape(token.AccessorID)) r.setWriteOptions(q) r.obj = token rtt, resp, err := a.c.doRequest(r) @@ -725,7 +725,7 @@ func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (* return nil, nil, fmt.Errorf("Must specify a tokenID for Token Cloning") } - r := a.c.newRequest("PUT", "/v1/acl/token/"+tokenID+"/clone") + r := a.c.newRequest("PUT", "/v1/acl/token/"+url.PathEscape(tokenID)+"/clone") r.setWriteOptions(q) r.obj = struct{ Description string }{description} rtt, resp, err := a.c.doRequest(r) @@ -748,7 +748,7 @@ func (a *ACL) TokenClone(tokenID string, description string, q *WriteOptions) (* // TokenDelete removes a single ACL token. The tokenID parameter must be a valid // Accessor ID of an existing token. func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/token/"+tokenID) + r := a.c.newRequest("DELETE", "/v1/acl/token/"+url.PathEscape(tokenID)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -766,7 +766,7 @@ func (a *ACL) TokenDelete(tokenID string, q *WriteOptions) (*WriteMeta, error) { // TokenRead retrieves the full token details. The tokenID parameter must be a valid // Accessor ID of an existing token. func (a *ACL) TokenRead(tokenID string, q *QueryOptions) (*ACLToken, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/token/"+tokenID) + r := a.c.newRequest("GET", "/v1/acl/token/"+url.PathEscape(tokenID)) r.setQueryOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -871,7 +871,7 @@ func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *Wri return nil, nil, fmt.Errorf("Must specify an ID in Policy Update") } - r := a.c.newRequest("PUT", "/v1/acl/policy/"+policy.ID) + r := a.c.newRequest("PUT", "/v1/acl/policy/"+url.PathEscape(policy.ID)) r.setWriteOptions(q) r.obj = policy rtt, resp, err := a.c.doRequest(r) @@ -893,7 +893,7 @@ func (a *ACL) PolicyUpdate(policy *ACLPolicy, q *WriteOptions) (*ACLPolicy, *Wri // PolicyDelete deletes a policy given its ID. func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/policy/"+policyID) + r := a.c.newRequest("DELETE", "/v1/acl/policy/"+url.PathEscape(policyID)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -910,7 +910,7 @@ func (a *ACL) PolicyDelete(policyID string, q *WriteOptions) (*WriteMeta, error) // PolicyRead retrieves the policy details including the rule set. func (a *ACL) PolicyRead(policyID string, q *QueryOptions) (*ACLPolicy, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/policy/"+policyID) + r := a.c.newRequest("GET", "/v1/acl/policy/"+url.PathEscape(policyID)) r.setQueryOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -1021,7 +1021,7 @@ func (a *ACL) RulesTranslate(rules io.Reader) (string, error) { // Deprecated: Support for the legacy syntax translation will be removed // when legacy ACL support is removed. func (a *ACL) RulesTranslateToken(tokenID string) (string, error) { - r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+tokenID) + r := a.c.newRequest("GET", "/v1/acl/rules/translate/"+url.PathEscape(tokenID)) rtt, resp, err := a.c.doRequest(r) if err != nil { return "", err @@ -1076,7 +1076,7 @@ func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, return nil, nil, fmt.Errorf("Must specify an ID in Role Update") } - r := a.c.newRequest("PUT", "/v1/acl/role/"+role.ID) + r := a.c.newRequest("PUT", "/v1/acl/role/"+url.PathEscape(role.ID)) r.setWriteOptions(q) r.obj = role rtt, resp, err := a.c.doRequest(r) @@ -1098,7 +1098,7 @@ func (a *ACL) RoleUpdate(role *ACLRole, q *WriteOptions) (*ACLRole, *WriteMeta, // RoleDelete deletes a role given its ID. func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/role/"+roleID) + r := a.c.newRequest("DELETE", "/v1/acl/role/"+url.PathEscape(roleID)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -1115,7 +1115,7 @@ func (a *ACL) RoleDelete(roleID string, q *WriteOptions) (*WriteMeta, error) { // RoleRead retrieves the role details (by ID). Returns nil if not found. func (a *ACL) RoleRead(roleID string, q *QueryOptions) (*ACLRole, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/role/"+roleID) + r := a.c.newRequest("GET", "/v1/acl/role/"+url.PathEscape(roleID)) r.setQueryOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -1365,7 +1365,7 @@ func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBind return nil, nil, fmt.Errorf("Must specify an ID in Binding Rule Update") } - r := a.c.newRequest("PUT", "/v1/acl/binding-rule/"+rule.ID) + r := a.c.newRequest("PUT", "/v1/acl/binding-rule/"+url.PathEscape(rule.ID)) r.setWriteOptions(q) r.obj = rule rtt, resp, err := a.c.doRequest(r) @@ -1387,7 +1387,7 @@ func (a *ACL) BindingRuleUpdate(rule *ACLBindingRule, q *WriteOptions) (*ACLBind // BindingRuleDelete deletes a binding rule given its ID. func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMeta, error) { - r := a.c.newRequest("DELETE", "/v1/acl/binding-rule/"+bindingRuleID) + r := a.c.newRequest("DELETE", "/v1/acl/binding-rule/"+url.PathEscape(bindingRuleID)) r.setWriteOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { @@ -1404,7 +1404,7 @@ func (a *ACL) BindingRuleDelete(bindingRuleID string, q *WriteOptions) (*WriteMe // BindingRuleRead retrieves the binding rule details. Returns nil if not found. func (a *ACL) BindingRuleRead(bindingRuleID string, q *QueryOptions) (*ACLBindingRule, *QueryMeta, error) { - r := a.c.newRequest("GET", "/v1/acl/binding-rule/"+bindingRuleID) + r := a.c.newRequest("GET", "/v1/acl/binding-rule/"+url.PathEscape(bindingRuleID)) r.setQueryOptions(q) rtt, resp, err := a.c.doRequest(r) if err != nil { diff --git a/api/catalog.go b/api/catalog.go index 80ae325eac..54fcce85f4 100644 --- a/api/catalog.go +++ b/api/catalog.go @@ -2,6 +2,7 @@ package api import ( "net" + "net/url" "strconv" ) @@ -254,9 +255,9 @@ func (c *Catalog) ConnectMultipleTags(service string, tags []string, q *QueryOpt } func (c *Catalog) service(service string, tags []string, q *QueryOptions, connect bool) ([]*CatalogService, *QueryMeta, error) { - path := "/v1/catalog/service/" + service + path := "/v1/catalog/service/" + url.PathEscape(service) if connect { - path = "/v1/catalog/connect/" + service + path = "/v1/catalog/connect/" + url.PathEscape(service) } r := c.c.newRequest("GET", path) r.setQueryOptions(q) @@ -287,7 +288,7 @@ func (c *Catalog) service(service string, tags []string, q *QueryOptions, connec // Node is used to query for service information about a single node func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/node/"+node) + r := c.c.newRequest("GET", "/v1/catalog/node/"+url.PathEscape(node)) r.setQueryOptions(q) rtt, resp, err := c.c.doRequest(r) if err != nil { @@ -314,7 +315,7 @@ func (c *Catalog) Node(node string, q *QueryOptions) (*CatalogNode, *QueryMeta, // a map of service ids to services. This different structure allows for using the wildcard specifier // '*' for the Namespace in the QueryOptions. func (c *Catalog) NodeServiceList(node string, q *QueryOptions) (*CatalogNodeServiceList, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/node-services/"+node) + r := c.c.newRequest("GET", "/v1/catalog/node-services/"+url.PathEscape(node)) r.setQueryOptions(q) rtt, resp, err := c.c.doRequest(r) if err != nil { @@ -338,7 +339,7 @@ func (c *Catalog) NodeServiceList(node string, q *QueryOptions) (*CatalogNodeSer // GatewayServices is used to query the services associated with an ingress gateway or terminating gateway. func (c *Catalog) GatewayServices(gateway string, q *QueryOptions) ([]*GatewayService, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/catalog/gateway-services/"+gateway) + r := c.c.newRequest("GET", "/v1/catalog/gateway-services/"+url.PathEscape(gateway)) r.setQueryOptions(q) rtt, resp, err := c.c.doRequest(r) if err != nil { diff --git a/api/config_entry.go b/api/config_entry.go index 91c407bb53..f1c4091d10 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "net/url" "strconv" "strings" "time" @@ -378,7 +379,7 @@ func (conf *ConfigEntries) Get(kind string, name string, q *QueryOptions) (Confi return nil, nil, err } - r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s/%s", kind, name)) + r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s/%s", url.PathEscape(kind), url.PathEscape(name))) r.setQueryOptions(q) rtt, resp, err := conf.c.doRequest(r) if err != nil { @@ -405,7 +406,7 @@ func (conf *ConfigEntries) List(kind string, q *QueryOptions) ([]ConfigEntry, *Q return nil, nil, fmt.Errorf("The kind parameter must not be empty") } - r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s", kind)) + r := conf.c.newRequest("GET", fmt.Sprintf("/v1/config/%s", url.PathEscape(kind))) r.setQueryOptions(q) rtt, resp, err := conf.c.doRequest(r) if err != nil { @@ -485,7 +486,7 @@ func (conf *ConfigEntries) delete(kind, name string, params map[string]string, w return false, nil, fmt.Errorf("Both kind and name parameters must not be empty") } - r := conf.c.newRequest("DELETE", fmt.Sprintf("/v1/config/%s/%s", kind, name)) + r := conf.c.newRequest("DELETE", fmt.Sprintf("/v1/config/%s/%s", url.PathEscape(kind), url.PathEscape(name))) r.setWriteOptions(w) for param, value := range params { r.params.Set(param, value) diff --git a/api/coordinate.go b/api/coordinate.go index 7ef6ce2744..bd607e32fd 100644 --- a/api/coordinate.go +++ b/api/coordinate.go @@ -2,6 +2,7 @@ package api import ( "github.com/hashicorp/serf/coordinate" + "net/url" ) // CoordinateEntry represents a node and its associated network coordinate. @@ -96,7 +97,7 @@ func (c *Coordinate) Update(coord *CoordinateEntry, q *WriteOptions) (*WriteMeta // Node is used to return the coordinates of a single node in the LAN pool. func (c *Coordinate) Node(node string, q *QueryOptions) ([]*CoordinateEntry, *QueryMeta, error) { - r := c.c.newRequest("GET", "/v1/coordinate/node/"+node) + r := c.c.newRequest("GET", "/v1/coordinate/node/"+url.PathEscape(node)) r.setQueryOptions(q) rtt, resp, err := c.c.doRequest(r) if err != nil { diff --git a/api/discovery_chain.go b/api/discovery_chain.go index 29bda85912..10150f5de8 100644 --- a/api/discovery_chain.go +++ b/api/discovery_chain.go @@ -3,6 +3,7 @@ package api import ( "encoding/json" "fmt" + "net/url" "time" ) @@ -26,7 +27,7 @@ func (d *DiscoveryChain) Get(name string, opts *DiscoveryChainOptions, q *QueryO method = "POST" } - r := d.c.newRequest(method, fmt.Sprintf("/v1/discovery-chain/%s", name)) + r := d.c.newRequest(method, fmt.Sprintf("/v1/discovery-chain/%s", url.PathEscape(name))) r.setQueryOptions(q) if opts != nil {