The attachments are missing (even though my sent folder email says the
attachments were part of it). I'm just going to copy-paste the two files
in the email.

 

Example code:

 

void

usingCxxApi(INKHttpTxn txnp) {

  HttpTransaction txn(txnp);

  HttpRequest client_req;

  if (!txn.getClientReq(client_req)) {

    INKError("[%s] Error while retrieving client request",
__FUNCTION__);

    return;

  }

  Url url;

  if (client_req.getUrl(url)) {

    MString query;

    if (url.getQuery(query)) {

      INKDebug(DEBUG_TAG, "[%s] Got query [%.*s]", __FUNCTION__,
query.size(), query.data());

    }

  }

  HttpHeaderFieldIterator field_iter;

  for (client_req.getHeaderFieldIterator(field_iter); field_iter.good();
field_iter.next()) {

    MString name;

    if (field_iter->getName(name) && name.size()) {

      HttpHeaderValueIterator value_iter;

      for (field_iter->getValueIterator(value_iter); value_iter.good();
value_iter.next()) {

        INKDebug(DEBUG_TAG, "[%s] Examining header field [%.*s] with
value [%.*s]",

                 name.size(), name.data(), value_iter->size(),
value_iter->data());

        }

      }

    }

  }

}

 

void

notUsingCxxApi(INKHttpTxn txnp) {

  INKMBuffer req_bufp;

  INKMLoc req_hdr_loc;

  if (INKHttpTxnClientReqGet(txnp, &req_bufp, &req_hdr_loc) == 0) {

    INKError("[%s] Error while retrieving client request",
__FUNCTION__);

    return;

  }

  INKMLoc url_loc = INKHttpHdrUrlGet(req_bufp, req_hdr_loc);

  if (url_loc && (url_loc != INK_ERROR_PTR)) {

    int query_len;

    const char *query = INKUrlHttpQueryGet(req_bufp, url_loc,
&query_len);

    if (query && (query != INK_ERROR_PTR)) {

      INKDebug(DEBUG_TAG, "[%s] Got query [%.*s]", __FUNCTION__,
query._len, query);

      INKHandleStringRelease(req_bufp, url_loc, query);

    }

    INKHandleMLocRelease(req_bufp, req_hdr_loc, url_loc);

  }

  INKMLoc field_loc = INKMimeHdrFieldGet(req_bufp, req_hdr_loc, 0);

  while (field_loc && (field_loc != INK_ERROR_PTR)) {

    INKMLoc next_field_loc;

    const char *name;

    int name_len;

    name = INKMimeHdrFieldNameGet(req_bufp, req_hdr_loc, field_loc,
&name_len);

    if (name && (name != INK_ERROR_PTR)) {

      int n_values;

      n_values = INKMimeHdrFieldValuesCount(req_bufp, req_hdr_loc,
field_loc);

      if (n_values && (n_values != INK_ERROR)) {

        const char *value;

        int value_len;

        for (int i = 0; i < n_values; ++i) {

          if (INKMimeHdrFieldValueStringGet(req_bufp, req_hdr_loc,
field_loc, i,

                                            &value, &value_len) ==
INK_SUCCESS) {

            if (value) {

              INKDebug(DEBUG_TAG, "[%s] Examining header field [%.*s]
with value [%.*s]",

                       name_len, name, value_len, value);

            }

            INKHandleStringRelease(req_bufp, field_loc, value);

          }

        }

      }

      INKHandleStringRelease(req_bufp, field_loc, name);

    }

    next_field_loc = INKMimeHdrFieldNext(req_bufp, req_hdr_loc,
field_loc);

    INKHandleMLocRelease(req_bufp, req_hdr_loc, field_loc);

    field_loc = next_field_loc;

  }

  INKHandleMLocRelease(req_bufp, INK_NULL_MLOC, req_hdr_loc);

}

 

 

 

And the actual wrapper:

 

 

 

 

 

#ifndef _TS_API_CXX_H

 

#define _TS_API_CXX_H

 

#include <boost/noncopyable.hpp>

 

#include "InkAPI.h"

 

namespace Ts {

 

  class MString : boost::noncopyable {

  public:

    MString() : _data(0), _size(0), _type(MLOC_DEPENDENT), _loc(0) { };

