parseDataURI parses a data URI of the form "data: ;base64, ". Returns the MIME type and decoded bytes.
(uri string)
| 228 | // parseDataURI parses a data URI of the form "data:<mime>;base64,<payload>". |
| 229 | // Returns the MIME type and decoded bytes. |
| 230 | func parseDataURI(uri string) (mimeType string, data []byte, err error) { |
| 231 | rest, ok := strings.CutPrefix(uri, "data:") |
| 232 | if !ok { |
| 233 | return "", nil, errors.New("not a data URI") |
| 234 | } |
| 235 | |
| 236 | header, payload, ok := strings.Cut(rest, ",") |
| 237 | if !ok { |
| 238 | return "", nil, errors.New("data URI missing comma separator") |
| 239 | } |
| 240 | |
| 241 | // Header is "<mime>[;charset=…];base64" or "<mime>" (plain text, unsupported here). |
| 242 | if !strings.HasSuffix(header, ";base64") { |
| 243 | return "", nil, errors.New("data URI is not base64-encoded (only base64 data URIs are supported)") |
| 244 | } |
| 245 | mimeType = strings.TrimSuffix(header, ";base64") |
| 246 | |
| 247 | // Strip any charset parameter (e.g. "image/png;charset=utf-8;base64" → "image/png"). |
| 248 | if idx := strings.Index(mimeType, ";"); idx >= 0 { |
| 249 | mimeType = mimeType[:idx] |
| 250 | } |
| 251 | mimeType = strings.TrimSpace(mimeType) |
| 252 | if mimeType == "" { |
| 253 | mimeType = "application/octet-stream" |
| 254 | } |
| 255 | |
| 256 | data, err = base64.StdEncoding.DecodeString(payload) |
| 257 | if err != nil { |
| 258 | return "", nil, fmt.Errorf("base64 decode: %w", err) |
| 259 | } |
| 260 | return mimeType, data, nil |
| 261 | } |
no test coverage detected