package main

import (
	"crypto"
	"crypto/rand"
	"fmt"
	"net/http"
	"strings"
	"time"
)

type Signer struct {
	key   crypto.Signer
	keyID string
}

// Sign modifies the request, computing and setting the Signature header, and setting the Date header to the provided time.
func (s Signer) Sign(r *http.Request, date time.Time) error {
	host := r.URL.Host
	path := r.URL.Path
	method := strings.ToLower(r.Method)
	stringToSign := fmt.Sprintf("(request-target): %s %s\nhost: %s\ndate: %s", method, path, host, date.Format(time.RFC1123))
	sig, err := s.key.Sign(rand.Reader, []byte(stringToSign), nil)
	if err != nil {
		return err
	}
	r.Header.Set("Date", date.Format(time.RFC1123))
	r.Header.Set("Signature", fmt.Sprintf(`keyId="%s",headers="(request-target) host date",signature="%s"`, s.keyID, sig))
	return nil
}
