// https://developer.fastly.com/solutions/examples/normalize-requests
package main
import (
"context"
"fmt"
"io"
"net/url"
"strings"
"github.com/fastly/compute-sdk-go/fsthttp"
)
// BackendName is the name of our service backend.
const BackendName = "origin_0"
func main() {
fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {
// This requires your service to be configured with a backend
// named "origin_0" and pointing to "https://http-me.glitch.me".
// Filter query strings to only include query
// parameters that are valid for your site
qs := r.URL.Query()
// Query strings parameters to keep.
keep := []string{"query", "page", "foo"}
qs = FilterExcept(qs, keep)
// Lowercase specific query string values.
qs.Set("query", strings.ToLower(qs.Get("query")))
// Encode() encodes the query string parameters into URL encoded form.
// And sorts them in alphabetical order.
r.URL.RawQuery = qs.Encode()
// Remove headers that you want to avoid using to vary responses.
r.Header.Del("user-agent")
r.Header.Del("cookie")
// Normalize headers that you may vary on.
// Normalize the Accept-Language header.
LangAccept := []string{"en", "de", "fr", "nl"}
LangDefault := "de"
LangNorm := NormAccept(r.Header.Get("accept-language"), LangAccept, LangDefault)
r.Header.Set("accept-language", LangNorm)
resp, err := r.Send(ctx, BackendName)
if err != nil {
w.WriteHeader(fsthttp.StatusBadGateway)
fmt.Fprintln(w, err.Error())
return
}
w.Header().Reset(resp.Header)
w.WriteHeader(resp.StatusCode)
io.Copy(w, resp.Body)
})
}
// filterExcept() function takes in all query string parameters and a list
// of parameters to keep and returns only a map of parameters to keep.
func FilterExcept(q url.Values, f []string) url.Values {
new := make(url.Values)
for _, val := range f {
for key, element := range q {
if key == val {
new[key] = element
}
}
}
return new
}
// headerAccept() function checks the input against a list of accepted values
// and returns a value in the list or the default value if no match is found.
// Disclaimer: This function is only a simple demonstration on how the accept
// header can be normalized. For production usage please use a dedicated package.
func NormAccept(input string, accept []string, def string) string {
f := 0
var result string
for _, val := range accept {
if strings.Contains(input, val) {
f = 1
result = val
break
}
}
if f == 1 {
return result
} else {
return def
}
}