Rename all rest structures and functions to be in terms of request/response instead...
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 23 Mar 2014 11:44:27 +0000 (11:44 +0000)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 23 Mar 2014 11:48:13 +0000 (11:48 +0000)
It makes significantly more sense now...

src/modules/rlm_rest/rest.c
src/modules/rlm_rest/rest.h
src/modules/rlm_rest/rlm_rest.c

index d6e121c..37b4e86 100644 (file)
@@ -113,7 +113,7 @@ const unsigned long http_curl_auth[HTTP_AUTH_NUM_ENTRIES] = {
 /** Conversion table for method config values.
  *
  * HTTP verb strings for http_method_t enum values. Used by libcurl in the
- * status line of the outgoing HTTP header, by rest_write_header for decoding
+ * status line of the outgoing HTTP header, by rest_response_header for decoding
  * incoming HTTP responses, and by the configuration parser.
  *
  * @see http_method_t
@@ -171,7 +171,7 @@ const FR_NAME_NUMBER http_auth_table[] = {
 
 /** Conversion table for "Content-Type" header values.
  *
- * Used by rest_write_header for parsing incoming headers.
+ * Used by rest_response_header for parsing incoming headers.
  *
  * Values we expect to see in the 'Content-Type:' header of the incoming
  * response.
@@ -328,7 +328,7 @@ void *mod_conn_create(void *instance)
        ctx = talloc_zero(randle, rlm_rest_curl_context_t);
 
        ctx->headers = NULL; /* CURL needs this to be NULL */
-       ctx->read.instance = inst;
+       ctx->request.instance = inst;
 
        randle->ctx = ctx;
        randle->handle = candle;
@@ -433,15 +433,15 @@ int mod_conn_delete(UNUSED void *instance, void *handle)
  * @param[out] out Char buffer to write encoded data to.
  * @param[in] size Multiply by nmemb to get the length of ptr.
  * @param[in] nmemb Multiply by size to get the length of ptr.
- * @param[in] userdata rlm_rest_read_t to keep encoding state between calls.
+ * @param[in] userdata rlm_rest_request_t to keep encoding state between calls.
  * @return length of data (including NULL) written to ptr, or 0 if no more
  *     data to write.
  */
 static size_t rest_encode_post(void *out, size_t size, size_t nmemb, void *userdata)
 {
-       rlm_rest_read_t *ctx = userdata;
-       REQUEST         *request = ctx->request; /* Used by RDEBUG */
-       VALUE_PAIR      *vp;
+       rlm_rest_request_t      *ctx = userdata;
+       REQUEST                 *request = ctx->request; /* Used by RDEBUG */
+       VALUE_PAIR              *vp;
 
        char *p = out;          /* Position in buffer */
        char *encoded = p;      /* Position in buffer of last fully encoded attribute or value */
@@ -607,13 +607,13 @@ no_space:
  * @param[out] out Char buffer to write encoded data to.
  * @param[in] size Multiply by nmemb to get the length of ptr.
  * @param[in] nmemb Multiply by size to get the length of ptr.
- * @param[in] userdata rlm_rest_read_t to keep encoding state between calls.
+ * @param[in] userdata rlm_rest_request_t to keep encoding state between calls.
  * @return length of data (including NULL) written to ptr, or 0 if no more
  *     data to write.
  */
 static size_t rest_encode_json(void *out, size_t size, size_t nmemb, void *userdata)
 {
-       rlm_rest_read_t *ctx = userdata;
+       rlm_rest_request_t      *ctx = userdata;
        REQUEST         *request = ctx->request; /* Used by RDEBUG */
        VALUE_PAIR      *vp, *next;
 
@@ -780,12 +780,12 @@ no_space:
  *     be written.
  * @param[in] func Stream function.
  * @param[in] limit Maximum buffer size to alloc.
- * @param[in] userdata rlm_rest_read_t to keep encoding state between calls to
+ * @param[in] userdata rlm_rest_request_t to keep encoding state between calls to
  *     stream function.
  * @return the length of the data written to the buffer (excluding NULL) or -1
  *     if alloc >= limit.
  */
-static ssize_t rest_read_wrapper(char **buffer, rest_read_t func, size_t limit, void *userdata)
+static ssize_t rest_request_encode_wrapper(char **buffer, rest_read_t func, size_t limit, void *userdata)
 {
        char *previous = NULL;
        char *current;
@@ -818,16 +818,16 @@ static ssize_t rest_read_wrapper(char **buffer, rest_read_t func, size_t limit,
        return -1;
 }
 
-/** (Re-)Initialises the data in a rlm_rest_read_t.
+/** (Re-)Initialises the data in a rlm_rest_request_t.
  *
- * Resets the values of a rlm_rest_read_t to their defaults.
+ * Resets the values of a rlm_rest_request_t to their defaults.
  *
  * @param[in] request Current request.
  * @param[in] ctx to initialise.
  * @param[in] sort If true VALUE_PAIRs will be sorted within the VALUE_PAIR
  *     pointer array.
  */
-static void rest_read_ctx_init(REQUEST *request, rlm_rest_read_t *ctx, bool sort)
+static void rest_request_init(REQUEST *request, rlm_rest_request_t *ctx, bool sort)
 {
        /*
         *      Setup stream read data
@@ -1366,12 +1366,12 @@ static int rest_decode_json(rlm_rest_t *instance, UNUSED rlm_rest_section_t *sec
  * @param[in] in Char buffer where inbound header data is written.
  * @param[in] size Multiply by nmemb to get the length of ptr.
  * @param[in] nmemb Multiply by size to get the length of ptr.
- * @param[in] userdata rlm_rest_write_t to keep parsing state between calls.
+ * @param[in] userdata rlm_rest_response_t to keep parsing state between calls.
  * @return Length of data processed, or 0 on error.
  */
-static size_t rest_write_header(void *in, size_t size, size_t nmemb, void *userdata)
+static size_t rest_response_header(void *in, size_t size, size_t nmemb, void *userdata)
 {
-       rlm_rest_write_t *ctx = userdata;
+       rlm_rest_response_t *ctx = userdata;
        REQUEST *request = ctx->request; /* Used by RDEBUG */
 
        char const *p = in, *q;
@@ -1544,12 +1544,12 @@ malformed:
  * @param[in] ptr Char buffer where inbound header data is written
  * @param[in] size Multiply by nmemb to get the length of ptr.
  * @param[in] nmemb Multiply by size to get the length of ptr.
- * @param[in] userdata rlm_rest_write_t to keep parsing state between calls.
+ * @param[in] userdata rlm_rest_response_t to keep parsing state between calls.
  * @return length of data processed, or 0 on error.
  */
-static size_t rest_write_body(void *ptr, size_t size, size_t nmemb, void *userdata)
+static size_t rest_response_body(void *ptr, size_t size, size_t nmemb, void *userdata)
 {
-       rlm_rest_write_t *ctx = userdata;
+       rlm_rest_response_t *ctx = userdata;
        REQUEST *request = ctx->request; /* Used by RDEBUG */
 
        char const *p = ptr, *q;
@@ -1615,20 +1615,20 @@ static size_t rest_write_body(void *ptr, size_t size, size_t nmemb, void *userda
        return t;
 }
 
-/** (Re-)Initialises the data in a rlm_rest_write_t.
+/** (Re-)Initialises the data in a rlm_rest_response_t.
  *
- * This resets the values of the a rlm_rest_write_t to their defaults.
+ * This resets the values of the a rlm_rest_response_t to their defaults.
  * Must be called between encoding sessions.
  *
- * @see rest_write_body
- * @see rest_write_header
+ * @see rest_response_body
+ * @see rest_response_header
  *
  * @param[in] request Current request.
  * @param[in] ctx data to initialise.
  * @param[in] type Default http_body_type to use when decoding raw data, may be
- * overwritten by rest_write_header.
+ * overwritten by rest_response_header.
  */
-static void rest_write_ctx_init(REQUEST *request, rlm_rest_write_t *ctx, http_body_type_t type)
+static void rest_response_init(REQUEST *request, rlm_rest_response_t *ctx, http_body_type_t type)
 {
        ctx->request = request;
        ctx->type = type;
@@ -1642,7 +1642,7 @@ static void rest_write_ctx_init(REQUEST *request, rlm_rest_write_t *ctx, http_bo
  *
  * @param[in] ctx data to be freed.
  */
-static void rest_write_free(rlm_rest_write_t *ctx)
+static void rest_response_free(rlm_rest_response_t *ctx)
 {
        if (ctx->buffer != NULL) {
                free(ctx->buffer);
@@ -1688,7 +1688,7 @@ static int rest_request_config_body(UNUSED rlm_rest_t *instance, rlm_rest_sectio
         *  multiple parts.
         */
        if (section->chunk > 0) {
-               SET_OPTION(CURLOPT_READDATA, &ctx->read);
+               SET_OPTION(CURLOPT_READDATA, &ctx->request);
                SET_OPTION(CURLOPT_READFUNCTION, func);
 
                return 0;
@@ -1698,7 +1698,7 @@ static int rest_request_config_body(UNUSED rlm_rest_t *instance, rlm_rest_sectio
         *  If were not doing chunked encoding then we read the entire
         *  body into a buffer, and send it in one go.
         */
-       len = rest_read_wrapper(&ctx->body, func, REST_BODY_MAX_LEN, &ctx->read);
+       len = rest_request_encode_wrapper(&ctx->body, func, REST_BODY_MAX_LEN, &ctx->request);
        if (len <= 0) {
                REDEBUG("Failed creating HTTP body content");
                return -1;
@@ -1912,12 +1912,12 @@ int rest_request_config(rlm_rest_t *instance, rlm_rest_section_t *section,
        /*
         *      Tell CURL how to get HTTP body content, and how to process incoming data.
         */
-       rest_write_ctx_init(request, &ctx->write, type);
+       rest_response_init(request, &ctx->response, type);
 
-       SET_OPTION(CURLOPT_HEADERFUNCTION, rest_write_header);
-       SET_OPTION(CURLOPT_HEADERDATA, &ctx->write);
-       SET_OPTION(CURLOPT_WRITEFUNCTION, rest_write_body);
-       SET_OPTION(CURLOPT_WRITEDATA, &ctx->write);
+       SET_OPTION(CURLOPT_HEADERFUNCTION, rest_response_header);
+       SET_OPTION(CURLOPT_HEADERDATA, &ctx->response);
+       SET_OPTION(CURLOPT_WRITEFUNCTION, rest_response_body);
+       SET_OPTION(CURLOPT_WRITEDATA, &ctx->response);
 
        switch (method) {
        case HTTP_METHOD_GET :
@@ -1928,7 +1928,7 @@ int rest_request_config(rlm_rest_t *instance, rlm_rest_section_t *section,
        case HTTP_METHOD_PUT :
        case HTTP_METHOD_CUSTOM :
                if (section->chunk > 0) {
-                       ctx->read.chunk = section->chunk;
+                       ctx->request.chunk = section->chunk;
 
                        ctx->headers = curl_slist_append(ctx->headers, "Expect:");
                        if (!ctx->headers) goto error_header;
@@ -1948,7 +1948,7 @@ int rest_request_config(rlm_rest_t *instance, rlm_rest_section_t *section,
 
 #ifdef HAVE_JSON
                case HTTP_BODY_JSON:
-                       rest_read_ctx_init(request, &ctx->read, 1);
+                       rest_request_init(request, &ctx->request, 1);
 
                        if (rest_request_config_body(instance, section, request, handle,
                                                     rest_encode_json) < 0) {
@@ -1959,7 +1959,7 @@ int rest_request_config(rlm_rest_t *instance, rlm_rest_section_t *section,
 #endif
 
                case HTTP_BODY_POST:
-                       rest_read_ctx_init(request, &ctx->read, 0);
+                       rest_request_init(request, &ctx->request, 0);
 
                        if (rest_request_config_body(instance, section, request, handle,
                                                     rest_encode_post) < 0) {
@@ -2020,7 +2020,7 @@ int rest_request_perform(UNUSED rlm_rest_t *instance, UNUSED rlm_rest_section_t
 
 /** Sends the response to the correct decode function.
  *
- * Uses the Content-Type information written in rest_write_header to
+ * Uses the Content-Type information written in rest_response_header to
  * determine the correct decode function to use. The decode function will
  * then convert the raw received data into VALUE_PAIRs.
  *
@@ -2030,32 +2030,32 @@ int rest_request_perform(UNUSED rlm_rest_t *instance, UNUSED rlm_rest_section_t
  * @param[in] handle to use.
  * @return 0 on success or -1 on error.
  */
-int rest_request_decode(rlm_rest_t *instance, UNUSED rlm_rest_section_t *section,
-                       REQUEST *request, void *handle)
+int rest_response_decode(rlm_rest_t *instance, UNUSED rlm_rest_section_t *section,
+                        REQUEST *request, void *handle)
 {
        rlm_rest_handle_t       *randle = handle;
        rlm_rest_curl_context_t *ctx = randle->ctx;
 
        int ret = -1;   /* -Wsometimes-uninitialized */
 
-       if (!ctx->write.buffer) {
+       if (!ctx->response.buffer) {
                RDEBUG2("Skipping attribute processing, no valid body data received");
                return ret;
        }
 
        RDEBUG3("Processing body");
 
-       switch (ctx->write.type) {
+       switch (ctx->response.type) {
        case HTTP_BODY_NONE:
                return 0;
 
        case HTTP_BODY_POST:
-               ret = rest_decode_post(instance, section, request, handle, ctx->write.buffer, ctx->write.used);
+               ret = rest_decode_post(instance, section, request, handle, ctx->response.buffer, ctx->response.used);
                break;
 
 #ifdef HAVE_JSON
        case HTTP_BODY_JSON:
-               ret = rest_decode_json(instance, section, request, handle, ctx->write.buffer, ctx->write.used);
+               ret = rest_decode_json(instance, section, request, handle, ctx->response.buffer, ctx->response.used);
                break;
 #endif
 
@@ -2076,7 +2076,7 @@ int rest_request_decode(rlm_rest_t *instance, UNUSED rlm_rest_section_t *section
  * Resets all options associated with a CURL handle, and frees any headers
  * associated with it.
  *
- * Calls rest_read_ctx_free and rest_write_free to free any memory used by
+ * Calls rest_read_ctx_free and rest_response_free to free any memory used by
  * context data.
  *
  * @param[in] instance configuration data.
@@ -2110,7 +2110,7 @@ void rest_request_cleanup(UNUSED rlm_rest_t *instance, UNUSED rlm_rest_section_t
        /*
         *  Free other context info
         */
-       rest_write_free(&ctx->write);
+       rest_response_free(&ctx->response);
 }
 
 /** URL encodes a string.
@@ -2143,12 +2143,12 @@ static size_t rest_uri_escape(UNUSED REQUEST *request, char *out, size_t outlen,
  *
  * @param[out] out Where to write the pointer to the new buffer containing the escaped URI.
  * @param[in] instance configuration data.
- * @param[in] section configuration data.
+ * @param[in] uri configuration data.
  * @param[in] request Current request
  * @return length of data written to buffer (excluding NULL) or < 0 if an error
  *     occurred.
  */
-ssize_t rest_uri_build(char **out, UNUSED rlm_rest_t *instance, rlm_rest_section_t *section, REQUEST *request)
+ssize_t rest_uri_build(char **out, UNUSED rlm_rest_t *instance, REQUEST *request, char const *uri)
 {
        char const *p;
        char *path_exp = NULL;
@@ -2158,7 +2158,7 @@ ssize_t rest_uri_build(char **out, UNUSED rlm_rest_t *instance, rlm_rest_section
 
        ssize_t len, outlen;
 
-       p = section->uri;
+       p = uri;
 
        /*
         *  All URLs must contain at least <scheme>://<server>/
@@ -2174,15 +2174,15 @@ ssize_t rest_uri_build(char **out, UNUSED rlm_rest_t *instance, rlm_rest_section
                goto malformed;
        }
 
-       len = (p - section->uri);
+       len = (p - uri);
 
        /*
         *  Allocate a temporary buffer to hold the first part of the URI
         */
        scheme = talloc_array(request, char, len + 1);
-       strlcpy(scheme, section->uri, len + 1);
+       strlcpy(scheme, uri, len + 1);
 
-       path = (section->uri + len);
+       path = (uri + len);
 
        len = radius_axlat(out, request, scheme, NULL, NULL);
        talloc_free(scheme);
index 2c17ca8..89bf0e6 100644 (file)
@@ -170,7 +170,7 @@ typedef enum {
 /*
  *     Outbound data context (passed to CURLOPT_READFUNCTION as CURLOPT_READDATA)
  */
-typedef struct rlm_rest_read_t {
+typedef struct rlm_rest_request_t {
        rlm_rest_t      *instance;
        REQUEST         *request;
        read_state_t    state;
@@ -178,13 +178,13 @@ typedef struct rlm_rest_read_t {
        vp_cursor_t     cursor;
 
        unsigned int    chunk;
-} rlm_rest_read_t;
+} rlm_rest_request_t;
 
 /*
  *     Curl inbound data context (passed to CURLOPT_WRITEFUNCTION and
  *     CURLOPT_HEADERFUNCTION as CURLOPT_WRITEDATA and CURLOPT_HEADERDATA)
  */
-typedef struct rlm_rest_write_t {
+typedef struct rlm_rest_response_t {
        rlm_rest_t       *instance;
        REQUEST          *request;
        write_state_t    state;
@@ -195,7 +195,7 @@ typedef struct rlm_rest_write_t {
 
        int              code;          /* HTTP Status Code */
        http_body_type_t type;          /* HTTP Content Type */
-} rlm_rest_write_t;
+} rlm_rest_response_t;
 
 /*
  *     Curl context data
@@ -203,8 +203,8 @@ typedef struct rlm_rest_write_t {
 typedef struct rlm_rest_curl_context_t {
        struct curl_slist       *headers;
        char                    *body;
-       rlm_rest_read_t         read;
-       rlm_rest_write_t        write;
+       rlm_rest_request_t      request;
+       rlm_rest_response_t     response;
 } rlm_rest_curl_context_t;
 
 /*
@@ -248,18 +248,18 @@ int rest_request_perform(rlm_rest_t *instance,
                         rlm_rest_section_t *section, REQUEST *request,
                         void *handle);
 
-int rest_request_decode(rlm_rest_t *instance,
+int rest_response_decode(rlm_rest_t *instance,
                        UNUSED rlm_rest_section_t *section, REQUEST *request,
                        void *handle);
 
 void rest_request_cleanup(rlm_rest_t *instance, rlm_rest_section_t *section,
                          void *handle);
 
-#define rest_get_handle_code(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->write.code)
+#define rest_get_handle_code(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.code)
 
-#define rest_get_handle_type(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->write.type)
+#define rest_get_handle_type(handle)(((rlm_rest_curl_context_t*)((rlm_rest_handle_t*)handle)->ctx)->response.type)
 
 /*
  *     Helper functions
  */
-ssize_t rest_uri_build(char **out, rlm_rest_t *instance, rlm_rest_section_t *section, REQUEST *request);
+ssize_t rest_uri_build(char **out, rlm_rest_t *instance, REQUEST *request, char const *uri);
index e2c2138..509d9e3 100644 (file)
@@ -102,7 +102,7 @@ static int rlm_rest_perform(rlm_rest_t *instance, rlm_rest_section_t *section, v
         *  Build xlat'd URI, this allows REST servers to be specified by
         *  request attributes.
         */
-       uri_len = rest_uri_build(&uri, instance, section, request);
+       uri_len = rest_uri_build(&uri, instance, request, section->uri);
        if (uri_len <= 0) return -1;
 
        RDEBUG("Sending HTTP %s to \"%s\"", fr_int2str(http_method_table, section->method, NULL), uri);
@@ -131,116 +131,6 @@ static void rlm_rest_cleanup(rlm_rest_t *instance, rlm_rest_section_t *section,
        rest_request_cleanup(instance, section, handle);
 };
 
-static int parse_sub_section(CONF_SECTION *parent, rlm_rest_section_t *config, rlm_components_t comp)
-{
-       CONF_SECTION *cs;
-
-       char const *name = section_type_value[comp].section;
-
-       cs = cf_section_sub_find(parent, name);
-       if (!cs) {
-               /* TODO: Should really setup section with default values */
-               return 0;
-       }
-
-       if (cf_section_parse(cs, config, section_config) < 0) {
-               return -1;
-       }
-
-       /*
-        *  Add section name (Maybe add to headers later?).
-        */
-       config->name = name;
-
-       /*
-        *  Sanity check
-        */
-        if ((config->username && !config->password) || (!config->username && config->password)) {
-               cf_log_err_cs(cs, "'username' and 'password' must both be set or both be absent");
-
-               return -1;
-        }
-
-       /*
-        *  Convert HTTP method auth and body type strings into their integer equivalents.
-        */
-       config->auth = fr_str2int(http_auth_table, config->auth_str, HTTP_AUTH_UNKNOWN);
-       if (config->auth == HTTP_AUTH_UNKNOWN) {
-               cf_log_err_cs(cs, "Unknown HTTP auth type '%s'", config->auth_str);
-               return -1;
-       } else if ((config->auth != HTTP_AUTH_NONE) && !http_curl_auth[config->auth]) {
-               cf_log_err_cs(cs, "Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build "
-                             "configuration, then recompile this module", config->auth_str);
-
-               return -1;
-       }
-
-       config->method = fr_str2int(http_method_table, config->method_str, HTTP_METHOD_CUSTOM);
-       config->body = fr_str2int(http_body_type_table, config->body_str, HTTP_BODY_UNKNOWN);
-
-       if (config->body == HTTP_BODY_UNKNOWN) {
-               cf_log_err_cs(cs, "Unknown HTTP body type '%s'", config->body_str);
-               return -1;
-       }
-
-       if (http_body_type_supported[config->body] == HTTP_BODY_UNSUPPORTED) {
-               cf_log_err_cs(cs, "Unsupported HTTP body type \"%s\", please submit patches", config->body_str);
-               return -1;
-       }
-
-       return 1;
-}
-
-/*
- *     Do any per-module initialization that is separate to each
- *     configured instance of the module.  e.g. set up connections
- *     to external databases, read configuration files, set up
- *     dictionary entries, etc.
- *
- *     If configuration information is given in the config section
- *     that must be referenced in later calls, store a handle to it
- *     in *instance otherwise put a null pointer there.
- */
-static int mod_instantiate(CONF_SECTION *conf, void *instance)
-{
-       rlm_rest_t *inst = instance;
-       char const *xlat_name;
-
-       xlat_name = cf_section_name2(conf);
-       if (!xlat_name) {
-               xlat_name = cf_section_name1(conf);
-       }
-
-       inst->xlat_name = xlat_name;
-
-       /*
-        *      Parse sub-section configs.
-        */
-       if (
-               (parse_sub_section(conf, &inst->authorize, RLM_COMPONENT_AUTZ) < 0) ||
-               (parse_sub_section(conf, &inst->authenticate, RLM_COMPONENT_AUTH) < 0) ||
-               (parse_sub_section(conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) ||
-               (parse_sub_section(conf, &inst->checksimul, RLM_COMPONENT_SESS) < 0) ||
-               (parse_sub_section(conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0))
-       {
-               return -1;
-       }
-
-       /*
-        *      Initialise REST libraries.
-        */
-       if (rest_init(inst) < 0) {
-               return -1;
-       }
-
-       inst->conn_pool = fr_connection_pool_init(conf, inst, mod_conn_create, mod_conn_alive, mod_conn_delete, NULL);
-       if (!inst->conn_pool) {
-               return -1;
-       }
-
-       return 0;
-}
-
 /*
  *     Find the named user in this modules database.  Create the set
  *     of attribute-value pairs to check and reply with for this user
@@ -281,7 +171,7 @@ static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
                /*
                 *      Attempt to parse content if there was any.
                 */
-               ret = rest_request_decode(inst, section, request, handle);
+               ret = rest_response_decode(inst, section, request, handle);
                if (ret < 0) {
                        rcode = RLM_MODULE_FAIL;
                        break;
@@ -299,7 +189,7 @@ static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
                 *      Attempt to parse content if there was any.
                 */
                if ((hcode >= 200) && (hcode < 300)) {
-                       ret = rest_request_decode(inst, section, request, handle);
+                       ret = rest_response_decode(inst, section, request, handle);
                        if (ret < 0)       rcode = RLM_MODULE_FAIL;
                        else if (ret == 0) rcode = RLM_MODULE_OK;
                        else               rcode = RLM_MODULE_UPDATED;
@@ -374,7 +264,7 @@ static rlm_rcode_t mod_authenticate(void *instance, UNUSED REQUEST *request)
                /*
                 *      Attempt to parse content if there was any.
                 */
-               ret = rest_request_decode(inst, section, request, handle);
+               ret = rest_response_decode(inst, section, request, handle);
                if (ret < 0) {
                        rcode = RLM_MODULE_FAIL;
                        break;
@@ -392,7 +282,7 @@ static rlm_rcode_t mod_authenticate(void *instance, UNUSED REQUEST *request)
                 *      Attempt to parse content if there was any.
                 */
                if ((hcode >= 200) && (hcode < 300)) {
-                       ret = rest_request_decode(inst, section, request, handle);
+                       ret = rest_response_decode(inst, section, request, handle);
                        if (ret < 0)       rcode = RLM_MODULE_FAIL;
                        else if (ret == 0) rcode = RLM_MODULE_OK;
                        else               rcode = RLM_MODULE_UPDATED;
@@ -441,7 +331,7 @@ static rlm_rcode_t mod_accounting(void *instance, UNUSED REQUEST *request)
        } else if (hcode == 204) {
                rcode = RLM_MODULE_OK;
        } else if ((hcode >= 200) && (hcode < 300)) {
-               ret = rest_request_decode(inst, section, request, handle);
+               ret = rest_response_decode(inst, section, request, handle);
                if (ret < 0)       rcode = RLM_MODULE_FAIL;
                else if (ret == 0) rcode = RLM_MODULE_OK;
                else               rcode = RLM_MODULE_UPDATED;
@@ -458,6 +348,116 @@ static rlm_rcode_t mod_accounting(void *instance, UNUSED REQUEST *request)
        return rcode;
 }
 
+static int parse_sub_section(CONF_SECTION *parent, rlm_rest_section_t *config, rlm_components_t comp)
+{
+       CONF_SECTION *cs;
+
+       char const *name = section_type_value[comp].section;
+
+       cs = cf_section_sub_find(parent, name);
+       if (!cs) {
+               /* TODO: Should really setup section with default values */
+               return 0;
+       }
+
+       if (cf_section_parse(cs, config, section_config) < 0) {
+               return -1;
+       }
+
+       /*
+        *  Add section name (Maybe add to headers later?).
+        */
+       config->name = name;
+
+       /*
+        *  Sanity check
+        */
+        if ((config->username && !config->password) || (!config->username && config->password)) {
+               cf_log_err_cs(cs, "'username' and 'password' must both be set or both be absent");
+
+               return -1;
+        }
+
+       /*
+        *  Convert HTTP method auth and body type strings into their integer equivalents.
+        */
+       config->auth = fr_str2int(http_auth_table, config->auth_str, HTTP_AUTH_UNKNOWN);
+       if (config->auth == HTTP_AUTH_UNKNOWN) {
+               cf_log_err_cs(cs, "Unknown HTTP auth type '%s'", config->auth_str);
+               return -1;
+       } else if ((config->auth != HTTP_AUTH_NONE) && !http_curl_auth[config->auth]) {
+               cf_log_err_cs(cs, "Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build "
+                             "configuration, then recompile this module", config->auth_str);
+
+               return -1;
+       }
+
+       config->method = fr_str2int(http_method_table, config->method_str, HTTP_METHOD_CUSTOM);
+       config->body = fr_str2int(http_body_type_table, config->body_str, HTTP_BODY_UNKNOWN);
+
+       if (config->body == HTTP_BODY_UNKNOWN) {
+               cf_log_err_cs(cs, "Unknown HTTP body type '%s'", config->body_str);
+               return -1;
+       }
+
+       if (http_body_type_supported[config->body] == HTTP_BODY_UNSUPPORTED) {
+               cf_log_err_cs(cs, "Unsupported HTTP body type \"%s\", please submit patches", config->body_str);
+               return -1;
+       }
+
+       return 1;
+}
+
+/*
+ *     Do any per-module initialization that is separate to each
+ *     configured instance of the module.  e.g. set up connections
+ *     to external databases, read configuration files, set up
+ *     dictionary entries, etc.
+ *
+ *     If configuration information is given in the config section
+ *     that must be referenced in later calls, store a handle to it
+ *     in *instance otherwise put a null pointer there.
+ */
+static int mod_instantiate(CONF_SECTION *conf, void *instance)
+{
+       rlm_rest_t *inst = instance;
+       char const *xlat_name;
+
+       xlat_name = cf_section_name2(conf);
+       if (!xlat_name) {
+               xlat_name = cf_section_name1(conf);
+       }
+
+       inst->xlat_name = xlat_name;
+
+       /*
+        *      Parse sub-section configs.
+        */
+       if (
+               (parse_sub_section(conf, &inst->authorize, RLM_COMPONENT_AUTZ) < 0) ||
+               (parse_sub_section(conf, &inst->authenticate, RLM_COMPONENT_AUTH) < 0) ||
+               (parse_sub_section(conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) ||
+               (parse_sub_section(conf, &inst->checksimul, RLM_COMPONENT_SESS) < 0) ||
+               (parse_sub_section(conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0))
+       {
+               return -1;
+       }
+
+       /*
+        *      Initialise REST libraries.
+        */
+       if (rest_init(inst) < 0) {
+               return -1;
+       }
+
+       inst->conn_pool = fr_connection_pool_init(conf, inst, mod_conn_create, mod_conn_alive, mod_conn_delete, NULL);
+       if (!inst->conn_pool) {
+               return -1;
+       }
+
+       return 0;
+}
+
 /*
  *     Only free memory we allocated.  The strings allocated via
  *     cf_section_parse() do not need to be freed.