    const char *data() const { return _data; }

    int size() const { return _size; }

    operator const char *() const { return _data; };

    void clear() {

      if (_type == MLOC_DEPENDENT) {

        if (_loc) {

          INKHandleStringRelease(_buf, _loc, _data);

          _loc = 0;

        }

      } else {

        if (_data) {

          INKfree(const_cast<char *>(_data));

        }

      }

      _size = 0;

    }

    ~MString() { clear(); }

  private:

    const char *_data;

    int _size;

    enum Type { MLOC_DEPENDENT, HEAP_DEPENDENT };

    Type _type;

    INKMBuffer _buf;

    INKMLoc _loc;

    void _set(INKMBuffer buf, INKMLoc loc) {

      _buf = buf;

      _loc = loc;

      _type = MLOC_DEPENDENT;

    }

    void _set(const char *ptr) {

      _data = ptr;

      _size = _data ? strlen(_data) : 0;

      _type = HEAP_DEPENDENT;

    }

    friend class Url;

    friend class HttpHeaderField;

    friend class HttpHeaderValueIterator;

    friend class HttpRequest;

  };

 

  class HttpHeaderValueIterator : boost::noncopyable {

  public:

    HttpHeaderValueIterator() : _curr_index(-1), _n_values(-1) { };

    bool good() { return (_curr_index < _n_values); };

    void next() {

      _curr_value.clear();

      ++_curr_index;

      if (_curr_index < _n_values) {

        if (INKMimeHdrFieldValueStringGet(_hdr_buf, _hdr_loc,
_field_loc,

                                          _curr_index,
&(_curr_value._data),

                                          &(_curr_value._size)) ==
INK_SUCCESS) {

          _curr_value._set(_hdr_buf, _field_loc);

        } else {

          _curr_index = _n_values = -1;

        }

      }

    }

    MString *operator ->() {

      return &(_curr_value);

    }

    MString &operator *() {

      return _curr_value;

    }

    void clear() {

      _curr_value.clear();

      _curr_index = _n_values = -1;

    }

    ~HttpHeaderValueIterator() { clear(); };

  private:

    INKMBuffer _hdr_buf;

    INKMLoc _hdr_loc;

    INKMLoc _field_loc;

    MString _curr_value;

    int _curr_index;

    int _n_values;

    void _set(INKMBuffer hdr_buf, INKMLoc hdr_loc, INKMLoc field_loc,
int n_values) {

      if (n_values) {

        _hdr_buf = hdr_buf;

        _hdr_loc = hdr_loc;

        _field_loc = field_loc;

        _n_values = n_values;

        next();

      }

    }

    friend class HttpHeaderField;

    friend class HttpMessage;

  };

 

  class HttpHeaderField : boost::noncopyable {

  public:

    HttpHeaderField() : _field_loc(0) { };

    bool getName(MString &name) {

      name.clear();

      if (_field_loc) {

        name._data = INKMimeHdrFieldNameGet(_hdr_buf, _hdr_loc,
_field_loc, &name._size);

        if (name._data && (name._data != INK_ERROR_PTR)) {

          name._set(_hdr_buf, _field_loc);

          return true;

        }

      }

      return false;

    }

    bool getValueIterator(HttpHeaderValueIterator &value_iter) {

      value_iter.clear();

      if (_field_loc) {

        int n_values = INKMimeHdrFieldValuesCount(_hdr_buf, _hdr_loc,
_field_loc);

        if (n_values != INK_ERROR) {

          value_iter._set(_hdr_buf, _hdr_loc, _field_loc, n_values);

          return true;

        }

      }

      return false;

    }

    void clear() {

      if (_field_loc) {

        INKHandleMLocRelease(_hdr_buf, _hdr_loc, _field_loc);

        _field_loc = 0;

      }

    }

    ~HttpHeaderField() { clear(); };

  private:

    INKMBuffer _hdr_buf;

    INKMLoc _hdr_loc;

    INKMLoc _field_loc;

    void _set(INKMBuffer hdr_buf, INKMLoc hdr_loc, INKMLoc field_loc) {

      _hdr_buf = hdr_buf;

      _hdr_loc = hdr_loc;

      _field_loc = field_loc;

    }

