MINOR: lua: create and register HTTP class

This class is accessible via the TXN object. It is created only if
the attached proxy have HTTP mode. It contain all the HTTP
manipulation functions:

 - req_get_headers
 - req_del_header
 - req_rep_header
 - req_rep_value
 - req_add_header
 - req_set_header
 - req_set_method
 - req_set_path
 - req_set_query
 - req_set_uri

 - res_get_headers
 - res_del_header
 - res_rep_header
 - res_rep_value
 - res_add_header
 - res_set_header
diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst
index 545ee37..d9cf262 100644
--- a/doc/lua-api/index.rst
+++ b/doc/lua-api/index.rst
@@ -425,6 +425,179 @@
   :param class_channel channel: The manipulated channel.
   :param integer int: The amount of data which will be forwarded.
 
+
+HTTP class
+==========
+
+.. js:class:: HTTP
+
+   This class contain all the HTTP manipulation functions.
+
+.. js:function:: http.req_get_header(http)
+
+  Returns an array containing all the request headers.
+
+  :param class_http http: The related http object.
+  :returns: array of headers.
+  :see: http.res_get_header()
+
+.. js:function:: http.res_get_header(http)
+
+  Returns an array containing all the response headers.
+
+  :param class_http http: The related http object.
+  :returns: array of headers.
+  :see: http.req_get_header()
+
+.. js:function:: http.req_add_header(http, name, value)
+
+  Appends an HTTP header field in the request whose name is
+  specified in "name" and whose value is defined in "value".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string value: The header value.
+  :see: http.res_add_header()
+
+.. js:function:: http.res_add_header(http, name, value)
+
+  appends an HTTP header field in the response whose name is
+  specified in "name" and whose value is defined in "value".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string value: The header value.
+  :see: http.req_add_header()
+
+.. js:function:: http.req_del_header(http, name)
+
+  Removes all HTTP header fields in the request whose name is
+  specified in "name".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :see: http.res_del_header()
+
+.. js:function:: http.res_del_header(http, name)
+
+  Removes all HTTP header fields in the response whose name is
+  specified in "name".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :see: http.req_del_header()
+
+.. js:function:: http.req_set_header(http, name, value)
+
+  This variable replace all occurence of all header "name", by only
+  one containing the "value".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string value: The header value.
+  :see: http.res_set_header()
+
+  This function does the same work as the folowwing code:
+
+.. code-block:: lua
+
+   function fcn(txn)
+      txn.http:req_del_header("header")
+      txn.http:req_add_header("header", "value")
+   end
+..
+
+.. js:function:: http.res_set_header(http, name, value)
+
+  This variable replace all occurence of all header "name", by only
+  one containing the "value".
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string value: The header value.
+  :see: http.req_set_header()
+
+.. js:function:: http.req_replace_header(http, name, regex, replace)
+
+  Matches the regular expression in all occurrences of header field "name"
+  according to "regex", and replaces them with the "replace" argument. The
+  replacement value can contain back references like \1, \2, ... This
+  function works with the request.
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string regex: The match regular expression.
+  :param string replace: The replacement value.
+  :see: http.res_replace_header()
+
+.. js:function:: http.res_replace_header(http, name, regex, string)
+
+  Matches the regular expression in all occurrences of header field "name"
+  according to "regex", and replaces them with the "replace" argument. The
+  replacement value can contain back references like \1, \2, ... This
+  function works with the request.
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string regex: The match regular expression.
+  :param string replace: The replacement value.
+  :see: http.req_replace_header()
+
+.. js:function:: http.req_replace_value(http, name, regex, replace)
+
+  Works like "http.req_replace_header()" except that it matches the regex
+  against every comma-delimited value of the header field "name" instead of the
+  entire header.
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string regex: The match regular expression.
+  :param string replace: The replacement value.
+  :see: http.req_replace_header()
+  :see: http.res_replace_value()
+
+.. js:function:: http.res_replace_value(http, name, regex, replace)
+
+  Works like "http.res_replace_header()" except that it matches the regex
+  against every comma-delimited value of the header field "name" instead of the
+  entire header.
+
+  :param class_http http: The related http object.
+  :param string name: The header name.
+  :param string regex: The match regular expression.
+  :param string replace: The replacement value.
+  :see: http.res_replace_header()
+  :see: http.req_replace_value()
+
+.. js:function:: http.req_set_method(http, method)
+
+  Rewrites the request method with the parameter "method".
+
+  :param class_http http: The related http object.
+  :param string method: The new method.
+
+.. js:function:: http.req_set_path(http, path)
+
+  Rewrites the request path with the "path" parameter.
+
+  :param class_http http: The related http object.
+  :param string path: The new path.
+
+.. js:function:: http.req_set_query(http, query)
+
+  Rewrites the request's query string which appears after the first question
+  mark ("?") with the parameter "query".
+
+  :param class_http http: The related http object.
+  :param string query: The new query.
+
+.. js:function:: http.req.set_uri(http, uri)
+
+  Rewrites the request URI with the parameter "uri".
+
+  :param class_http http: The related http object.
+  :param string uri: The new uri.
+
 TXN class
 =========
 
