Skip to content

Commit

Permalink
Fix issues with serialising x-www-form-urlencoded data (#304)
Browse files Browse the repository at this point in the history
* fix broken x-www-form-urlencoded serialisation

* fix backends to use string instead of slice for ssl_ciphers field

* add a note/todo related to the change

* update description
  • Loading branch information
Integralist authored Sep 21, 2021
1 parent 7aca3ab commit c05acd7
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 116 deletions.
6 changes: 3 additions & 3 deletions fastly/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Backend struct {
SSLSNIHostname string `mapstructure:"ssl_sni_hostname"`
MinTLSVersion string `mapstructure:"min_tls_version"`
MaxTLSVersion string `mapstructure:"max_tls_version"`
SSLCiphers []string `mapstructure:"ssl_ciphers"`
SSLCiphers string `mapstructure:"ssl_ciphers"`
CreatedAt *time.Time `mapstructure:"created_at"`
UpdatedAt *time.Time `mapstructure:"updated_at"`
DeletedAt *time.Time `mapstructure:"deleted_at"`
Expand Down Expand Up @@ -124,7 +124,7 @@ type CreateBackendInput struct {
SSLSNIHostname string `form:"ssl_sni_hostname,omitempty"`
MinTLSVersion string `form:"min_tls_version,omitempty"`
MaxTLSVersion string `form:"max_tls_version,omitempty"`
SSLCiphers []string `form:"ssl_ciphers,omitempty"`
SSLCiphers string `form:"ssl_ciphers,omitempty"`
}

// CreateBackend creates a new Fastly backend.
Expand Down Expand Up @@ -225,7 +225,7 @@ type UpdateBackendInput struct {
SSLSNIHostname *string `form:"ssl_sni_hostname,omitempty"`
MinTLSVersion *string `form:"min_tls_version,omitempty"`
MaxTLSVersion *string `form:"max_tls_version,omitempty"`
SSLCiphers []string `form:"ssl_ciphers,omitempty"`
SSLCiphers string `form:"ssl_ciphers,omitempty"`
}

// UpdateBackend updates a specific backend.
Expand Down
2 changes: 2 additions & 0 deletions fastly/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestClient_Backends(t *testing.T) {
Port: 1234,
ConnectTimeout: 1500,
OverrideHost: "origin.example.com",
SSLCiphers: "DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384",
})
})
if err != nil {
Expand Down Expand Up @@ -115,6 +116,7 @@ func TestClient_Backends(t *testing.T) {
Name: "test-backend",
NewName: String("new-test-backend"),
OverrideHost: String("www.example.com"),
SSLCiphers: "RC4:!COMPLEMENTOFDEFAULT",
})
})
if err != nil {
Expand Down
24 changes: 23 additions & 1 deletion fastly/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/url"
"os"
"path/filepath"
"regexp"
"runtime"
"strings"
"sync"
Expand Down Expand Up @@ -52,6 +53,17 @@ var ProjectVersion = "3.12.0"
var UserAgent = fmt.Sprintf("FastlyGo/%s (+%s; %s)",
ProjectVersion, ProjectURL, runtime.Version())

// formEncodingArrayPattern is used to match the encoded multi-valued field
// format of |<T> where T is an incrementing index
//
// Example:
// foo|0=A&foo|1=B
//
// NOTE:
// I'm only checking double digits and nothing larger as I don't expect anyone
// to provide over 99 separate values.
var formEncodingArrayPattern = regexp.MustCompile(`%7C\d{1,2}`)

// Client is the main entrypoint to the Fastly golang API library.
type Client struct {
// Address is the address of Fastly's API endpoint.
Expand Down Expand Up @@ -294,7 +306,17 @@ func (c *Client) RequestForm(verb, p string, i interface{}, ro *RequestOptions)
if err := form.NewEncoder(buf).KeepZeros(true).DelimitWith('|').Encode(i); err != nil {
return nil, err
}
body := buf.String()

// NOTE: This is a temporary work-around to the issue of the Fastly API not
// recognising the format used by the github.com/ajg/form package.
//
// TODO: Consider using some form of custom marshal
// (https://github.com/ajg/form#custom-marshaling) or alternatively switch
// out the package for something else that has better support for the more
// traditional serialisation format: foo[]=A&foo[]=B
//
// EXAMPLE: https://play.golang.org/p/Kmf3l54MB73
body := formEncodingArrayPattern.ReplaceAllString(buf.String(), "%5B%5D") // %5B%5D == []

ro.Body = strings.NewReader(body)
ro.BodyLength = int64(len(body))
Expand Down
36 changes: 18 additions & 18 deletions fastly/fixtures/backends/cleanup.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend/test-backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend/test-backend
method: DELETE
response:
body: '{"msg":"Record not found","detail":"Couldn''t find Backend ''{ deleted
=\u003e 0000-00-00 00:00:00, name =\u003e test-backend, service =\u003e 7i6HN3TK9wS159v2gPAZ8A,
version =\u003e 20 }''"}'
version =\u003e 32 }''"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:53 GMT
- Mon, 20 Sep 2021 12:34:31 GMT
Fastly-Ratelimit-Remaining:
- "917"
- "4973"
Fastly-Ratelimit-Reset:
- "1610622000"
- "1632142800"
Status:
- 404 Not Found
Strict-Transport-Security:
Expand All @@ -39,9 +39,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9035-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9035-CONTROL-SLWDC, cache-man4148-MAN
X-Timer:
- S1610619953.007977,VS0,VE193
- S1632141271.970511,VS0,VE175
status: 404 Not Found
code: 404
duration: ""
Expand All @@ -50,26 +50,26 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend/new-test-backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend/new-test-backend
method: DELETE
response:
body: '{"msg":"Record not found","detail":"Couldn''t find Backend ''{ deleted
=\u003e 0000-00-00 00:00:00, name =\u003e new-test-backend, service =\u003e
7i6HN3TK9wS159v2gPAZ8A, version =\u003e 20 }''"}'
7i6HN3TK9wS159v2gPAZ8A, version =\u003e 32 }''"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:53 GMT
- Mon, 20 Sep 2021 12:34:31 GMT
Fastly-Ratelimit-Remaining:
- "916"
- "4972"
Fastly-Ratelimit-Reset:
- "1610622000"
- "1632142800"
Status:
- 404 Not Found
Strict-Transport-Security:
Expand All @@ -83,9 +83,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4148-MAN
X-Timer:
- S1610619953.247038,VS0,VE184
- S1632141271.166720,VS0,VE157
status: 404 Not Found
code: 404
duration: ""
26 changes: 15 additions & 11 deletions fastly/fixtures/backends/create.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
version: 1
interactions:
- request:
body: ServiceID=7i6HN3TK9wS159v2gPAZ8A&ServiceVersion=20&address=integ-test.go-fastly.com&connect_timeout=1500&name=test-backend&override_host=origin.example.com&port=1234
body: ServiceID=7i6HN3TK9wS159v2gPAZ8A&ServiceVersion=32&address=integ-test.go-fastly.com&connect_timeout=1500&name=test-backend&override_host=origin.example.com&port=1234&ssl_check_cert=0&ssl_ciphers=DHE-RSA-AES256-SHA%3ADHE-RSA-CAMELLIA256-SHA%3AAES256-GCM-SHA384
form:
ServiceID:
- 7i6HN3TK9wS159v2gPAZ8A
ServiceVersion:
- "20"
- "32"
address:
- integ-test.go-fastly.com
connect_timeout:
Expand All @@ -18,28 +18,32 @@ interactions:
- origin.example.com
port:
- "1234"
ssl_check_cert:
- "0"
ssl_ciphers:
- DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384
headers:
Content-Type:
- application/x-www-form-urlencoded
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend
method: POST
response:
body: '{"address":"integ-test.go-fastly.com","connect_timeout":1500,"name":"test-backend","override_host":"origin.example.com","port":1234,"service_id":"7i6HN3TK9wS159v2gPAZ8A","version":20,"max_tls_version":null,"hostname":"integ-test.go-fastly.com","client_cert":null,"ssl_ca_cert":null,"error_threshold":0,"ssl_client_cert":null,"deleted_at":null,"shield":null,"max_conn":200,"ssl_cert_hostname":null,"use_ssl":false,"first_byte_timeout":15000,"ipv6":null,"ssl_ciphers":null,"comment":"","ssl_sni_hostname":null,"ssl_client_key":null,"request_condition":"","ssl_check_cert":true,"weight":100,"healthcheck":null,"auto_loadbalance":false,"updated_at":"2021-01-14T10:25:50Z","created_at":"2021-01-14T10:25:50Z","ipv4":null,"min_tls_version":null,"between_bytes_timeout":10000,"ssl_hostname":null}'
body: '{"address":"integ-test.go-fastly.com","connect_timeout":1500,"name":"test-backend","override_host":"origin.example.com","port":1234,"ssl_check_cert":false,"ssl_ciphers":"DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384","service_id":"7i6HN3TK9wS159v2gPAZ8A","version":32,"request_condition":"","use_ssl":false,"ssl_cert_hostname":null,"hostname":"integ-test.go-fastly.com","auto_loadbalance":false,"weight":100,"created_at":"2021-09-20T12:34:29Z","ipv4":null,"shield":null,"comment":"","min_tls_version":null,"ssl_sni_hostname":null,"first_byte_timeout":15000,"client_cert":null,"max_conn":200,"max_tls_version":null,"ssl_client_key":null,"ssl_ca_cert":null,"ipv6":null,"updated_at":"2021-09-20T12:34:29Z","between_bytes_timeout":10000,"healthcheck":null,"ssl_client_cert":null,"error_threshold":0,"ssl_hostname":null,"deleted_at":null}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:50 GMT
- Mon, 20 Sep 2021 12:34:29 GMT
Fastly-Ratelimit-Remaining:
- "923"
- "4976"
Fastly-Ratelimit-Reset:
- "1610622000"
- "1632142800"
Status:
- 200 OK
Strict-Transport-Security:
Expand All @@ -53,9 +57,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9037-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9037-CONTROL-SLWDC, cache-man4148-MAN
X-Timer:
- S1610619950.359768,VS0,VE545
- S1632141270.622348,VS0,VE222
status: 200 OK
code: 200
duration: ""
16 changes: 8 additions & 8 deletions fastly/fixtures/backends/delete.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend/new-test-backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend/new-test-backend
method: DELETE
response:
body: '{"status":"ok"}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:52 GMT
- Mon, 20 Sep 2021 12:34:30 GMT
Fastly-Ratelimit-Remaining:
- "918"
- "4974"
Fastly-Ratelimit-Reset:
- "1610622000"
- "1632142800"
Status:
- 200 OK
Strict-Transport-Security:
Expand All @@ -37,9 +37,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9037-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9035-CONTROL-SLWDC, cache-man4148-MAN
X-Timer:
- S1610619953.711130,VS0,VE253
- S1632141271.688140,VS0,VE254
status: 200 OK
code: 200
duration: ""
20 changes: 10 additions & 10 deletions fastly/fixtures/backends/get.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,36 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend/test-backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend/test-backend
method: GET
response:
body: '{"name":"test-backend","service_id":"7i6HN3TK9wS159v2gPAZ8A","address":"integ-test.go-fastly.com","ssl_sni_hostname":null,"between_bytes_timeout":10000,"ssl_client_key":null,"weight":100,"min_tls_version":null,"auto_loadbalance":false,"shield":null,"connect_timeout":1500,"comment":"","port":1234,"ipv4":null,"ssl_client_cert":null,"first_byte_timeout":15000,"ssl_ciphers":null,"deleted_at":null,"request_condition":"","max_conn":200,"ssl_cert_hostname":null,"hostname":"integ-test.go-fastly.com","ssl_check_cert":true,"ipv6":null,"use_ssl":false,"ssl_ca_cert":null,"version":20,"updated_at":"2021-01-14T10:25:50Z","override_host":"origin.example.com","created_at":"2021-01-14T10:25:50Z","error_threshold":0,"max_tls_version":null,"healthcheck":null,"ssl_hostname":null,"client_cert":null}'
body: '{"ipv4":null,"auto_loadbalance":false,"between_bytes_timeout":10000,"connect_timeout":1500,"name":"test-backend","ipv6":null,"address":"integ-test.go-fastly.com","request_condition":"","updated_at":"2021-09-20T12:34:29Z","service_id":"7i6HN3TK9wS159v2gPAZ8A","comment":"","error_threshold":0,"version":32,"ssl_client_key":null,"weight":100,"max_conn":200,"ssl_client_cert":null,"ssl_check_cert":false,"port":1234,"ssl_cert_hostname":null,"ssl_ca_cert":null,"max_tls_version":null,"shield":null,"healthcheck":null,"ssl_sni_hostname":null,"ssl_ciphers":"DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384","override_host":"origin.example.com","client_cert":null,"created_at":"2021-09-20T12:34:29Z","deleted_at":null,"use_ssl":false,"ssl_hostname":null,"hostname":"integ-test.go-fastly.com","min_tls_version":null,"first_byte_timeout":15000}'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store, s-maxage=0
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:51 GMT
- Mon, 20 Sep 2021 12:34:30 GMT
Status:
- 200 OK
Strict-Transport-Security:
- max-age=31536000
Vary:
- Accept-Encoding
Via:
- 1.1 varnish, 1.1 varnish
- 1.1 varnish, 1.1 varnish, 1.1 varnish
X-Cache:
- MISS, MISS
- MISS, MISS, MISS
X-Cache-Hits:
- 0, 0
- 0, 0, 0
X-Served-By:
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4148-MAN, cache-man4148-MAN
X-Timer:
- S1610619951.458633,VS0,VE468
- S1632141270.062465,VS0,VE346
status: 200 OK
code: 200
duration: ""
14 changes: 7 additions & 7 deletions fastly/fixtures/backends/list.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ interactions:
form: {}
headers:
User-Agent:
- FastlyGo/2.1.0 (+github.com/fastly/go-fastly; go1.15.4)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/20/backend
- FastlyGo/3.12.0 (+github.com/fastly/go-fastly; go1.17)
url: https://api.fastly.com/service/7i6HN3TK9wS159v2gPAZ8A/version/32/backend
method: GET
response:
body: '[{"use_ssl":false,"weight":100,"ssl_ciphers":null,"port":1234,"connect_timeout":1500,"ssl_ca_cert":null,"created_at":"2021-01-14T10:25:50Z","ipv6":null,"ssl_client_cert":null,"comment":"","address":"integ-test.go-fastly.com","client_cert":null,"deleted_at":null,"max_conn":200,"override_host":"origin.example.com","ssl_check_cert":true,"auto_loadbalance":false,"ssl_hostname":null,"error_threshold":0,"hostname":"integ-test.go-fastly.com","name":"test-backend","updated_at":"2021-01-14T10:25:50Z","between_bytes_timeout":10000,"first_byte_timeout":15000,"request_condition":"","healthcheck":null,"ssl_client_key":null,"max_tls_version":null,"ssl_cert_hostname":null,"ssl_sni_hostname":null,"version":20,"shield":null,"min_tls_version":null,"ipv4":null,"service_id":"7i6HN3TK9wS159v2gPAZ8A"}]'
body: '[{"use_ssl":false,"port":1234,"first_byte_timeout":15000,"error_threshold":0,"ssl_cert_hostname":null,"ssl_ciphers":"DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:AES256-GCM-SHA384","request_condition":"","comment":"","client_cert":null,"ssl_client_cert":null,"healthcheck":null,"override_host":"origin.example.com","ssl_check_cert":false,"ipv4":null,"address":"integ-test.go-fastly.com","service_id":"7i6HN3TK9wS159v2gPAZ8A","ssl_ca_cert":null,"ipv6":null,"created_at":"2021-09-20T12:34:29Z","ssl_sni_hostname":null,"auto_loadbalance":false,"min_tls_version":null,"hostname":"integ-test.go-fastly.com","between_bytes_timeout":10000,"name":"test-backend","connect_timeout":1500,"version":32,"ssl_client_key":null,"updated_at":"2021-09-20T12:34:29Z","ssl_hostname":null,"deleted_at":null,"weight":100,"max_tls_version":null,"shield":null,"max_conn":200}]'
headers:
Accept-Ranges:
- bytes
Cache-Control:
- no-cache
- no-store
Content-Type:
- application/json
Date:
- Thu, 14 Jan 2021 10:25:51 GMT
- Mon, 20 Sep 2021 12:34:30 GMT
Status:
- 200 OK
Strict-Transport-Security:
Expand All @@ -33,9 +33,9 @@ interactions:
X-Cache-Hits:
- 0, 0
X-Served-By:
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4144-MAN
- cache-control-slwdc9036-CONTROL-SLWDC, cache-man4148-MAN
X-Timer:
- S1610619951.946600,VS0,VE467
- S1632141270.868788,VS0,VE168
status: 200 OK
code: 200
duration: ""
Loading

0 comments on commit c05acd7

Please sign in to comment.