Error handling with base64 decoding in Go
Consider this simple base64 snippet:
package main
import (
"fmt"
"encoding/base64"
)
func main() {
const encoded string = "aGVsbG8=" // hello
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
panic(err)
}
fmt.Println(string(decoded))
}
This gives hi as expected. Now if I am deliberately passing in corrupted input like
const encoded string = "XXXXXaGVsbG8="
then I find myself hitting the panic line which gives me:
panic: illegal base64 data at input byte 11
goroutine 1 [running]:
main.main()
/tmp/sandbox422941756/main.go:12 +0x140
Looking at the source code and this issue , it seems like there isn't much here other than matching the string literal and returning a more meaningful message to the caller of the caller:
if err != nil {
if strings.Contains(err.Error(), "illegal base64 data at input byte") {
panic("\nbase64 input is corrupt, check service Key")
}
}
There must be a more elegant way to do this besides string matching. What is the go- reactive way to achieve this?
source to share
Look at the type of error. For example,
package main
import (
"encoding/base64"
"fmt"
)
func main() {
encoded := "XXXXXaGVsbG8=" // corrupt
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
if _, ok := err.(base64.CorruptInputError); ok {
panic("\nbase64 input is corrupt, check service Key")
}
panic(err)
}
fmt.Println(string(decoded))
}
Output:
panic:
base64 input is corrupt, check service Key
source to share
Looking at the implementation (non-ported base64.Encoding.decode()
method), if this method returns an error, it can only be a specific type base64.CorruptInputError
. This type of error always produces the following error line:
func (e CorruptInputError) Error() string {
return "illegal base64 data at input byte " + strconv.FormatInt(int64(e), 10)
}
Thus, apart from some extreme circumstances (for example, memory errors, changed execution code, etc.), if it base64.StdEncoding.DecodeString()
returns an error, the error string always contains a string "illegal base64 data at input byte "
(in the current version).
There is no need to validate your error string, you can handle any returned error not nil
as the input is invalid. And the error string is an implementation detail, so you shouldn't rely on it anyway. The error line is for people, not code. This is how the package is implemented encoding/base64
, you cannot do finer error handling alongside this (and there is usually no need to distinguish between individual error cases in a case Encoding.DecodeString()
).
When a packet gives different error values ββfor different error cases, there are methods to effectively manage them. For more information, check out this question:
Are there standard Err variables?
As mentioned, in the case of a package encoding/base64
, a type value is returned base64.CorruptInputError
, you can use type assertion to check this. See peterSO's answer for this.
source to share