gophercloud icon indicating copy to clipboard operation
gophercloud copied to clipboard

Container object custom metadata

Open pierreprinetti opened this issue 2 years ago • 1 comments

Objects in the Swift API can have arbitrary metadata attached.

However, the function in charge of parsing the metadata of a container object doesn't parse them.

Container object properties are returned in headers starting with X-Container-Meta-<name> where <name> is the name of the metadata item.


Note to the implementer: given that properties are passed as HTTP headers, they are subject to the rules of the HTTP headers. Besides being case-insensitive, header field parameters cannot carry characters outside the ISO-8859-1 character set by default.

pierreprinetti avatar Sep 08 '23 10:09 pierreprinetti

Hello,

I have this issue (I almost created a solution xD). But, it's true that Swift APIs can have arbitrary metadata, and these metadata are labeled by X-Object-Meta- and not X-Container-Meta-.

The functionality to handle such data is already implemented at openstack/objectstorage/v1/objects/results.go#L284

For containers, there is no such metadata as per the documentation: Object Storage API - Containers..

Regarding the issue of having characters in object names that could violate the ISO-8859-1 or the None ASCII in headers rule, this is already implemented in Openstack, refere to this example:

[stack@undercloud (overcloudrc) ~]$ openstack object set aldokimi-test file.txt --property "Filename=Ä-Fílë.txt"
Cannot set property Filename to non-ascii value
2025-11-08 01:06:33,742 ERROR [object_store_v1.py:586] Cannot set property Filename to non-ascii value

But, if you use the swift API directly to create metadata for an object, it will allow you to add any characters you want, so I propose to add a function to the HTTP wrapper, this function will replace ISO-8859-1/UTF-8 non-printable characters with '?', refer to the code bellow:

func FilterHTTPHeader(value string) string {
	var builder strings.Builder
	builder.Grow(len(value))

	for _, r := range value {
		if r == '\t' || (r >= 32 && r <= unicode.MaxASCII) {
			builder.WriteRune(r)
		} else {
			builder.WriteRune('?')
		}
	}
	return builder.String()
}

If the idea is approved, I will create a PR and post it,

Thanks,

aldokimi avatar Nov 08 '25 01:11 aldokimi