@@ -466,6 +639,11 @@
 
   This attribute contains a channel class object for the response buffer.
 
+.. js:attribute:: txn.http
+
+  This attribute contains an HTTP class object. It is avalaible only if the
+  proxy has the "mode http" enabled.
+
 .. js:function:: txn.get_priv(txn)
 
   Return Lua data stored in the current transaction (with the `txn.set_priv()`)
@@ -497,61 +675,11 @@
 
   :param class_txn txn: The class txn object containing the data.
 
-.. js:function:: txn.http.redirect(txn, location)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.add_header(txn, name, value)
-
-  Not yet avalaible.
 
-.. js:function:: txn.http.req.set_method(txn, string)
 
-  Not yet avalaible.
 
-.. js:function:: txn.http.req.set_path(txn, string)
 
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.set_query(txn, string)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.set_uri(txn, string)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.set_header(txn, name, value)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.del_header(txn, name)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.replace_header(txn, name, regex, string)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.req.replace_value(txn, name, regex, string)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.res.set_header(txn, name, value)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.res.del_header(txn, name)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.res.replace_header(txn, name, regex, string)
-
-  Not yet avalaible.
-
-.. js:function:: txn.http.res.replace_value(txn, name, regex, string)
 
-  Not yet avalaible.
 
 .. js:function:: txn.set_loglevel(txn, loglevel)
 
diff --git a/include/types/hlua.h b/include/types/hlua.h
index b59a3b7..8418771 100644
--- a/include/types/hlua.h
+++ b/include/types/hlua.h
@@ -15,6 +15,7 @@
 #define CLASS_CONVERTERS "Converters"
 #define CLASS_SOCKET   "Socket"
 #define CLASS_CHANNEL  "Channel"
+#define CLASS_HTTP     "HTTP"
 
 struct session;
 
diff --git a/src/hlua.c b/src/hlua.c
index 65939ee..b6f53a9 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -73,6 +73,7 @@
 static int class_channel_ref;
 static int class_fetches_ref;
 static int class_converters_ref;
