Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the maximum length of Azure blob metadata values?

What is the maximum size for the values in Windows Azure blob metadata?

I can see that the web server will impose a practical upper limit of about 4k.

like image 219
Oliver Bock Avatar asked Dec 11 '13 05:12

Oliver Bock


1 Answers

Max. metadata size is 8K as per the documentation here: https://learn.microsoft.com/en-us/rest/api/storageservices/Setting-and-Retrieving-Properties-and-Metadata-for-Blob-Resources

  • Metadata names must adhere to the naming rules for C# identifiers.
  • Names are case-insensitive but are case-insensitive when set or read.
  • If two or more metadata headers with the same name are submitted for a resource, the Blob service returns status code 400 (Bad Request).
  • The metadata consists of name/value pairs.
  • The total size of all metadata pairs can be up to 8KB in size.
  • Metadata name/value pairs are valid HTTP headers, and so they adhere to all restrictions governing HTTP headers.

Additionally:

  • As Metadata Names must be valid C# identifiers - though there isn't a formal length limit on identifiers in C#, versions of Visual C# prior to Visual Studio 2015 would complain if an identifier exceeded 511 characters in length.
  • There is no formal or defined limit to the length of HTTP header names nor HTTP header values - though many web-servers will block requests that have a total header size exceeding 16KB, or even 8KB in some cases.
  • Each blob metadata entry is represented by its own separate HTTP header with a name prefix of the form x-ms-meta-{yourMetadataName}, so that's 10 characters added for each metadata name.

Here's a client-side validation check you could use:

static void ValidateMetadata( IEnumerable< KeyValuePair<String,String> > blobMetadata )
{
    const int AZURE_MD_NAME_PREFIX_LENGTH = 10; // "x-ms-meta-"

    Int32 totalLength = 0;
    foreach( KeyValuePair<String,String> md in blobMetadata )
    {
        totalLength += AZURE_MD_NAME_PREFIX_LENGTH + md.Key.Length + m.Value.Length;
        
        if( !IsValidMetadataName( md.Key ) )
        {
            throw new ArgumentException( message: "Metadata name \"" + md.Key + "\" is invalid." );
        }
    
        if( md.Value.Any( c => !IsValidHttpHeaderValueChar( c ) ) || md.Value.Contains("\r\n") )
        {
            throw new ArgumentException( message: "Metadata value \"" + md.Value + "\" is invalid." );
        }
    }

    if( totalLength > 8192 )
    {
         throw new ArgumentException( message: "Total length of metadata names and values " + totalLength +" exceeds 8KiB limit." );
    }
}

private static Boolean IsValidMetadataName( String name )
{
    // https://stackoverflow.com/questions/47687379/what-characters-are-allowed-in-http-header-values

    if( String.IsNullOrWhiteSpace( name ) ) return false;

    // The intersection of valid HTTP Header Names and C# Identifiers means:
    // * First character must be a letter.
    // * All other characters must be ASCII letters or digits.
    // * Underscores are technically legal, but many HTTP systems reject them: https://stackoverflow.com/questions/22856136/why-http-servers-forbid-underscores-in-http-header-names - this method disallows underscores to be safe, though in practice it will probably work fine.

    if( !Char.IsLetter( name[0] ) ) return false;
    
    foreach( Char c in name )
    {
        bool validChar = Char.IsLetterOrDigit( c ) && c < 127;
        if( !validChar ) return false;
    }

    return true;
}

private static Boolean IsValidHttpHeaderChar( Char c )
{
    // Technically a quoted-string can contain almost any character ("quoted-string" in the HTTP spec), but it's unclear if Azure Blob storage supports that or not.

    bool isCtl  = ( 0 <= c && c <= 31 ) || ( c == 127 );
    if( isCtl ) return false;
    return true; // This method checks individual chars, so it cannot check for \r\n.
}
like image 195
Jits Avatar answered Nov 14 '22 20:11

Jits