#include "afb-msg-json.h"
#include "afb-context.h"
#include "afb-hreq.h"
-#include "afb-subcall.h"
#include "afb-session.h"
+#include "afb-cred.h"
#include "verbose.h"
#include "locale-root.h"
#define SIZE_RESPONSE_BUFFER 8192
+static int global_reqids = 0;
+
static char empty_string[] = "";
static const char long_key_for_uuid[] = "x-afb-uuid";
char *path; /* path of the file saved */
};
-static struct json_object *req_json(struct afb_hreq *hreq);
-static struct afb_arg req_get(struct afb_hreq *hreq, const char *name);
-static void req_fail(struct afb_hreq *hreq, const char *status, const char *info);
-static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info);
-static const char *req_raw(struct afb_hreq *hreq, size_t *size);
-static void req_send(struct afb_hreq *hreq, const char *buffer, size_t size);
-static int req_subscribe_unsubscribe_error(struct afb_hreq *hreq, struct afb_event event);
-static void req_subcall(struct afb_hreq *hreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure);
-
-const struct afb_req_itf afb_hreq_req_itf = {
- .json = (void*)req_json,
- .get = (void*)req_get,
- .success = (void*)req_success,
- .fail = (void*)req_fail,
- .raw = (void*)req_raw,
- .send = (void*)req_send,
- .context_get = (void*)afb_context_get,
- .context_set = (void*)afb_context_set,
- .addref = (void*)afb_hreq_addref,
- .unref = (void*)afb_hreq_unref,
- .session_close = (void*)afb_context_close,
- .session_set_LOA = (void*)afb_context_change_loa,
- .subscribe = (void*)req_subscribe_unsubscribe_error,
- .unsubscribe = (void*)req_subscribe_unsubscribe_error,
- .subcall = (void*)req_subcall
+static struct json_object *req_json(struct afb_xreq *xreq);
+static struct afb_arg req_get(struct afb_xreq *xreq, const char *name);
+static void req_fail(struct afb_xreq *xreq, const char *status, const char *info);
+static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info);
+static void req_destroy(struct afb_xreq *xreq);
+
+const struct afb_xreq_query_itf afb_hreq_xreq_query_itf = {
+ .json = req_json,
+ .get = req_get,
+ .success = req_success,
+ .fail = req_fail,
+ .unref = req_destroy
};
static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create)
MHD_add_response_header(response, k, v);
k = va_arg(args, const char *);
}
- v = afb_context_sent_uuid(&hreq->context);
+ v = afb_context_sent_uuid(&hreq->xreq.context);
if (v != NULL && asprintf(&cookie, cookie_setter, v) > 0) {
MHD_add_response_header(response, MHD_HTTP_HEADER_SET_COOKIE, cookie);
free(cookie);
const char *result = NULL;
#if defined(INFER_EXTENSION)
+ /*
+ * Set some well-known extensions
+ * Note that it is mandatory for example for css files in order to provide
+ * right mimetype that must be text/css (otherwise chrome browser will not
+ * load correctly css file) while libmagic returns text/plain.
+ */
const char *extension = strrchr(filename, '.');
if (extension) {
static const char *const known[][2] = {
{ ".js", "text/javascript" },
{ ".html", "text/html" },
{ ".css", "text/css" },
+ { ".ico", "image/x-icon"},
+ { ".png", "image/png" },
+ { ".svg", "image/svg+xml" },
+ { ".ttf", "application/x-font-ttf"},
{ NULL, NULL }
};
int i = 0;
return result;
}
-void afb_hreq_addref(struct afb_hreq *hreq)
-{
- hreq->refcount++;
-}
-
-void afb_hreq_unref(struct afb_hreq *hreq)
+static void req_destroy(struct afb_xreq *xreq)
{
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
struct hreq_data *data;
- if (hreq == NULL || --hreq->refcount)
- return;
-
if (hreq->postform != NULL)
MHD_destroy_post_processor(hreq->postform);
for (data = hreq->data; data; data = hreq->data) {
free(data->value);
free(data);
}
- afb_context_disconnect(&hreq->context);
+ afb_context_disconnect(&hreq->xreq.context);
json_object_put(hreq->json);
+ free((char*)hreq->xreq.api);
+ free((char*)hreq->xreq.verb);
+ afb_cred_unref(hreq->xreq.cred);
free(hreq);
}
+void afb_hreq_addref(struct afb_hreq *hreq)
+{
+ afb_xreq_addref(&hreq->xreq);
+}
+
+void afb_hreq_unref(struct afb_hreq *hreq)
+{
+ afb_xreq_unref(&hreq->xreq);
+}
+
/*
* Removes the 'prefix' of 'length' from the tail of 'hreq'
* if and only if the prefix exists and is terminated by a leading
return !size;
}
-struct afb_req afb_hreq_to_req(struct afb_hreq *hreq)
-{
- return (struct afb_req){ .itf = &afb_hreq_req_itf, .closure = hreq };
-}
-
-static struct afb_arg req_get(struct afb_hreq *hreq, const char *name)
+static struct afb_arg req_get(struct afb_xreq *xreq, const char *name)
{
const char *value;
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
struct hreq_data *hdat = get_data(hreq, name, 0);
if (hdat)
return (struct afb_arg){
return 1;
}
-static struct json_object *req_json(struct afb_hreq *hreq)
+static struct json_object *req_json(struct afb_xreq *xreq)
{
struct hreq_data *hdat;
struct json_object *obj, *val;
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
obj = hreq->json;
if (obj == NULL) {
return obj;
}
-static const char *req_raw(struct afb_hreq *hreq, size_t *size)
-{
- const char *result = json_object_get_string(req_json(hreq));
- *size = result ? strlen(result) : 0;
- return result;
-}
-
-static void req_send(struct afb_hreq *hreq, const char *buffer, size_t size)
-{
- afb_hreq_reply_copy(hreq, MHD_HTTP_OK, size, buffer, NULL);
-}
-
static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)
{
ssize_t len = stpncpy(buf, json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)+pos, max) - buf;
if (reqid == NULL)
reqid = afb_hreq_get_argument(hreq, short_key_for_reqid);
- reply = afb_msg_json_reply(status, info, resp, &hreq->context, reqid);
+ reply = afb_msg_json_reply(status, info, resp, &hreq->xreq.context, reqid);
response = MHD_create_response_from_callback((uint64_t)strlen(json_object_to_json_string_ext(reply, JSON_C_TO_STRING_PLAIN)), SIZE_RESPONSE_BUFFER, (void*)send_json_cb, reply, (void*)json_object_put);
afb_hreq_reply(hreq, retcode, response, NULL);
}
-static void req_fail(struct afb_hreq *hreq, const char *status, const char *info)
+static void req_fail(struct afb_xreq *xreq, const char *status, const char *info)
{
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
req_reply(hreq, MHD_HTTP_OK, status, info, NULL);
}
-static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info)
+static void req_success(struct afb_xreq *xreq, json_object *obj, const char *info)
{
+ struct afb_hreq *hreq = CONTAINER_OF_XREQ(struct afb_hreq, xreq);
req_reply(hreq, MHD_HTTP_OK, "success", info, obj);
}
-static int req_subscribe_unsubscribe_error(struct afb_hreq *hreq, struct afb_event event)
+void afb_hreq_call(struct afb_hreq *hreq, struct afb_apiset *apiset, const char *api, size_t lenapi, const char *verb, size_t lenverb)
{
- errno = EINVAL;
- return -1;
-}
-
-static void req_subcall(struct afb_hreq *hreq, const char *api, const char *verb, struct json_object *args, void (*callback)(void*, int, struct json_object*), void *closure)
-{
- afb_subcall(&hreq->context, api, verb, args, callback, closure, (struct afb_req){ .itf = &afb_hreq_req_itf, .closure = hreq });
+ hreq->xreq.api = strndup(api, lenapi);
+ hreq->xreq.verb = strndup(verb, lenverb);
+ if (hreq->xreq.api == NULL || hreq->xreq.verb == NULL) {
+ ERROR("Out of memory");
+ afb_hreq_reply_error(hreq, MHD_HTTP_INTERNAL_SERVER_ERROR);
+ } else if (afb_hreq_init_context(hreq) < 0) {
+ afb_hreq_reply_error(hreq, MHD_HTTP_INTERNAL_SERVER_ERROR);
+ } else {
+ afb_xreq_addref(&hreq->xreq); /* TODO check if needed */
+ afb_xreq_process(&hreq->xreq, apiset);
+ }
}
int afb_hreq_init_context(struct afb_hreq *hreq)
const char *uuid;
const char *token;
- if (hreq->context.session != NULL)
+ if (hreq->xreq.context.session != NULL)
return 0;
uuid = afb_hreq_get_header(hreq, long_key_for_uuid);
if (token == NULL)
token = afb_hreq_get_argument(hreq, short_key_for_token);
- return afb_context_connect(&hreq->context, uuid, token);
+ return afb_context_connect(&hreq->xreq.context, uuid, token);
}
int afb_hreq_init_cookie(int port, const char *path, int maxage)
return 1;
}
+struct afb_xreq *afb_hreq_to_xreq(struct afb_hreq *hreq)
+{
+ return &hreq->xreq;
+}
+
+struct afb_hreq *afb_hreq_create()
+{
+ struct afb_hreq *hreq = calloc(1, sizeof *hreq);
+ if (hreq) {
+ /* init the request */
+ afb_xreq_init(&hreq->xreq, &afb_hreq_xreq_query_itf);
+ hreq->reqid = ++global_reqids;
+ }
+ return hreq;
+}