mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-31 13:00:49 +00:00
Refactor JSON and RPC API
This commit is contained in:
1 parent
a4b003b7ac
commit
54d6bad5e5
11 files changed
+703
-694
No files matched your search
+25
-27
@@ -28,7 +28,9 @@ static int mg_pass_string(const char *s, int len) {
|
||||
return MG_JSON_INVALID;
|
||||
}
|
||||
|
||||
int mg_json_get(const char *s, int len, const char *path, int *toklen) {
|
||||
int mg_json_get(struct mg_str json, const char *path, int *toklen) {
|
||||
const char *s = json.ptr;
|
||||
int len = (int) json.len;
|
||||
enum { S_VALUE, S_KEY, S_COLON, S_COMMA_OR_EOO } expecting = S_VALUE;
|
||||
unsigned char nesting[MG_JSON_MAX_DEPTH];
|
||||
int i, j = 0, depth = 0;
|
||||
@@ -165,7 +167,7 @@ int mg_json_get(const char *s, int len, const char *path, int *toklen) {
|
||||
|
||||
bool mg_json_get_num(struct mg_str json, const char *path, double *v) {
|
||||
int n, toklen, found = 0;
|
||||
if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 &&
|
||||
if ((n = mg_json_get(json, path, &toklen)) >= 0 &&
|
||||
(json.ptr[n] == '-' || (json.ptr[n] >= '0' && json.ptr[n] <= '9'))) {
|
||||
if (v != NULL) *v = mg_atod(json.ptr + n, toklen, NULL);
|
||||
found = 1;
|
||||
@@ -174,10 +176,9 @@ bool mg_json_get_num(struct mg_str json, const char *path, double *v) {
|
||||
}
|
||||
|
||||
bool mg_json_get_bool(struct mg_str json, const char *path, bool *v) {
|
||||
int n, toklen, found = 0;
|
||||
if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 &&
|
||||
(json.ptr[n] == 't' || json.ptr[n] == 'f')) {
|
||||
if (v != NULL) *v = json.ptr[n] == 't';
|
||||
int found = 0, off = mg_json_get(json, path, NULL);
|
||||
if (off >= 0 && (json.ptr[off] == 't' || json.ptr[off] == 'f')) {
|
||||
if (v != NULL) *v = json.ptr[off] == 't';
|
||||
found = 1;
|
||||
}
|
||||
return found;
|
||||
@@ -209,13 +210,12 @@ static bool json_unescape(const char *s, size_t len, char *to, size_t n) {
|
||||
}
|
||||
|
||||
char *mg_json_get_str(struct mg_str json, const char *path) {
|
||||
int n, toklen;
|
||||
char *result = NULL;
|
||||
if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 &&
|
||||
json.ptr[n] == '"') {
|
||||
if ((result = (char *) calloc(1, (size_t) toklen)) != NULL &&
|
||||
!json_unescape(json.ptr + n + 1, (size_t) (toklen - 2), result,
|
||||
(size_t) toklen)) {
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && len > 1 && json.ptr[off] == '"') {
|
||||
if ((result = (char *) calloc(1, (size_t) len)) != NULL &&
|
||||
!json_unescape(json.ptr + off + 1, (size_t) (len - 2), result,
|
||||
(size_t) len)) {
|
||||
free(result);
|
||||
result = NULL;
|
||||
}
|
||||
@@ -223,27 +223,25 @@ char *mg_json_get_str(struct mg_str json, const char *path) {
|
||||
return result;
|
||||
}
|
||||
|
||||
char *mg_json_get_b64(struct mg_str json, const char *path, int *len) {
|
||||
int n, toklen;
|
||||
char *mg_json_get_b64(struct mg_str json, const char *path, int *slen) {
|
||||
char *result = NULL;
|
||||
if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 &&
|
||||
json.ptr[n] == '"' && toklen > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) toklen)) != NULL) {
|
||||
int k = mg_base64_decode(json.ptr + n + 1, toklen - 2, result);
|
||||
if (len != NULL) *len = k;
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && json.ptr[off] == '"' && len > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) len)) != NULL) {
|
||||
int k = mg_base64_decode(json.ptr + off + 1, len - 2, result);
|
||||
if (slen != NULL) *slen = k;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char *mg_json_get_hex(struct mg_str json, const char *path, int *len) {
|
||||
int n, toklen;
|
||||
char *mg_json_get_hex(struct mg_str json, const char *path, int *slen) {
|
||||
char *result = NULL;
|
||||
if ((n = mg_json_get(json.ptr, (int) json.len, path, &toklen)) >= 0 &&
|
||||
json.ptr[n] == '"' && toklen > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) toklen / 2)) != NULL) {
|
||||
mg_unhex(json.ptr + n + 1, (size_t) (toklen - 2), (uint8_t *) result);
|
||||
result[(toklen - 2) / 2] = '\0';
|
||||
if (len != NULL) *len = (toklen - 2) / 2;
|
||||
int len = 0, off = mg_json_get(json, path, &len);
|
||||
if (off >= 0 && json.ptr[off] == '"' && len > 1 &&
|
||||
(result = (char *) calloc(1, (size_t) len / 2)) != NULL) {
|
||||
mg_unhex(json.ptr + off + 1, (size_t) (len - 2), (uint8_t *) result);
|
||||
result[len / 2 - 1] = '\0';
|
||||
if (slen != NULL) *slen = len / 2 - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
|
||||
// Error return values - negative. Successful returns are >= 0
|
||||
enum { MG_JSON_TOO_DEEP = -1, MG_JSON_INVALID = -2, MG_JSON_NOT_FOUND = -3 };
|
||||
int mg_json_get(const char *buf, int len, const char *path, int *toklen);
|
||||
int mg_json_get(struct mg_str json, const char *path, int *toklen);
|
||||
|
||||
bool mg_json_get_num(struct mg_str json, const char *path, double *v);
|
||||
bool mg_json_get_bool(struct mg_str json, const char *path, bool *v);
|
||||
|
||||
@@ -23,26 +23,25 @@ void mg_rpc_free(void **head) {
|
||||
}
|
||||
}
|
||||
|
||||
void mg_rpc_process(void **head, struct mg_str s, mg_pfn_t pfn, void *pfnd) {
|
||||
struct mg_rpc_req req = {{s.ptr, s.len}, pfn, pfnd, NULL};
|
||||
int len, off = mg_json_get(s.ptr, (int) s.len, "$.method", &len);
|
||||
if (off > 0 && s.ptr[off] == '"') {
|
||||
struct mg_str m = mg_str_n(&s.ptr[off + 1], (size_t) len - 2);
|
||||
struct mg_rpc *h = *(struct mg_rpc **) head;
|
||||
void mg_rpc_process(struct mg_rpc_req *r) {
|
||||
int len, off = mg_json_get(r->frame, "$.method", &len);
|
||||
if (off > 0 && r->frame.ptr[off] == '"') {
|
||||
struct mg_str m = mg_str_n(&r->frame.ptr[off + 1], (size_t) len - 2);
|
||||
struct mg_rpc *h = *(struct mg_rpc **) r->head;
|
||||
while (h != NULL && !mg_match(m, h->method, NULL)) h = h->next;
|
||||
if (h != NULL) {
|
||||
req.fn_data = h->fn_data;
|
||||
h->fn(&req);
|
||||
r->handler_data = h->fn_data;
|
||||
h->fn(r);
|
||||
} else {
|
||||
mg_rpc_err(&req, -32601, "\"%.*s not found\"", (int) m.len, m.ptr);
|
||||
mg_rpc_err(r, -32601, "\"%.*s not found\"", (int) m.len, m.ptr);
|
||||
}
|
||||
} else {
|
||||
mg_rpc_err(&req, -32700, "%.*Q", (int) s.len, s.ptr);
|
||||
mg_rpc_err(r, -32700, "%.*Q", (int) r->frame.len, r->frame.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_rpc_vok(struct mg_rpc_req *r, const char *fmt, va_list *ap) {
|
||||
int len, off = mg_json_get(r->frame.ptr, (int) r->frame.len, "$.id", &len);
|
||||
int len, off = mg_json_get(r->frame, "$.id", &len);
|
||||
if (off > 0) {
|
||||
mg_rprintf(r->pfn, r->pfn_data, "{%Q:%.*s,%Q:", "id", len,
|
||||
&r->frame.ptr[off], "result");
|
||||
@@ -59,7 +58,7 @@ void mg_rpc_ok(struct mg_rpc_req *r, const char *fmt, ...) {
|
||||
}
|
||||
|
||||
void mg_rpc_verr(struct mg_rpc_req *r, int code, const char *fmt, va_list *ap) {
|
||||
int len, off = mg_json_get(r->frame.ptr, (int) r->frame.len, "$.id", &len);
|
||||
int len, off = mg_json_get(r->frame, "$.id", &len);
|
||||
mg_rprintf(r->pfn, r->pfn_data, "{");
|
||||
if (off > 0) {
|
||||
mg_rprintf(r->pfn, r->pfn_data, "%Q:%.*s,", "id", len, &r->frame.ptr[off]);
|
||||
@@ -88,5 +87,5 @@ static size_t print_methods(mg_pfn_t pfn, void *pfn_data, va_list *ap) {
|
||||
}
|
||||
|
||||
void mg_rpc_list(struct mg_rpc_req *r) {
|
||||
mg_rpc_ok(r, "[%M]", print_methods, r->fn_data);
|
||||
mg_rpc_ok(r, "[%M]", print_methods, r->head);
|
||||
}
|
||||
@@ -4,16 +4,18 @@
|
||||
|
||||
// JSON-RPC request descriptor
|
||||
struct mg_rpc_req {
|
||||
struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
|
||||
void **head; // List of all RPC handlers
|
||||
mg_pfn_t pfn; // Response printing function
|
||||
void *pfn_data; // Response printing function data
|
||||
void *fn_data; // Endpoint handler data
|
||||
void *handler_data; // Endpoint handler data
|
||||
void *process_data; // Arbitrary user data
|
||||
struct mg_str frame; // Request, e.g. {"id":1,"method":"add","params":[1,2]}
|
||||
};
|
||||
|
||||
void mg_rpc_add(void **head, struct mg_str method_pattern,
|
||||
void (*handler)(struct mg_rpc_req *), void *handler_data);
|
||||
void mg_rpc_free(void **head);
|
||||
void mg_rpc_process(void **head, struct mg_str json, mg_pfn_t pfn, void *pfnd);
|
||||
void mg_rpc_process(struct mg_rpc_req *);
|
||||
|
||||
// Helper functions to print result or error frame
|
||||
void mg_rpc_ok(struct mg_rpc_req *, const char *fmt, ...);
|
||||
|
||||
Reference in new issue
Block a user