[Olsr-dev] [PATCH] jsoninfo: HTTP headers with CORS (if requested)
Ferry Huberts
(spam-protected)
Sat May 17 16:43:17 CEST 2014
Reviewed-by: Ferry Huberts <(spam-protected)>
thanks for incorporating feedback, push onto master whenever you like.
On 17/05/14 16:37, Alessio Caiazza wrote:
> The new "httpheaders" parameter prepends HTTP headers to the reply.
> If not set it will default to "no" and have the same behaviour as before.
> Cross-origin resource sharing headers (CORS) are included in reply allowing the
> json retrieval by javascript applications not served by olsrd itself.
> This will allow to easily develop js applications running directly in the
> browser.
> ---
> lib/jsoninfo/README_JSONINFO | 8 +++++
> lib/jsoninfo/src/olsrd_jsoninfo.c | 76 +++++++++++++++++++++++++++++++++++++--
> lib/jsoninfo/src/olsrd_jsoninfo.h | 1 +
> lib/jsoninfo/src/olsrd_plugin.c | 17 +++++++++
> 4 files changed, 99 insertions(+), 3 deletions(-)
>
> diff --git a/lib/jsoninfo/README_JSONINFO b/lib/jsoninfo/README_JSONINFO
> index a102a56..4e63859 100644
> --- a/lib/jsoninfo/README_JSONINFO
> +++ b/lib/jsoninfo/README_JSONINFO
> @@ -73,6 +73,14 @@ LoadPlugin "olsrd_jsoninfo.so.0.0"
> # if you set it to 0.0.0.0, it will accept all connections
> #PlParam "accept" "0.0.0.0"
>
> + # The "httpheaders" parameter prepends HTTP headers to the reply.
> + # If not set it will default to "no" and have the same behaviour as before.
> + # Among with a minimal set of headers also Cross-origin resource sharing
> + # headers (CORS) are included in reply allowing the json retrieval by
> + # javascript applications not served by olsrd itself.
> + # You can enable it uncommenting the following line:
> + #PlParam "httpheaders" "yes"
> +
> # specify a UUID for this node to track it for debugging
> #PlParam "UUIDFile" "/etc/olsrd/olsrd.uuid"
> }
> diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.c b/lib/jsoninfo/src/olsrd_jsoninfo.c
> index 9db99b8..db44227 100644
> --- a/lib/jsoninfo/src/olsrd_jsoninfo.c
> +++ b/lib/jsoninfo/src/olsrd_jsoninfo.c
> @@ -96,6 +96,9 @@
>
> static int ipc_socket;
>
> +/* Response types */
> +#define HTTP_200 "HTTP/1.1 200 OK"
> +
> /* IPC initialization function */
> static int plugin_ipc_init(void);
>
> @@ -126,6 +129,18 @@ static void ipc_print_interfaces(struct autobuf *);
> static void ipc_print_plugins(struct autobuf *);
> static void ipc_print_olsrd_conf(struct autobuf *abuf);
>
> +static size_t build_http_header(const char *status, const char *mime,
> + uint32_t msgsize, char *buf, uint32_t bufsize);
> +
> +/*
> + * this is the size of the buffer used for build_http_header
> + * the amount of data written into the buffer will be less than
> + * 400 bytes approximatively.
> + * The size may vary because the Content-Length header contains
> + * the length of the json data
> + */
> +#define MAX_HTTPHEADER_SIZE 512
> +
> #define TXT_IPC_BUFSIZE 256
>
> /* these provide all of the runtime status info */
> @@ -1282,6 +1297,9 @@ static void
> send_info(unsigned int send_what, int the_socket)
> {
> struct autobuf abuf;
> + size_t header_len = 0;
> + char header_buf[MAX_HTTPHEADER_SIZE];
> + const char *content_type = "application/json";
>
> /* global variables for tracking when to put a comma in for JSON */
> entrynumber[0] = 0;
> @@ -1320,12 +1338,17 @@ send_info(unsigned int send_what, int the_socket)
> ipc_print_olsrd_conf(&abuf);
> }
>
> - outbuffer[outbuffer_count] = olsr_malloc(abuf.len, "txt output buffer");
> - outbuffer_size[outbuffer_count] = abuf.len;
> + if(http_headers) {
> + header_len = build_http_header(HTTP_200, content_type, abuf.len, header_buf, sizeof(header_buf));
> + }
> +
> + outbuffer[outbuffer_count] = olsr_malloc(header_len + abuf.len, "json output buffer");
> + outbuffer_size[outbuffer_count] = header_len + abuf.len;
> outbuffer_written[outbuffer_count] = 0;
> outbuffer_socket[outbuffer_count] = the_socket;
>
> - memcpy(outbuffer[outbuffer_count], abuf.buf, abuf.len);
> + memcpy(outbuffer[outbuffer_count], header_buf, header_len);
> + memcpy((outbuffer[outbuffer_count]) + header_len, abuf.buf, abuf.len);
> outbuffer_count++;
>
> if (outbuffer_count == 1) {
> @@ -1340,6 +1363,53 @@ send_info(unsigned int send_what, int the_socket)
> abuf_free(&abuf);
> }
>
> +static size_t
> +build_http_header(const char *status, const char *mime, uint32_t msgsize,
> + char *buf, uint32_t bufsize)
> +{
> + time_t currtime;
> + size_t size;
> +
> + size = snprintf(buf, bufsize, "%s\r\n", status);
> +
> + /* Date */
> + time(&currtime);
> + size += strftime(&buf[size], bufsize - size, "Date: %a, %d %b %Y %H:%M:%S GMT\r\n", localtime(&currtime));
> +
> + /* Server version */
> + size += snprintf(&buf[size], bufsize - size, "Server: OLSRD JSONInfo plugin\r\n");
> +
> + /* connection-type */
> + size += snprintf(&buf[size], bufsize - size, "Connection: closed\r\n");
> +
> + /* MIME type */
> + if(mime != NULL) {
> + size += snprintf(&buf[size], bufsize - size, "Content-type: %s\r\n", mime);
> + }
> +
> + /* CORS data */
> + /**No needs to be strict here, access control is based on source IP*/
> + size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Origin: *\r\n");
> + size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n");
> + size += snprintf(&buf[size], bufsize - size, "Access-Control-Allow-Headers: Accept, Origin, X-Requested-With\r\n");
> + size += snprintf(&buf[size], bufsize - size, "Access-Control-Max-Age: 1728000\r\n");
> +
> + /* Content length */
> + if (msgsize > 0) {
> + size += snprintf(&buf[size], bufsize - size, "Content-length: %i\r\n", msgsize);
> + }
> +
> + /* Cache-control
> + * No caching dynamic pages
> + */
> + size += snprintf(&buf[size], bufsize - size, "Cache-Control: no-cache\r\n");
> +
> + /* End header */
> + size += snprintf(&buf[size], bufsize - size, "\r\n");
> +
> + return size;
> +}
> +
> /*
> * Local Variables:
> * mode: c
> diff --git a/lib/jsoninfo/src/olsrd_jsoninfo.h b/lib/jsoninfo/src/olsrd_jsoninfo.h
> index 8478f62..56acb70 100644
> --- a/lib/jsoninfo/src/olsrd_jsoninfo.h
> +++ b/lib/jsoninfo/src/olsrd_jsoninfo.h
> @@ -62,6 +62,7 @@ extern union olsr_ip_addr jsoninfo_accept_ip;
> extern union olsr_ip_addr jsoninfo_listen_ip;
> extern int ipc_port;
> extern int nompr;
> +extern bool http_headers;
>
> int olsrd_plugin_interface_version(void);
> int olsrd_plugin_init(void);
> diff --git a/lib/jsoninfo/src/olsrd_plugin.c b/lib/jsoninfo/src/olsrd_plugin.c
> index 36550a8..03aa45f 100644
> --- a/lib/jsoninfo/src/olsrd_plugin.c
> +++ b/lib/jsoninfo/src/olsrd_plugin.c
> @@ -64,6 +64,7 @@ union olsr_ip_addr jsoninfo_accept_ip;
> union olsr_ip_addr jsoninfo_listen_ip;
> int ipc_port;
> int nompr;
> +bool http_headers;
>
> static void my_init(void) __attribute__ ((constructor));
> static void my_fini(void) __attribute__ ((destructor));
> @@ -79,6 +80,7 @@ my_init(void)
>
> /* defaults for parameters */
> ipc_port = 9090;
> + http_headers = false;
> if (olsr_cnf->ip_version == AF_INET) {
> jsoninfo_accept_ip.v4.s_addr = htonl(INADDR_LOOPBACK);
> jsoninfo_listen_ip.v4.s_addr = htonl(INADDR_ANY);
> @@ -120,11 +122,26 @@ store_string(const char *value, void *data, set_plugin_parameter_addon addon __a
> return 0;
> }
>
> +static int
> +store_boolean(const char *value, void *data, set_plugin_parameter_addon addon __attribute__ ((unused)))
> +{
> + bool *dest = data;
> + if(strcmp(value, "yes") == 0)
> + *dest = true;
> + else if (strcmp(value, "no") == 0)
> + *dest = false;
> + else
> + return 1; //error
> +
> + return 0;
> +}
> +
> static const struct olsrd_plugin_parameters plugin_parameters[] = {
> {.name = "port",.set_plugin_parameter = &set_plugin_port,.data = &ipc_port},
> {.name = "accept",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_accept_ip},
> {.name = "listen",.set_plugin_parameter = &set_plugin_ipaddress,.data = &jsoninfo_listen_ip},
> {.name = "uuidfile",.set_plugin_parameter = &store_string,.data = uuidfile},
> + {.name = "httpheaders",.set_plugin_parameter = &store_boolean,.data = &http_headers},
> };
>
> void
>
--
Ferry Huberts
More information about the Olsr-dev
mailing list