+static int class_http_ref;
 
 /* Global Lua execution timeout. By default Lua, execution linked
  * with session (actions, sample-fetches and converters) have a
@@ -2861,6 +2862,361 @@
 /*
  *
  *
+ * Class HTTP
+ *
+ *
+ */
+
+/* Returns a struct hlua_txn if the stack entry "ud" is
+ * a class session, otherwise it throws an error.
+ */
+__LJMP static struct hlua_txn *hlua_checkhttp(lua_State *L, int ud)
+{
+	return (struct hlua_txn *)MAY_LJMP(hlua_checkudata(L, ud, class_http_ref));
+}
+
+/* This function creates and push in the stack a HTTP object
+ * according with a current TXN.
+ */
+static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
+{
+	struct hlua_txn *ht;
+
+	/* Check stack size. */
+	if (!lua_checkstack(L, 3))
+		return 0;
+
+	/* Create the object: obj[0] = userdata.
+	 * Note that the base of the Converters object is the
+	 * same than the TXN object.
+	 */
+	lua_newtable(L);
+	ht = lua_newuserdata(L, sizeof(struct hlua_txn));
+	lua_rawseti(L, -2, 0);
+
+	ht->s = txn->s;
+	ht->p = txn->p;
+	ht->l7 = txn->l7;
+
+	/* Pop a class session metatable and affect it to the table. */
+	lua_rawgeti(L, LUA_REGISTRYINDEX, class_http_ref);
+	lua_setmetatable(L, -2);
+
+	return 1;
+}
+
+/* This function creates ans returns an array of HTTP headers.
+ * This function does not fails. It is used as wrapper with the
+ * 2 following functions.
+ */
+__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
+{
+	const char *cur_ptr, *cur_next, *p;
+	int old_idx, cur_idx;
+	struct hdr_idx_elem *cur_hdr;
+	const char *hn, *hv;
+	int hnl, hvl;
+
+	/* Create the table. */
+	lua_newtable(L);
+
+	/* Build array of headers. */
+	old_idx = 0;
+	cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn.hdr_idx);
+
+	while (1) {
+		cur_idx = htxn->s->txn.hdr_idx.v[old_idx].next;
+		if (!cur_idx)
+			break;
+		old_idx = cur_idx;
+
+		cur_hdr  = &htxn->s->txn.hdr_idx.v[cur_idx];
+		cur_ptr  = cur_next;
+		cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
+
+		/* Now we have one full header at cur_ptr of len cur_hdr->len,
+		 * and the next header starts at cur_next. We'll check
+		 * this header in the list as well as against the default
+		 * rule.
+		 */
+
+		/* look for ': *'. */
+		hn = cur_ptr;
+		for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
+		if (p >= cur_ptr+cur_hdr->len)
+			continue;
+		hnl = p - hn;
+		p++;
+		while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
+			p++;
+		if (p >= cur_ptr+cur_hdr->len)
+			continue;
+		hv = p;
+		hvl = cur_ptr+cur_hdr->len-p;
+
+		/* Push values in the table. */
+		lua_pushlstring(L, hn, hnl);
+		lua_pushlstring(L, hv, hvl);
+		lua_settable(L, -3);
+	}
+
+	return 1;
+}
+
+__LJMP static int hlua_http_req_get_headers(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 1, "req_get_headers"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_get_headers(L, htxn, &htxn->s->txn.req);
+}
+
+__LJMP static int hlua_http_res_get_headers(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 1, "res_get_headers"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_get_headers(L, htxn, &htxn->s->txn.rsp);
+}
+
+/* This function replace full header, or just a value in
+ * the request or in the response. It is a wrapper fir the
+ * 4 following functions.
+ */
+__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
+                                           struct http_msg *msg, int action)
+{
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	const char *reg = MAY_LJMP(luaL_checkstring(L, 3));
+	const char *value = MAY_LJMP(luaL_checkstring(L, 4));
+	struct my_regex re;
+
+	if (!regex_comp(reg, &re, 1, 1, NULL))
+		WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
+
+	http_transform_header_str(htxn->s, msg, name, name_len, value, &re, action);
+	regex_free(&re);
+	return 0;
+}
+
+__LJMP static int hlua_http_req_rep_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.req, HTTP_REQ_ACT_REPLACE_HDR));
+}
+
+__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.rsp, HTTP_RES_ACT_REPLACE_HDR));
+}
+
+__LJMP static int hlua_http_req_rep_val(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.req, HTTP_REQ_ACT_REPLACE_VAL));
+}
+
+__LJMP static int hlua_http_res_rep_val(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 4, "res_rep_val"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.rsp, HTTP_RES_ACT_REPLACE_VAL));
+}
+
+/* This function deletes all the occurences of an header.
+ * It is a wrapper for the 2 following functions.
+ */
+__LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
+{
+	size_t len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
+	struct hdr_ctx ctx;
+	struct http_txn *txn = &htxn->s->txn;
+
+	ctx.idx = 0;
+	while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx))
+		http_remove_header2(msg, &txn->hdr_idx, &ctx);
+	return 0;
+}
+
+__LJMP static int hlua_http_req_del_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 2, "req_del_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_del_hdr(L, htxn, &htxn->s->txn.req);
+}
+
+__LJMP static int hlua_http_res_del_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 2, "req_del_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_del_hdr(L, htxn, &htxn->s->txn.rsp);
+}
+
+/* This function adds an header. It is a wrapper used by
+ * the 2 following functions.
+ */
+__LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
+{
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	size_t value_len;
+	const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
+	char *p;
+
+	/* Check length. */
+	trash.len = value_len + name_len + 2;
+	if (trash.len > trash.size)
+		return 0;
+
+	/* Creates the header string. */
+	p = trash.str;
+	memcpy(p, name, name_len);
+	p += name_len;
+	*p = ':';
+	p++;
+	*p = ' ';
+	p++;
+	memcpy(p, value, value_len);
+
+	lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn.hdr_idx,
+	                                         trash.str, trash.len) != 0);
+
+	return 0;
+}
+
+__LJMP static int hlua_http_req_add_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 3, "req_add_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_add_hdr(L, htxn, &htxn->s->txn.req);
+}
+
+__LJMP static int hlua_http_res_add_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 3, "res_add_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	return hlua_http_add_hdr(L, htxn, &htxn->s->txn.rsp);
+}
+
+static int hlua_http_req_set_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 3, "req_set_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	hlua_http_del_hdr(L, htxn, &htxn->s->txn.req);
+	return hlua_http_add_hdr(L, htxn, &htxn->s->txn.req);
+}
+
+static int hlua_http_res_set_hdr(lua_State *L)
+{
+	struct hlua_txn *htxn;
+
+	MAY_LJMP(check_args(L, 3, "res_set_hdr"));
+	htxn = MAY_LJMP(hlua_checkhttp(L, 1));
+
+	hlua_http_del_hdr(L, htxn, &htxn->s->txn.rsp);
+	return hlua_http_add_hdr(L, htxn, &htxn->s->txn.rsp);
+}
+
+/* This function set the method. */
+static int hlua_http_req_set_meth(lua_State *L)
+{
+	struct hlua_txn *s = MAY_LJMP(hlua_checkhttp(L, 1));
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	struct http_txn *txn = &s->s->txn;
+
+	lua_pushboolean(L, http_replace_req_line(0, name, name_len, s->p, s->s, txn) != -1);
+	return 1;
+}
+
+/* This function set the method. */
+static int hlua_http_req_set_path(lua_State *L)
+{
+	struct hlua_txn *s = MAY_LJMP(hlua_checkhttp(L, 1));
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	struct http_txn *txn = &s->s->txn;
+
+	lua_pushboolean(L, http_replace_req_line(1, name, name_len, s->p, s->s, txn) != -1);
+	return 1;
+}
+
+/* This function set the query-string. */
+static int hlua_http_req_set_query(lua_State *L)
+{
+	struct hlua_txn *s = MAY_LJMP(hlua_checkhttp(L, 1));
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	struct http_txn *txn = &s->s->txn;
+
+	/* Check length. */
+	if (name_len > trash.size - 1) {
+		lua_pushboolean(L, 0);
+		return 1;
+	}
+
+	/* Add the mark question as prefix. */
+	chunk_reset(&trash);
+	trash.str[trash.len++] = '?';
+	memcpy(trash.str + trash.len, name, name_len);
+	trash.len += name_len;
+
+	lua_pushboolean(L, http_replace_req_line(2, trash.str, trash.len, s->p, s->s, txn) != -1);
+	return 1;
+}
+
+/* This function set the uri. */
+static int hlua_http_req_set_uri(lua_State *L)
+{
+	struct hlua_txn *s = MAY_LJMP(hlua_checkhttp(L, 1));
+	size_t name_len;
+	const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
+	struct http_txn *txn = &s->s->txn;
+
+	lua_pushboolean(L, http_replace_req_line(3, name, name_len, s->p, s->s, txn) != -1);
+	return 1;
+}
+
+/*
+ *
+ *
  * Class TXN
  *
  *
@@ -2976,6 +3332,16 @@
 		return 0;
 	lua_settable(L, -3);
 
+	/* Creates the HTTP object is the current proxy allows http. */
+	lua_pushstring(L, "http");
+	if (p->mode == PR_MODE_HTTP) {
+		if (!hlua_http_new(L, hs))
+			return 0;
+	}
+	else
+		lua_pushnil(L);
+	lua_settable(L, -3);
+
 	/* Pop a class sesison metatable and affect it to the userdata. */
 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_txn_ref);
 	lua_setmetatable(L, -2);
