mirror of
https://github.com/openshwprojects/OpenBK7231T_App.git
synced 2026-02-10 04:25:49 +00:00
add json parser?
This commit is contained in:
@ -73,8 +73,10 @@ static void tcp_client_thread( beken_thread_arg_t arg )
|
||||
// returns length to be sent if any
|
||||
request.received[request.receivedLen] = 0;
|
||||
int lenret = HTTP_ProcessPacket(&request);
|
||||
addLog( "TCP sending reply len %i\n",lenret );
|
||||
send( fd, reply, lenret, 0 );
|
||||
if (lenret > 0){
|
||||
addLog( "TCP sending reply len %i\n",lenret );
|
||||
send( fd, reply, lenret, 0 );
|
||||
}
|
||||
|
||||
rtos_delay_milliseconds(10);
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ Connection: keep-alive
|
||||
const char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ; // HTTP header
|
||||
const char httpMimeTypeHTML[] = "text/html" ; // HTML MIME type
|
||||
const char httpMimeTypeText[] = "text/plain" ; // TEXT MIME type
|
||||
const char httpMimeTypeJson[] = "application/json" ; // TEXT MIME type
|
||||
const char htmlHeader[] = "<!DOCTYPE html><html><body>" ;
|
||||
const char htmlEnd[] = "</body></html>" ;
|
||||
const char htmlReturnToMenu[] = "<a href=\"index\">Return to menu</a>";;
|
||||
@ -61,8 +62,8 @@ const char httpCorsHeaders[] = "Access-Control-Allow-Origin: *\r\nAccess-Control
|
||||
|
||||
const char *methodNames[] = {
|
||||
"GET",
|
||||
"POST",
|
||||
"PUT",
|
||||
"POST",
|
||||
"OPTIONS"
|
||||
};
|
||||
|
||||
@ -110,6 +111,18 @@ int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callbac
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_strnicmp(char *a, char *b, int len){
|
||||
int i;
|
||||
for (i = 0; i < len; i++){
|
||||
char x = *a;
|
||||
char y = *b;
|
||||
if (!x || !y) return 1;
|
||||
if ((x | 0x20) != (y | 0x20)) return 1;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool http_startsWith(const char *base, const char *substr) {
|
||||
while(*substr != 0) {
|
||||
@ -329,7 +342,7 @@ int HTTP_ProcessPacket(http_request_t *request) {
|
||||
char tmpB[64];
|
||||
char tmpC[64];
|
||||
//int bChanged = 0;
|
||||
const char *urlStr = "";
|
||||
char *urlStr = "";
|
||||
|
||||
char *recvbuf = request->received;
|
||||
for (int i = 0; i < sizeof(methodNames)/sizeof(*methodNames); i++){
|
||||
@ -367,6 +380,9 @@ int HTTP_ProcessPacket(http_request_t *request) {
|
||||
printf("invalid request\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
request->url = urlStr;
|
||||
|
||||
// protocol is next, termed by \r\n
|
||||
char *protocol = p;
|
||||
p = strchr(protocol, '\r');
|
||||
@ -379,6 +395,8 @@ int HTTP_ProcessPacket(http_request_t *request) {
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
// i.e. not received
|
||||
request->contentLength = -1;
|
||||
char *headers = p;
|
||||
do {
|
||||
p = strchr(headers, '\r');
|
||||
@ -389,7 +407,7 @@ int HTTP_ProcessPacket(http_request_t *request) {
|
||||
request->numheaders++;
|
||||
}
|
||||
// pick out contentLength
|
||||
if (!strcmp(headers, "Content-Length:")){
|
||||
if (!my_strnicmp(headers, "Content-Length:", 15)){
|
||||
request->contentLength = atoi(headers + 15);
|
||||
}
|
||||
|
||||
@ -436,7 +454,7 @@ int HTTP_ProcessPacket(http_request_t *request) {
|
||||
// look for a callback with this URL and method, or HTTP_ANY
|
||||
for (i = 0; i < numCallbacks; i++){
|
||||
char *url = callbacks[i]->url;
|
||||
if (http_checkUrlBase(urlStr, &url[1])){
|
||||
if (http_startsWith(urlStr, &url[1])){
|
||||
int method = callbacks[i]->method;
|
||||
if(method == HTTP_ANY || method == request->method){
|
||||
return callbacks[i]->callback(request);
|
||||
|
||||
@ -3,10 +3,13 @@
|
||||
extern const char httpHeader[]; // HTTP header
|
||||
extern const char httpMimeTypeHTML[]; // HTML MIME type
|
||||
extern const char httpMimeTypeText[]; // TEXT MIME type
|
||||
extern const char httpMimeTypeJson[];
|
||||
extern const char htmlHeader[];
|
||||
extern const char htmlEnd[];
|
||||
extern const char htmlReturnToMenu[];
|
||||
|
||||
extern const char *htmlPinRoleNames[];
|
||||
|
||||
#define MAX_QUERY 16
|
||||
#define MAX_HEADERS 16
|
||||
typedef struct http_request_tag {
|
||||
|
||||
@ -2,14 +2,19 @@
|
||||
#include "../logging/logging.h"
|
||||
#include "../httpserver/new_http.h"
|
||||
#include "str_pub.h"
|
||||
#include "../new_pins.h"
|
||||
#include "../jsmn/jsmn_h.h"
|
||||
|
||||
static int http_rest_get(http_request_t *request);
|
||||
static int http_rest_post(http_request_t *request);
|
||||
static int http_rest_app(http_request_t *request);
|
||||
|
||||
static int http_rest_post_pins(http_request_t *request);
|
||||
static int http_rest_get_pins(http_request_t *request);
|
||||
|
||||
void init_rest(){
|
||||
HTTP_RegisterCallback( "/api", HTTP_GET, http_rest_get);
|
||||
HTTP_RegisterCallback( "/api", HTTP_POST, http_rest_post);
|
||||
HTTP_RegisterCallback( "/api/", HTTP_GET, http_rest_get);
|
||||
HTTP_RegisterCallback( "/api/", HTTP_POST, http_rest_post);
|
||||
HTTP_RegisterCallback( "/app", HTTP_GET, http_rest_app);
|
||||
}
|
||||
|
||||
@ -54,9 +59,154 @@ static int http_rest_app(http_request_t *request){
|
||||
}
|
||||
|
||||
static int http_rest_get(http_request_t *request){
|
||||
if (!strcmp(request->url, "api/pins")){
|
||||
return http_rest_get_pins(request);
|
||||
}
|
||||
|
||||
http_setup(request, httpMimeTypeHTML);
|
||||
poststr(request, "GET of ");
|
||||
poststr(request, request->url);
|
||||
poststr(request, htmlEnd);
|
||||
poststr(request,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int http_rest_post(http_request_t *request){
|
||||
static int http_rest_get_pins(http_request_t *request){
|
||||
int i;
|
||||
char tmp[20];
|
||||
/*typedef struct pinsState_s {
|
||||
byte roles[32];
|
||||
byte channels[32];
|
||||
} pinsState_t;
|
||||
|
||||
extern pinsState_t g_pins;
|
||||
*/
|
||||
http_setup(request, httpMimeTypeJson);
|
||||
poststr(request, "{\"rolenames\":[");
|
||||
for (i = 0; i < IOR_Total_Options; i++){
|
||||
if (i){
|
||||
sprintf(tmp, ",\"%s\"", htmlPinRoleNames[i]);
|
||||
} else {
|
||||
sprintf(tmp, "\"%s\"", htmlPinRoleNames[i]);
|
||||
}
|
||||
poststr(request, tmp);
|
||||
}
|
||||
poststr(request, "],\"roles\":[");
|
||||
|
||||
for (i = 0; i < 32; i++){
|
||||
if (i){
|
||||
sprintf(tmp, ",%d", g_pins.roles[i]);
|
||||
} else {
|
||||
sprintf(tmp, "%d", g_pins.roles[i]);
|
||||
}
|
||||
poststr(request, tmp);
|
||||
}
|
||||
poststr(request, "],\"channels\":[");
|
||||
for (i = 0; i < 32; i++){
|
||||
if (i){
|
||||
sprintf(tmp, ",%d", g_pins.channels[i]);
|
||||
} else {
|
||||
sprintf(tmp, "%d", g_pins.channels[i]);
|
||||
}
|
||||
poststr(request, tmp);
|
||||
}
|
||||
poststr(request, "]}");
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int http_rest_post(http_request_t *request){
|
||||
char tmp[20];
|
||||
if (!strcmp(request->url, "api/pins")){
|
||||
return http_rest_post_pins(request);
|
||||
}
|
||||
http_setup(request, httpMimeTypeHTML);
|
||||
poststr(request, "POST to ");
|
||||
poststr(request, request->url);
|
||||
poststr(request, "<br/>Content Length:");
|
||||
sprintf(tmp, "%d", request->contentLength);
|
||||
poststr(request, tmp);
|
||||
poststr(request, "<br/>Content:[");
|
||||
poststr(request, request->bodystart);
|
||||
poststr(request, "]<br/>");
|
||||
poststr(request, htmlEnd);
|
||||
poststr(request,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int http_rest_post_pins(http_request_t *request){
|
||||
int i;
|
||||
int r;
|
||||
char tmp[256];
|
||||
|
||||
//https://github.com/zserge/jsmn/blob/master/example/simple.c
|
||||
jsmn_parser p;
|
||||
jsmntok_t t[128]; /* We expect no more than 128 tokens */
|
||||
char *json_str = request->bodystart;
|
||||
int json_len = strlen(json_str);
|
||||
http_setup(request, httpMimeTypeText);
|
||||
|
||||
jsmn_init(&p);
|
||||
r = jsmn_parse(&p, json_str, json_len, t,
|
||||
sizeof(t) / sizeof(t[0]));
|
||||
if (r < 0) {
|
||||
sprintf(tmp,"Failed to parse JSON: %d\n", r);
|
||||
poststr(request, tmp);
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Assume the top-level element is an object */
|
||||
if (r < 1 || t[0].type != JSMN_OBJECT) {
|
||||
sprintf(tmp,"Object expected\n");
|
||||
poststr(request, tmp);
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(tmp,"parsed JSON: %s\n", json_str);
|
||||
poststr(request, tmp);
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
|
||||
|
||||
/* Loop over all keys of the root object */
|
||||
for (i = 1; i < r; i++) {
|
||||
if (jsoneq(json_str, &t[i], "roles") == 0) {
|
||||
int j;
|
||||
sprintf(tmp,"- Roles:\n");
|
||||
poststr(request, tmp);
|
||||
if (t[i + 1].type != JSMN_ARRAY) {
|
||||
continue; /* We expect groups to be an array of strings */
|
||||
}
|
||||
for (j = 0; j < t[i + 1].size; j++) {
|
||||
jsmntok_t *g = &t[i + j + 2];
|
||||
sprintf(tmp," * %.*s\n", g->end - g->start, json_str + g->start);
|
||||
poststr(request, tmp);
|
||||
}
|
||||
i += t[i + 1].size + 1;
|
||||
} else if (jsoneq(json_str, &t[i], "channels") == 0) {
|
||||
int j;
|
||||
sprintf(tmp,"- Channels:\n");
|
||||
poststr(request, tmp);
|
||||
if (t[i + 1].type != JSMN_ARRAY) {
|
||||
continue; /* We expect groups to be an array of strings */
|
||||
}
|
||||
for (j = 0; j < t[i + 1].size; j++) {
|
||||
jsmntok_t *g = &t[i + j + 2];
|
||||
sprintf(tmp," * %.*s\n", g->end - g->start, json_str + g->start);
|
||||
poststr(request, tmp);
|
||||
}
|
||||
i += t[i + 1].size + 1;
|
||||
} else {
|
||||
sprintf(tmp,"Unexpected key: %.*s\n", t[i].end - t[i].start,
|
||||
json_str + t[i].start);
|
||||
poststr(request, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
poststr(request, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
1
src/httpserver/rest_interface.h
Normal file
1
src/httpserver/rest_interface.h
Normal file
@ -0,0 +1 @@
|
||||
void init_rest();
|
||||
Reference in New Issue
Block a user