Since most of PL/pgSQL functions accept a `uuid` domain, we get an error if the value is not valid, forcing us to return an HTTP 500, as we can not detect that the error was due to that. Instead, i now validate that the slug is indeed a valid UUID before attempting to send it to the database, returning the correct HTTP error code and avoiding useless calls to the database. I based the validation function of Parse() from Google’s uuid package[0] because this function is an order or magnitude faster in benchmarks: goos: linux goarch: amd64 pkg: dev.tandem.ws/tandem/numerus/pkg cpu: Intel(R) Core(TM) i5-6200U CPU @ 2.30GHz BenchmarkValidUuid-4 36946050 29.37 ns/op BenchmarkValidUuid_Re-4 3633169 306.70 ns/op The regular expression used for the benchmark was: var re = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$") And the input parameter for both functions was the following valid UUID, because most of the time the passed UUID will be valid: "f47ac10b-58cc-0372-8567-0e02b2c3d479" I did not use the uuid package, even though it is in Debian’s repository, because i only need to check whether the value is valid, not convert it to a byte array. As far as i know, that package can not do that. [0]: https://github.com/google/uuid
47 lines
1.8 KiB
Go
47 lines
1.8 KiB
Go
package pkg
|
|
|
|
func ValidUuid(s string) bool {
|
|
if len(s) != 36 {
|
|
return false
|
|
}
|
|
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
|
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
|
|
return false
|
|
}
|
|
for _, x := range [16]int{
|
|
0, 2, 4, 6,
|
|
9, 11,
|
|
14, 16,
|
|
19, 21,
|
|
24, 26, 28, 30, 32, 34} {
|
|
if !validHex(s[x], s[x+1]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// xvalues returns the value of a byte as a hexadecimal digit or 255.
|
|
var xvalues = [256]byte{
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
|
|
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
}
|
|
|
|
func validHex(x1, x2 byte) bool {
|
|
return xvalues[x1] != 255 && xvalues[x2] != 255
|
|
}
|