provider.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package utilization
  2. import (
  3. "fmt"
  4. "strings"
  5. "time"
  6. )
  7. // Helper constants, functions, and types common to multiple providers are
  8. // contained in this file.
  9. // Constants from the spec.
  10. const (
  11. maxFieldValueSize = 255 // The maximum value size, in bytes.
  12. providerTimeout = 1 * time.Second // The maximum time a HTTP provider may block.
  13. )
  14. type validationError struct{ e error }
  15. func (a validationError) Error() string {
  16. return a.e.Error()
  17. }
  18. func isValidationError(e error) bool {
  19. _, is := e.(validationError)
  20. return is
  21. }
  22. // This function normalises string values per the utilization spec.
  23. func normalizeValue(s string) (string, error) {
  24. out := strings.TrimSpace(s)
  25. bytes := []byte(out)
  26. if len(bytes) > maxFieldValueSize {
  27. return "", validationError{fmt.Errorf("response is too long: got %d; expected <=%d", len(bytes), maxFieldValueSize)}
  28. }
  29. for i, r := range out {
  30. if !isAcceptableRune(r) {
  31. return "", validationError{fmt.Errorf("bad character %x at position %d in response", r, i)}
  32. }
  33. }
  34. return out, nil
  35. }
  36. func isAcceptableRune(r rune) bool {
  37. switch r {
  38. case 0xFFFD:
  39. return false // invalid UTF-8
  40. case '_', ' ', '/', '.', '-':
  41. return true
  42. default:
  43. return r > 0x7f || // still allows some invalid UTF-8, but that's the spec.
  44. ('0' <= r && r <= '9') ||
  45. ('a' <= r && r <= 'z') ||
  46. ('A' <= r && r <= 'Z')
  47. }
  48. }