Traffic Server HTTP Header System

No Null-Terminated Strings

It’s not safe to assume that string data contained in marshal buffers (such as URLs and MIME fields) is stored in null-terminated string copies. Therefore, your plugins should always use the length parameter when retrieving or manipulating these strings. You cannot pass in NULL for string-length return values; string values returned from marshall buffers are not null-terminated. If you need a null-terminated value, then use TSstrndup to automatically null-terminate a string. The strings that come back and are not null-terminated cannot be passed into the common str*() routines

Note

Values returned from a marshall buffer can be NULL, which means the field or object requested does not exist.

For example (from the blacklist_1 sample)

  1. char *host_string;
  2. int host_length;
  3. host_string = TSUrlHostGet (bufp, url_loc, &host_length);
  4. for (i = 0; i < nsites; i++) {
  5. if (strncmp (host_string, sites[i], host_length) == 0) {
  6. // ...
  7. }

See the sample plugins for additional examples.

Duplicate MIME Fields Are Not Coalesced

MIME headers can contain more than one MIME field with the same name. Earlier versions of Traffic Server joined multiple fields with the same name into one field with composite values. This behavior came at a performance cost and caused interoperability problems with older clients and servers. Therefore, this version of Traffic Server does not coalesce duplicate fields.

Properly-behaving plugins should check for the presence of duplicate fields and then iterate over the duplicate fields via TSMimeHdrFieldNextDup().

MIME Fields Always Belong to an Associated MIME Header

When using Traffic Server, you cannot create a new MIME field without an associated MIME header or HTTP header; MIME fields are always seen as part of a MIME header or HTTP header.

To use a MIME field, you must specify the MIME header or HTTP header to which it belongs - this is called the field’s parent header. The TSMimeField* functions in older versions of the SDK have been deprecated, as they do not require the parent header as inputs. The current version of Traffic Server uses new functions, the ``TSMimeHdrField`` series, which require you to specify the location of the parent header along with the location of the MIME field. For every deprecated ``TSMimeField`` function, there is a new, preferred TSMimeHdrField* function. Therefore, you should use the ``TSMimeHdrField`` functions instead of the deprecated ``TSMimeField`` series. Examples are provided below.

Instead of:

  1. TSMLoc TSMimeFieldCreate (TSMBuffer bufp)

You should use:

  1. TSMLoc TSMimeHdrFieldCreate (TSMBuffer bufp, TSMLoc hdr)

Instead of:

  1. void TSMimeFieldCopyValues (TSMBuffer dest_bufp, TSMLoc dest_offset,
  2. TSMBuffer src_bufp, TSMLoc src_offset)

You should use:

  1. void TSMimeHdrFieldCopyValues (TSMBuffer dest_bufp, TSMLoc dest_hdr,
  2. TSMLoc dest_field, TSMBuffer src_bufp, TSMLoc src_hdr, TSMLoc
  3. src_field)

In the TSMimeHdrField* function prototypes, the TSMLoc field corresponds to the TSMLoc offset used the deprecated TSMimeField* functions (see the discussion of parent TSMLoc in the following section).

Release Marshal Buffer Handles

When you fetch a component object or create a new object, you get back a handle to the object location. The handle is either an TSMLoc for an object location or char * for a string location. You can manipulate the object through these handles, but when you are finished you need to release the handle to free up system resources.

The general guideline is to release all TSMLoc and string handles you retrieve. The one exception is the string returned by TSUrlStringGet, which must be freed by a call to TSfree.

The handle release functions expect three arguments: the marshal buffer containing the data, the location of the parent object, and the location of the object to be released. The parent location is usually clear from the creation of the TSMLoc or string. For example, if your plugin had the following calls:

  1. url_loc = TSHttpHdrUrlGet (bufp, hdr_loc);
  2. host_string = TSUrlHostGet (bufp, url_loc, &host_length);

then your plugin would have to call:

  1. TSHandleMLocRelease (bufp, hdr_loc, url_loc);

If an TSMLoc is obtained from a transaction, then it does not have a parent TSMLoc. Use the null TSMLoc constant TS_NULL_MLOC as its parent. For example, if your plugin calls:

  1. TSHttpTxnClientReqGet (txnp, &bufp, &hdr_loc);

then you must release hdr_loc with:

  1. TSHandleMLocRelease (bufp, TS_NULL_MLOC, hdr_loc);

You need to use TS_NULL_MLOC to release any TSMLoc handles retrieved by the TSHttpTxn*Get functions.

Here’s an example using a new TSMimeHdrField function:

  1. TSHttpTxnServerRespGet( txnp, &resp_bufp, &resp_hdr_loc );
  2. new_field_loc = TSMimeHdrFieldCreate (resp_bufp, resp_hdr_loc);
  3. TSHandleMLocRelease ( resp_bufp, resp_hdr_loc, new_field_loc);
  4. TSHandleMLocRelease ( resp_bufp, TS_NULL_MLOC, resp_hdr_loc);

See the sample plugins for many more examples.

Tip

You should release handles before reenabling the HTTP transaction. In other words, call TSHandleMLocRelease before TSHttpTxnReenable.