aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosé Bollo <jose.bollo@iot.bzh>2016-04-06 19:24:02 +0200
committerJosé Bollo <jose.bollo@iot.bzh>2016-04-06 19:24:02 +0200
commitc0453c34a58aac8150300ab829149a0ca4d9e5ee (patch)
tree615f1fc4efe819af7d0518c7cdddf754dfb62b87
parente6298876fdbf457b6dd61556472060a9fa652c82 (diff)
upload of files
Change-Id: Ifbe226ddc11f67223b4215db66af1ad1108a11f5 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
-rw-r--r--plugins/samples/CMakeLists.txt10
-rw-r--r--plugins/samples/SamplePost.c143
-rw-r--r--src/afb-hreq.c39
-rw-r--r--src/afb-hsrv.c7
-rw-r--r--test/sample-post.html13
5 files changed, 119 insertions, 93 deletions
diff --git a/plugins/samples/CMakeLists.txt b/plugins/samples/CMakeLists.txt
index 24ffd91b..c3c305ca 100644
--- a/plugins/samples/CMakeLists.txt
+++ b/plugins/samples/CMakeLists.txt
@@ -6,11 +6,11 @@ TARGET_LINK_LIBRARIES(helloWorld-api ${link_libraries})
INSTALL(TARGETS helloWorld-api
LIBRARY DESTINATION ${plugin_install_dir})
-#ADD_LIBRARY(samplePost-api MODULE SamplePost.c)
-#SET_TARGET_PROPERTIES(samplePost-api PROPERTIES PREFIX "")
-#TARGET_LINK_LIBRARIES(samplePost-api ${link_libraries})
-#INSTALL(TARGETS samplePost-api
-# LIBRARY DESTINATION ${plugin_install_dir})
+ADD_LIBRARY(samplePost-api MODULE SamplePost.c)
+SET_TARGET_PROPERTIES(samplePost-api PROPERTIES PREFIX "")
+TARGET_LINK_LIBRARIES(samplePost-api ${link_libraries})
+INSTALL(TARGETS samplePost-api
+ LIBRARY DESTINATION ${plugin_install_dir})
ADD_LIBRARY(clientCtx-api MODULE ClientCtx.c)
SET_TARGET_PROPERTIES(clientCtx-api PROPERTIES PREFIX "")
diff --git a/plugins/samples/SamplePost.c b/plugins/samples/SamplePost.c
index 24ee5385..aab54e91 100644
--- a/plugins/samples/SamplePost.c
+++ b/plugins/samples/SamplePost.c
@@ -16,106 +16,99 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <json.h>
-#include "local-def.h"
+#include "afb-plugin.h"
+#include "afb-req-itf.h"
+
+
+static int fillargs(json_object *args, struct afb_arg arg)
+{
+ json_object *obj;
+
+ obj = json_object_new_object();
+ json_object_object_add (obj, "value", json_object_new_string(arg.value));
+ json_object_object_add (obj, "size", json_object_new_int64((int64_t)arg.size));
+ json_object_object_add (obj, "is_file", json_object_new_boolean(arg.is_file));
+ json_object_object_add (args, arg.name && *arg.name ? arg.name : "<empty-string>", obj);
+ return 1; /* continue to iterate */
+}
// Sample Generic Ping Debug API
-static json_object* getPingTest(AFB_request *request) {
+static void getPingTest(struct afb_req request)
+{
static int pingcount = 0;
- json_object *response;
- char query [8000];
- int len;
-
- // request all query key/value
- len = getQueryAll (request, query, sizeof(query));
- if (len == 0) strncpy (query, "NoSearchQueryList", sizeof(query));
-
- // return response to caller
- response = jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon count=%d uuid=%s query={%s}"
- , pingcount++, request->uuid, query);
- return (response);
+ json_object *query;
+
+ query = json_object_new_object();
+ afb_req_iterate(request, (void*)fillargs, query);
+
+ afb_req_success_f(request, query, "Ping Binder Daemon count=%d", ++pingcount);
}
// With content-type=json data are directly avaliable in request->post->data
-STATIC json_object* GetJsonByPost (AFB_request *request) {
+static void GetJsonByPost (struct afb_req request)
+{
json_object* jresp;
- char query [8000];
- int len;
-
- // Get all query string [Note real app should probably use value=getQueryValue(request,"key")]
- len = getQueryAll (request, query, sizeof(query));
- if (len == 0) strncpy (query, "NoSearchQueryList", sizeof(query));
-
- // for debug/test return response to caller
- jresp = jsonNewMessage(AFB_SUCCESS, "GetJsonByPost query={%s}", query);
-
- return (jresp);
-}
+ json_object *query;
+ struct afb_arg arg;
+ query = json_object_new_object();
+ afb_req_iterate(request, (void*)fillargs, query);
+ arg = afb_req_get(request, "");
+ jresp = arg.value ? json_tokener_parse(arg.value) : NULL;
+ afb_req_success_f(request, jresp, "GetJsonByPost query={%s}", json_object_to_json_string(query));
+}
+
+// Upload a file and execute a function when upload is done
+static void Uploads (struct afb_req request, const char *destination)
+{
+ afb_req_fail_f(request, "unimplemented", "destination: %s", destination);
+}
// Upload a file and execute a function when upload is done
-STATIC json_object* UploadAppli (AFB_request *request, AFB_PostItem *item) {
-
- char *destination = "applications";
-
- // This is called after PostForm and then after DonePostForm
- if (item == NULL) {
- // Do something intelligent here to install application
- request->errcode = MHD_HTTP_OK; // or error is something went wrong;
- request->jresp = jsonNewMessage(AFB_SUCCESS,"UploadFile Post Appli=%s done", getPostPath (request));
- // Note: should not return here in order getPostedFile to clear Post resources.
- }
-
- // upload multi iteration logic is handle by getPostedFile
- return (getPostFile (request, item, destination));
+static void UploadAppli (struct afb_req request)
+{
+ Uploads(request, "applications");
}
// Simples Upload case just upload a file
-STATIC json_object* UploadMusic (AFB_request *request, AFB_PostItem *item) {
-
- // upload multi iteration logic is handle by getPostedFile
- return (getPostFile (request, item, "musics"));
+static void UploadMusic (struct afb_req request)
+{
+ Uploads(request, "musics");
}
// PostForm callback is called multiple times (one or each key within form, or once per file buffer)
// When file has been fully uploaded call is call with item==NULL
-STATIC json_object* UploadImage (AFB_request *request, AFB_PostItem *item) {
-
- // note if directory is relative it will be prefixed by request->config->sessiondir
- char *destination = "images";
-
- // This is called after PostForm and then after DonePostForm
- if (item == NULL && getPostPath (request) != NULL) {
- // Do something with your newly upload filepath=postFileCtx->path
- request->errcode = MHD_HTTP_OK;
- request->jresp = jsonNewMessage(AFB_SUCCESS,"UploadFile Post Image done");
-
- // Note: should not return here in order getPostedFile to clear Post resources.
- }
-
- // upload multi iteration logic is handle by getPostedFile
- return (getPostFile (request, item, destination));
+static void UploadImage (struct afb_req request)
+{
+ Uploads(request, "images");
}
// NOTE: this sample does not use session to keep test a basic as possible
// in real application upload-xxx should be protected with AFB_SESSION_CHECK
-STATIC AFB_restapi pluginApis[]= {
- {"ping" , AFB_SESSION_NONE , (AFB_apiCB)getPingTest ,"Ping Rest Test Service"},
- {"upload-json" , AFB_SESSION_NONE , (AFB_apiCB)GetJsonByPost ,"Demo for Json Buffer on Post"},
- {"upload-image" , AFB_SESSION_NONE , (AFB_apiCB)UploadImage ,"Demo for file upload"},
- {"upload-music" , AFB_SESSION_NONE , (AFB_apiCB)UploadMusic ,"Demo for file upload"},
- {"upload-appli" , AFB_SESSION_NONE , (AFB_apiCB)UploadAppli ,"Demo for file upload"},
+static const struct AFB_restapi pluginApis[]= {
+ {"ping" , AFB_SESSION_NONE , getPingTest ,"Ping Rest Test Service"},
+ {"upload-json" , AFB_SESSION_NONE , GetJsonByPost ,"Demo for Json Buffer on Post"},
+ {"upload-image" , AFB_SESSION_NONE , UploadImage ,"Demo for file upload"},
+ {"upload-music" , AFB_SESSION_NONE , UploadMusic ,"Demo for file upload"},
+ {"upload-appli" , AFB_SESSION_NONE , UploadAppli ,"Demo for file upload"},
{NULL}
};
-PUBLIC AFB_plugin *pluginRegister () {
- AFB_plugin *plugin = malloc (sizeof (AFB_plugin));
- plugin->type = AFB_PLUGIN_JSON;
- plugin->info = "Sample with Post Upload Files";
- plugin->prefix= "post"; // url base
- plugin->apis = pluginApis;
-
- return (plugin);
+static const struct AFB_plugin plugin_desc = {
+ .type = AFB_PLUGIN_JSON,
+ .info = "Sample with Post Upload Files",
+ .prefix = "post",
+ .apis = pluginApis
+};
+
+const struct AFB_plugin *pluginRegister (const struct AFB_interface *itf)
+{
+ return &plugin_desc;
};
diff --git a/src/afb-hreq.c b/src/afb-hreq.c
index 474b90e8..7c481e95 100644
--- a/src/afb-hreq.c
+++ b/src/afb-hreq.c
@@ -447,9 +447,29 @@ int afb_hreq_post_add(struct afb_hreq *hreq, const char *key, const char *data,
int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *file, const char *data, size_t size)
{
+ ssize_t sz;
struct hreq_data *hdat = get_data(hreq, key, 1);
- /* continuation with reopening */
+ if (hdat->value == NULL) {
+ hdat->file = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600);
+ if (hdat->file == 0) {
+ hdat->file = dup(0);
+ close(0);
+ }
+ if (hdat->file <= 0) {
+ hdat->file = 0;
+ return 0;
+ }
+ hdat->value = strdup(file);
+ if (hdat->value == NULL) {
+ close(hdat->file);
+ hdat->file = 0;
+ return 0;
+ }
+ } else {
+ if (strcmp(hdat->value, file))
+ return 0;
+ }
if (hdat->file < 0) {
hdat->file = open(hdat->value, O_WRONLY|O_APPEND);
if (hdat->file == 0) {
@@ -459,15 +479,16 @@ int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *f
if (hdat->file <= 0)
return 0;
}
- if (hdat->file > 0) {
- write(hdat->file, data, size);
- return 1;
+ while (size) {
+ sz = write(hdat->file, data, size);
+ if (sz >= 0) {
+ hdat->length += (size_t)sz;
+ size -= (size_t)sz;
+ data += sz;
+ } else if (errno != EINTR)
+ return 0;
}
-
- /* creation */
- /* TODO */
- return 0;
-
+ return 1;
}
int afb_hreq_is_argument_a_file(struct afb_hreq *hreq, const char *key)
diff --git a/src/afb-hsrv.c b/src/afb-hsrv.c
index 977aea63..afe865f7 100644
--- a/src/afb-hsrv.c
+++ b/src/afb-hsrv.c
@@ -56,6 +56,12 @@ struct afb_diralias {
int dirfd;
};
+struct afb_hsrv {
+ struct MHD_Daemon *httpd;
+ struct afb_hsrv_handler *handlers;
+ struct upoll *upoll;
+};
+
static struct upoll *upoll = NULL;
static struct afb_hsrv_handler *new_handler(
@@ -303,6 +309,7 @@ static int access_handler(
hreq->postform = MHD_create_post_processor (connection, 65500, postproc, hreq);
if (hreq->postform == NULL)
goto internal_error;
+ return MHD_YES;
} else if (strcasestr(type, JSON_CONTENT) == NULL) {
afb_hsrv_reply_error(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE);
return MHD_YES;
diff --git a/test/sample-post.html b/test/sample-post.html
index c9decdcb..337df97b 100644
--- a/test/sample-post.html
+++ b/test/sample-post.html
@@ -3,8 +3,13 @@
<title>Sample Post test</title>
<body>
<h1>Sample Post test</h1>
+ <form enctype="multipart/form-data">
+ <input type="file" name="file" />
+ <input type="hidden" name="hidden" value="bollobollo" />
<ol>
- <li><a href="api/post/upload-json">upload json</a>
- <li><a href="api/post/upload-image">upload json</a>
- <li><a href="api/post/upload-music">upload json</a>
- <li><a href="api/post/upload-appli">upload json</a>
+ <li><button formmethod="POST" formaction="api/post/ping">ping</button>
+ <li><button formmethod="POST" formaction="api/post/upload-json">upload json</button>
+ <li><button formmethod="POST" formaction="api/post/upload-image">upload image</button>
+ <li><button formmethod="POST" formaction="api/post/upload-music">upload music</button>
+ <li><button formmethod="POST" formaction="api/post/upload-appli">upload application</button>
+ </form>