@@ -3056,65 +3422,6 @@
 	return 0;
 }
 
-/* This function is an LUA binding. It creates ans returns
- * an array of HTTP headers. This function does not fails.
- */
-static int hlua_session_get_headers(lua_State *L)
-{
-	struct hlua_txn *s = MAY_LJMP(hlua_checktxn(L, 1));
-	struct session *sess = s->s;
-	const char *cur_ptr, *cur_next, *p;
-	int old_idx, cur_idx;
-	struct hdr_idx_elem *cur_hdr;
-	const char *hn, *hv;
-	int hnl, hvl;
-
-	/* Create the table. */
-	lua_newtable(L);
-
-	/* Build array of headers. */
-	old_idx = 0;
-	cur_next = sess->req.buf->p + hdr_idx_first_pos(&sess->txn.hdr_idx);
-
-	while (1) {
-		cur_idx = sess->txn.hdr_idx.v[old_idx].next;
-		if (!cur_idx)
-			break;
-		old_idx = cur_idx;
-
-		cur_hdr  = &sess->txn.hdr_idx.v[cur_idx];
-		cur_ptr  = cur_next;
-		cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
-
-		/* Now we have one full header at cur_ptr of len cur_hdr->len,
-		 * and the next header starts at cur_next. We'll check
-		 * this header in the list as well as against the default
-		 * rule.
-		 */
-
-		/* look for ': *'. */
-		hn = cur_ptr;
-		for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
-		if (p >= cur_ptr+cur_hdr->len)
-			continue;
-		hnl = p - hn;
-		p++;
-		while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
-			p++;
-		if (p >= cur_ptr+cur_hdr->len)
-			continue;
-		hv = p;
-		hvl = cur_ptr+cur_hdr->len-p;
-
-		/* Push values in the table. */
-		lua_pushlstring(L, hn, hnl);
-		lua_pushlstring(L, hv, hvl);
-		lua_settable(L, -3);
-	}
-
-	return 1;
-}
-
 __LJMP static int hlua_sleep_yield(lua_State *L, int status, lua_KContext ctx)
 {
 	int wakeup_ms = lua_tointeger(L, -1);
@@ -4255,6 +4562,45 @@
 
 	/*
 	 *
+	 * Register class HTTP
+	 *
+	 */
+
+	/* Create and fill the metatable. */
+	lua_newtable(gL.T);
+
+	/* Create and fille the __index entry. */
+	lua_pushstring(gL.T, "__index");
+	lua_newtable(gL.T);
+
+	/* Register Lua functions. */
+	hlua_class_function(gL.T, "req_get_headers",hlua_http_req_get_headers);
+	hlua_class_function(gL.T, "req_del_header", hlua_http_req_del_hdr);
+	hlua_class_function(gL.T, "req_rep_header", hlua_http_req_rep_hdr);
+	hlua_class_function(gL.T, "req_rep_value",  hlua_http_req_rep_val);
+	hlua_class_function(gL.T, "req_add_header", hlua_http_req_add_hdr);
+	hlua_class_function(gL.T, "req_set_header", hlua_http_req_set_hdr);
+	hlua_class_function(gL.T, "req_set_method", hlua_http_req_set_meth);
+	hlua_class_function(gL.T, "req_set_path",   hlua_http_req_set_path);
+	hlua_class_function(gL.T, "req_set_query",  hlua_http_req_set_query);
+	hlua_class_function(gL.T, "req_set_uri",    hlua_http_req_set_uri);
+
+	hlua_class_function(gL.T, "res_get_headers",hlua_http_res_get_headers);
+	hlua_class_function(gL.T, "res_del_header", hlua_http_res_del_hdr);
+	hlua_class_function(gL.T, "res_rep_header", hlua_http_res_rep_hdr);
+	hlua_class_function(gL.T, "res_rep_value",  hlua_http_res_rep_val);
+	hlua_class_function(gL.T, "res_add_header", hlua_http_res_add_hdr);
+	hlua_class_function(gL.T, "res_set_header", hlua_http_res_set_hdr);
+
+	lua_settable(gL.T, -3);
+
+	/* Register previous table in the registry with reference and named entry. */
+	lua_pushvalue(gL.T, -1); /* Copy the -1 entry and push it on the stack. */
+	lua_setfield(gL.T, LUA_REGISTRYINDEX, CLASS_HTTP); /* register class session. */
+	class_http_ref = luaL_ref(gL.T, LUA_REGISTRYINDEX); /* reference class session. */
+
+	/*
+	 *
 	 * Register class TXN
 	 *
 	 */
@@ -4267,7 +4613,6 @@
 	lua_newtable(gL.T);
 
 	/* Register Lua functions. */
-	hlua_class_function(gL.T, "get_headers", hlua_session_get_headers);
 	hlua_class_function(gL.T, "set_priv",    hlua_set_priv);
 	hlua_class_function(gL.T, "get_priv",    hlua_get_priv);
 	hlua_class_function(gL.T, "close",       hlua_txn_close);