Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 3.2.1 (unreleased)

BUG FIXES

* data-source/http: Using DefaultTransport to reinstate previous behavior (e.g., ProxyFromEnvironment) ([#198](https://github.com/hashicorp/terraform-provider-http/pull/198)).

## 3.2.0 (October 31, 2022)

ENHANCEMENTS:
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/hashicorp/terraform-plugin-framework-validators v0.5.0
github.com/hashicorp/terraform-plugin-go v0.14.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0
golang.org/x/net v0.1.0
)

require (
Expand Down Expand Up @@ -61,9 +62,8 @@ require (
github.com/vmihailenco/tagparser v0.1.2 // indirect
github.com/zclconf/go-cty v1.11.0 // indirect
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d // indirect
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20200711021454-869866162049 // indirect
google.golang.org/grpc v1.48.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0=
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -314,15 +314,15 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
Expand Down
44 changes: 34 additions & 10 deletions internal/provider/data_source_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@ import (
"io/ioutil"
"mime"
"net/http"
"net/url"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-framework-validators/schemavalidator"
"github.com/hashicorp/terraform-plugin-framework/path"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"golang.org/x/net/http/httpproxy"
)

var _ datasource.DataSource = (*httpDataSource)(nil)
Expand Down Expand Up @@ -151,7 +152,7 @@ func (d *httpDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
return
}

url := model.URL.ValueString()
requestURL := model.URL.ValueString()
method := model.Method.ValueString()
requestHeaders := model.RequestHeaders
requestBody := strings.NewReader(model.RequestBody.ValueString())
Expand All @@ -162,12 +163,32 @@ func (d *httpDataSource) Read(ctx context.Context, req datasource.ReadRequest, r

caCertificate := model.CaCertificate

tr := &http.Transport{
TLSClientConfig: &tls.Config{},
tr, ok := http.DefaultTransport.(*http.Transport)
if !ok {
resp.Diagnostics.AddError(
"Error configuring http transport",
"Error http: Can't configure http transport.",
)
return
}

// Prevent issues with multiple data source configurations modifying the shared transport.
clonedTr := tr.Clone()

// Prevent issues with tests caching the proxy configuration.
clonedTr.Proxy = func(req *http.Request) (*url.URL, error) {
return httpproxy.FromEnvironment().ProxyFunc()(req.URL)
}

if clonedTr.TLSClientConfig == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: To further prevent any differences due version to 3.2.0 changes, it is mentioned in the TLSClientConfig documentation that:

// If nil, the default configuration is used.
// If non-nil, HTTP/2 support may not be enabled by default.

I think we may want to consider moving this nil check inside each of the !IsNull() branches below to prevent any sort of further HTTP/2 oddities when there is no custom TLS configuration.

clonedTr.TLSClientConfig = &tls.Config{}
}

if !model.Insecure.IsNull() {
tr.TLSClientConfig.InsecureSkipVerify = model.Insecure.ValueBool()
if clonedTr.TLSClientConfig == nil {
clonedTr.TLSClientConfig = &tls.Config{}
}
clonedTr.TLSClientConfig.InsecureSkipVerify = model.Insecure.ValueBool()
}

// Use `ca_cert_pem` cert pool
Expand All @@ -181,14 +202,17 @@ func (d *httpDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
return
}

tr.TLSClientConfig.RootCAs = caCertPool
if clonedTr.TLSClientConfig == nil {
clonedTr.TLSClientConfig = &tls.Config{}
}
clonedTr.TLSClientConfig.RootCAs = caCertPool
}

client := &http.Client{
Transport: tr,
Transport: clonedTr,
}

request, err := http.NewRequestWithContext(ctx, method, url, requestBody)
request, err := http.NewRequestWithContext(ctx, method, requestURL, requestBody)
if err != nil {
resp.Diagnostics.AddError(
"Error creating request",
Expand Down Expand Up @@ -251,7 +275,7 @@ func (d *httpDataSource) Read(ctx context.Context, req datasource.ReadRequest, r
return
}

model.ID = types.StringValue(url)
model.ID = types.StringValue(requestURL)
model.ResponseHeaders = respHeadersState
model.ResponseBody = types.StringValue(responseBody)
model.Body = types.StringValue(responseBody)
Expand Down
72 changes: 72 additions & 0 deletions internal/provider/data_source_http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"regexp"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestDataSource_200(t *testing.T) {
Expand Down Expand Up @@ -471,6 +474,75 @@ func TestDataSource_UnsupportedInsecureCaCert(t *testing.T) {
})
}

// testProxiedURL is a hardcoded URL used in acceptance testing where it is
// expected that a locally started HTTP proxy will handle the request.
//
// Neither localhost nor the loopback interface (127.0.0.1) can be used for the
// address of the server as httpproxy/proxy.go will ignore these addresses.
//
// References:
// - https://cs.opensource.google/go/x/net/+/internal-branch.go1.19-vendor:http/httpproxy/proxy.go;l=181
// - https://cs.opensource.google/go/x/net/+/internal-branch.go1.19-vendor:http/httpproxy/proxy.go;l=186
const testProxiedURL = "http://terraform-provider-http-test-proxy"

func TestDataSource_HTTPViaProxyWithEnv(t *testing.T) {
proxyRequests := 0
serverRequests := 0

// Content-Type is set to text/plain otherwise the http data source issues a warning which
// causes Terraform 0.14 to not write any data to state.
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
serverRequests++
w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusOK)
}))

defer server.Close()

serverURL, err := url.Parse(server.URL)

if err != nil {
t.Fatalf("error parsing server URL: %s", err)
}

proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
proxyRequests++
httputil.NewSingleHostReverseProxy(serverURL).ServeHTTP(w, r)
}))
defer proxy.Close()

t.Setenv("HTTP_PROXY", proxy.URL)
t.Setenv("HTTPS_PROXY", proxy.URL)

resource.UnitTest(t, resource.TestCase{
ProtoV5ProviderFactories: protoV5ProviderFactories(),

Steps: []resource.TestStep{
{
Config: fmt.Sprintf(`
data "http" "http_test" {
url = "%s"
}
`, testProxiedURL),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.http.http_test", "status_code", "200"),
CheckServerAndProxyRequestCount(&proxyRequests, &serverRequests),
),
},
},
})
}

func CheckServerAndProxyRequestCount(proxyRequestCount, serverRequestCount *int) resource.TestCheckFunc {
return func(_ *terraform.State) error {
if *proxyRequestCount != *serverRequestCount {
return fmt.Errorf("expected proxy and server request count to match: proxy was %d, while server was %d", *proxyRequestCount, *serverRequestCount)
}

return nil
}
}

type TestHttpMock struct {
server *httptest.Server
}
Expand Down