| 159 | } |
| 160 | |
| 161 | func normalizeScheme(s string) (string, error) { |
| 162 | // https://tools.ietf.org/html/rfc3986#section-3.1 |
| 163 | s = strings.ToLower(s) |
| 164 | if first := s[0]; 'a' > first || 'z' < first { |
| 165 | return "", errors.New("must start with a letter") |
| 166 | } |
| 167 | for i := 1; i < len(s); i++ { // iterate over bytes, not runes |
| 168 | c := s[i] |
| 169 | switch { |
| 170 | case 'a' <= c && c <= 'z': |
| 171 | continue |
| 172 | case '0' <= c && c <= '9': |
| 173 | continue |
| 174 | case c == '.' || c == '+' || c == '-': |
| 175 | continue |
| 176 | } |
| 177 | return "", fmt.Errorf("may not contain %q", c) |
| 178 | } |
| 179 | return s, nil |
| 180 | } |