# variables set like http_proxy.
# | `method` | HTTP method to use, one of 'get', 'post', 'put', 'patch',
# 'delete' or any custom HTTP method.
+ # | `header` | A custom header in the format '<header>: <value>'.
# | `body` | The format of the HTTP body sent to the remote server.
# May be 'none', 'post' or 'json', defaults to 'none'.
# | `data` | Send custom freeform data in the HTTP body. `Content-type`
*/
#define talloc_foreach(_array, _iter) \
for (__typeof__(_array[0]) _iter, *_p = (void *)(_array), *_end = (void *)((_array) + talloc_array_length(_array)); \
- (_p < _end) && (_iter = *((void **)(_p))); \
+ (_p < _end) && (_iter = *((void **)(uintptr_t)(_p))); \
_p = (__typeof__(_p))((__typeof__(_array))_p) + 1)
typedef int(* fr_talloc_free_func_t)(void *fire_ctx, void *uctx);
char const *option = "unknown";
char const *content_type;
- fr_pair_t *header;
- fr_dcursor_t headers;
-
char buffer[512];
fr_assert(candle);
ctx->headers = curl_slist_append(ctx->headers, buffer);
if (!ctx->headers) goto error_header;
- for (header = fr_pair_dcursor_by_da_init(&headers, &request->control_pairs, attr_rest_http_header);
- header;
- header = fr_dcursor_next(&headers)) {
- header = fr_dcursor_remove(&headers);
- if (!strchr(header->vp_strvalue, ':')) {
- RWDEBUG("Invalid HTTP header \"%s\" must be in format '<attribute>: <value>'. Skipping...",
- header->vp_strvalue);
- talloc_free(header);
- continue;
+ /*
+ * Add in the section headers
+ */
+ if (section->headers) {
+ talloc_foreach(section->headers, header) {
+ RINDENT();
+ RDEBUG3("%pV", fr_box_strvalue_buffer(header));
+ REXDENT();
+
+ ctx->headers = curl_slist_append(ctx->headers, header);
}
- RINDENT();
- RDEBUG3("%pV", &header->data);
- REXDENT();
+ }
- ctx->headers = curl_slist_append(ctx->headers, header->vp_strvalue);
- talloc_free(header);
+ /*
+ * Add in dynamic headers from the request
+ */
+ {
+ fr_pair_t *header;
+ fr_dcursor_t headers;
+
+ for (header = fr_pair_dcursor_by_da_init(&headers, &request->control_pairs, attr_rest_http_header);
+ header;
+ header = fr_dcursor_next(&headers)) {
+ header = fr_dcursor_remove(&headers);
+ if (!strchr(header->vp_strvalue, ':')) {
+ RWDEBUG("Invalid HTTP header \"%s\" must be in format '<attribute>: <value>'. Skipping...",
+ header->vp_strvalue);
+ talloc_free(header);
+ continue;
+ }
+ RINDENT();
+ RDEBUG3("%pV", &header->data);
+ REXDENT();
+
+ ctx->headers = curl_slist_append(ctx->headers, header->vp_strvalue);
+ talloc_free(header);
+ }
}
/*
http_body_type_t force_to; //!< Override the Content-Type header in the response
//!< to force decoding as a particular type.
+ char const **headers; //!< Custom headers to set (optional).
char const *data; //!< Custom body data (optional).
bool auth_is_set; //!< Whether a value was provided for auth_str.
{ FR_CONF_OFFSET("uri", FR_TYPE_STRING | FR_TYPE_XLAT, rlm_rest_section_t, uri), .dflt = "" },
{ FR_CONF_OFFSET("proxy", FR_TYPE_STRING, rlm_rest_section_t, proxy), .func = rest_proxy_parse },
{ FR_CONF_OFFSET("method", FR_TYPE_STRING, rlm_rest_section_t, method_str), .dflt = "GET" },
+ { FR_CONF_OFFSET("header", FR_TYPE_STRING | FR_TYPE_MULTI, rlm_rest_section_t, headers) },
{ FR_CONF_OFFSET("body", FR_TYPE_STRING, rlm_rest_section_t, body_str), .dflt = "none" },
{ FR_CONF_OFFSET("data", FR_TYPE_STRING | FR_TYPE_XLAT, rlm_rest_section_t, data) },
{ FR_CONF_OFFSET("force_to", FR_TYPE_STRING, rlm_rest_section_t, force_to_str) },
/* User authentication */
{ FR_CONF_OFFSET_IS_SET("auth", FR_TYPE_VOID, rlm_rest_section_t, auth),
.func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = http_auth_table, .len = &http_auth_table_len }, .dflt = "none" },
+
+ { FR_CONF_OFFSET("header", FR_TYPE_STRING | FR_TYPE_MULTI, rlm_rest_section_t, headers) },
+
{ FR_CONF_OFFSET("username", FR_TYPE_STRING | FR_TYPE_XLAT, rlm_rest_section_t, username) },
{ FR_CONF_OFFSET("password", FR_TYPE_STRING | FR_TYPE_XLAT, rlm_rest_section_t, password) },
{ FR_CONF_OFFSET("require_auth", FR_TYPE_BOOL, rlm_rest_section_t, require_auth), .dflt = "no" },