    void _set(INKMLoc field_loc) { _field_loc = field_loc; };

    void _destroy() {

      if (_field_loc) {

        INKMimeHdrFieldDestroy(_hdr_buf, _hdr_loc, _field_loc);

        clear();

      }

    }

    friend class HttpHeaderFieldIterator;

  };

 

  class HttpHeaderFieldIterator : boost::noncopyable {

  public:

    HttpHeaderFieldIterator() : _curr_index(-1), _good(false) { };

    bool good() { return _good; };

    void next() {

      if (_good) {

        ++_curr_index;

        _curr_field.clear();

        _field_loc = INKMimeHdrFieldGet(_hdr_buf, _hdr_loc,
_curr_index);

        if (_field_loc && (_field_loc != INK_ERROR_PTR)) {

          _curr_field._set(_field_loc);

        } else {

          _good = false;

        }

      }

    }

    void destroy() {

      if (_good) {

        _curr_field._destroy();

        --_curr_index; // to offset the increment in next()

      }

    }

    HttpHeaderField *operator ->() {

      return &(_curr_field);

    }

    HttpHeaderField &operator *() {

      return _curr_field;

    }

    void clear() {

      _curr_field.clear();

      _good = false;

    }

    ~HttpHeaderFieldIterator() { clear(); }

  private:

    INKMBuffer _hdr_buf;

    INKMLoc _hdr_loc;

    INKMLoc _field_loc;

    HttpHeaderField _curr_field;

    int _curr_index;

    bool _good;

    void _set(INKMBuffer hdr_buf, INKMLoc hdr_loc, INKMLoc field_loc) {

      _hdr_buf = hdr_buf;

      _hdr_loc = hdr_loc;

      _field_loc = field_loc;

      _curr_field._set(hdr_buf, hdr_loc, _field_loc);

      _curr_index = 0;

      _good = true;

    }

    friend class HttpMessage;

  };

  

  class Url : boost::noncopyable {

  public:

    Url() : _url_loc(0) { }

    bool getQuery(MString &query) {

      query.clear();

      if (_url_loc) {

        query._data = INKUrlHttpQueryGet(_hdr_buf, _url_loc,
&(query._size));

        if (query._data && (query._data != INK_ERROR_PTR)) {

          query._set(_hdr_buf, _url_loc);

          return true;

        }

      }

      return false;

    }

    bool getString(MString &mstr) {

      mstr.clear();

      if (_url_loc) {

        const char *ptr = INKUrlStringGet(_hdr_buf, _url_loc, NULL);

        if (ptr && (ptr != INK_ERROR_PTR)) {

          mstr._set(ptr);

          return true;

        }

      }

      return false;

    }

    void clear() {

      if (_url_loc) {

        INKHandleMLocRelease(_hdr_buf, _hdr_loc, _url_loc);

        _url_loc = 0;

      }

    }

    ~Url() { clear(); }

  private:

    INKMBuffer _hdr_buf;

    INKMLoc _hdr_loc;

    INKMLoc _url_loc;

    void _set(INKMBuffer hdr_buf, INKMLoc hdr_loc, INKMLoc url_loc) {

      _hdr_buf = hdr_buf;

      _hdr_loc = hdr_loc;

      _url_loc = url_loc;

    }

    friend class HttpRequest;

  };

 

  class HttpMessage : boost::noncopyable {

  public:

    HttpMessage() : _buf(0), _loc(0) { };

    virtual void clear() {

      if (_buf) {

        INKHandleMLocRelease(_buf, INK_NULL_MLOC, _loc);

        _buf = 0;

        _loc = 0;

      }

    }

    virtual bool getHeaderFieldIterator(HttpHeaderFieldIterator
&field_iter) {

      field_iter.clear();

      if (_buf) {

        INKMLoc first_field = INKMimeHdrFieldGet(_buf, _loc, 0);

        if (first_field && (first_field != INK_ERROR_PTR)) {

          field_iter._set(_buf, _loc, first_field);

          return true;

        }

      }

      return false;

    }

