terraform/builtin/providers/http/data_source.go

105 lines
2.2 KiB
Go

package http
import (
"fmt"
"io/ioutil"
"net/http"
"regexp"
"time"
"github.com/hashicorp/terraform/helper/schema"
)
func dataSource() *schema.Resource {
return &schema.Resource{
Read: dataSourceRead,
Schema: map[string]*schema.Schema{
"url": &schema.Schema{
Type: schema.TypeString,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"request_headers": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"body": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}
func dataSourceRead(d *schema.ResourceData, meta interface{}) error {
url := d.Get("url").(string)
headers := d.Get("request_headers").(map[string]interface{})
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return fmt.Errorf("Error creating request: %s", err)
}
for name, value := range headers {
req.Header.Set(name, value.(string))
}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("Error during making a request: %s", url)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return fmt.Errorf("HTTP request error. Response code: %d", resp.StatusCode)
}
contentType := resp.Header.Get("Content-Type")
if contentType == "" || isContentTypeAllowed(contentType) == false {
return fmt.Errorf("Content-Type is not a text type. Got: %s", contentType)
}
bytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("Error while reading response body. %s", err)
}
d.Set("body", string(bytes))
d.SetId(time.Now().UTC().String())
return nil
}
// This is to prevent potential issues w/ binary files
// and generally unprintable characters
// See https://github.com/hashicorp/terraform/pull/3858#issuecomment-156856738
func isContentTypeAllowed(contentType string) bool {
allowedContentTypes := []*regexp.Regexp{
regexp.MustCompile("^text/.+"),
regexp.MustCompile("^application/json$"),
}
for _, r := range allowedContentTypes {
if r.MatchString(contentType) {
return true
}
}
return false
}