    virtual bool addHeaderField(const char *name, int name_len, const
char *value, int value_len) {

      bool retval = false;

      if (_buf) {

        INKMLoc field_loc = INKMimeHdrFieldCreate(_buf, _loc);

        if (field_loc && (field_loc != INK_ERROR_PTR)) {

          if (INKMimeHdrFieldNameSet(_buf, _loc, field_loc, name,
name_len) == INK_SUCCESS) {

            if (INKMimeHdrFieldValueStringInsert(_buf, _loc, field_loc,
0, value, value_len) == INK_SUCCESS) {

              if (INKMimeHdrFieldAppend(_buf, _loc, field_loc) ==
INK_SUCCESS) {

                retval = true;

              }

            }

          }

          INKHandleMLocRelease(_buf, _loc, field_loc);

        }

      }

      return retval;

    }

    virtual bool isHeaderPresent(const char *name, int name_len, const
char *value = 0, int value_len = 0) {

      bool retval = false;

      if (_buf) {

        INKMLoc field_loc = INKMimeHdrFieldFind(_buf, _loc, name,
name_len);

        if (field_loc && (field_loc != INK_ERROR_PTR)) {

          if (value && value_len) {

            int n_values = INKMimeHdrFieldValuesCount(_buf, _loc,
field_loc);

            if (n_values != INK_ERROR) {

              HttpHeaderValueIterator value_iter;

              value_iter._set(_buf, _loc, field_loc, n_values);

              for (; value_iter.good(); value_iter.next()) {

                if ((value_iter->size() == value_len) &&
(strncasecmp(value_iter->data(), value, value_len) == 0)) {

                  retval = true;

                  break;

                }

              }

            }

          } else {

            retval = true;

          }

          INKHandleMLocRelease(_buf, _loc, field_loc);

        }

      }

      return retval;

    }

    virtual ~HttpMessage() { clear(); };

  protected:

    INKMBuffer _buf;

    INKMLoc _loc;

  };

 

  class HttpRequest : public HttpMessage {

  public:

    bool getUrl(Url &url) {

      url.clear();

      if (_buf) {

        INKMLoc url_loc = INKHttpHdrUrlGet(_buf, _loc);

        if (url_loc && (url_loc != INK_ERROR_PTR)) {

          url._set(_buf, _loc, url_loc);

          return true;

        }

      }

      return false;

    }

    bool getMethod(MString &method) {

      method.clear();

      if (_buf) {

        method._data = INKHttpHdrMethodGet(_buf, _loc, &method._size);

        if (method._data && (method._data != INK_ERROR_PTR)) {

          method._set(_buf, _loc);

          return true;

        }

      }

      return false;

    }

  private:

    friend class HttpTransaction;

  };

 

  class HttpResponse : public HttpMessage {

  public:

  private:

    friend class HttpTransaction;

  };

 

  class HttpTransaction : boost::noncopyable {

  public:

    HttpTransaction(INKHttpTxn txnp) : _txnp(txnp) { };

    bool getClientReq(HttpRequest &req) {

      req.clear();

      return (INKHttpTxnClientReqGet(_txnp, &req._buf, &req._loc) == 1);

    }

    bool getServerResp(HttpResponse &resp) {

      resp.clear();

      return (INKHttpTxnServerRespGet(_txnp, &resp._buf, &resp._loc) ==
1);

    }

    bool getClientResp(HttpResponse &resp) {

      resp.clear();

      return (INKHttpTxnClientRespGet(_txnp, &resp._buf, &resp._loc) ==
1);

    }

  private:

    INKHttpTxn _txnp;

  };

 

};

 

#endif

 

 

 

 

> -----Original Message-----

> From: Manjesh Nilange [mailto:manj...@yahoo-inc.com]

> Sent: Wednesday, July 21, 2010 2:59 PM

> To: dev@trafficserver.apache.org

> Subject: C++ wrapper for some API sections

> 

> Hi all,

> 

> I started working on a C++ wrapper for some of the API functions to
make

> some of the data structures easier to use. What I did was basically
wrap

> the pointers and types so that they can be automatically

> released/destroyed. I abandoned working on this as I have other things

> on my place. However, if others see value in what it currently
provides

> or wish to enhance and improve it, I'll check it in. I'm attaching the

> wrapper and an example source file to show the benefits (reduced code

> and automatic cleanup). The wrapper is just a proof of concept and has

> some caveats and limitations, but it compiles and works fine.

> 

> - Manjesh

 

Reply via email to