Skip to content

Commit 9d4e11d

Browse files
committed
Add send-money-json-API sample
1 parent b302fd3 commit 9d4e11d

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed

src/samples/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ if (NOT ${CMAKE_BUILD_TYPE} MATCHES "Coverage")
77
add_subdirectory(asyncawait)
88
add_subdirectory(pastebin)
99
add_subdirectory(smolsite)
10+
add_subdirectory(send-money-json-api)
1011
endif()
1112

1213
add_subdirectory(techempower)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
add_executable(send-money-json-api
2+
main.c
3+
../techempower/json.c
4+
)
5+
6+
target_link_libraries(send-money-json-api
7+
${LWAN_COMMON_LIBS}
8+
${ADDITIONAL_LIBRARIES}
9+
)
+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* lwan - web server
3+
* Copyright (c) 2024 L. A. F. Pereira <[email protected]>
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU General Public License
7+
* as published by the Free Software Foundation; either version 2
8+
* of the License, or any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18+
* USA.
19+
*/
20+
21+
/*
22+
* Hastily written to compare results with other languages and
23+
* frameworks after this Twitter thread:
24+
* https://twitter.com/iSeiryu/status/1793830738153889902
25+
*/
26+
27+
#include <stdbool.h>
28+
#include <time.h>
29+
30+
#define ARRAY_SIZE N_ELEMENTS
31+
32+
#include "../techempower/json.h"
33+
#include "lwan.h"
34+
35+
struct address {
36+
const char *street;
37+
const char *city;
38+
const char *state;
39+
const char *zip;
40+
};
41+
42+
struct account_holder {
43+
const char *id;
44+
const char *firstName;
45+
const char *lastName;
46+
struct address address;
47+
const char *email;
48+
};
49+
50+
struct send_money_request {
51+
struct account_holder from, to;
52+
int amount;
53+
const char *sendOn;
54+
};
55+
56+
struct receipt {
57+
char *from_account;
58+
char *to_account;
59+
char *created_on;
60+
char *to_address;
61+
int amount;
62+
};
63+
64+
static const struct json_obj_descr receipt_descr[] = {
65+
JSON_OBJ_DESCR_PRIM(struct receipt, from_account, JSON_TOK_STRING),
66+
JSON_OBJ_DESCR_PRIM(struct receipt, to_account, JSON_TOK_STRING),
67+
JSON_OBJ_DESCR_PRIM(struct receipt, amount, JSON_TOK_NUMBER),
68+
JSON_OBJ_DESCR_PRIM(struct receipt, created_on, JSON_TOK_STRING),
69+
JSON_OBJ_DESCR_PRIM(struct receipt, to_address, JSON_TOK_STRING),
70+
};
71+
72+
static const struct json_obj_descr address_descr[] = {
73+
JSON_OBJ_DESCR_PRIM(struct address, street, JSON_TOK_STRING),
74+
JSON_OBJ_DESCR_PRIM(struct address, city, JSON_TOK_STRING),
75+
JSON_OBJ_DESCR_PRIM(struct address, state, JSON_TOK_STRING),
76+
JSON_OBJ_DESCR_PRIM(struct address, zip, JSON_TOK_STRING),
77+
};
78+
79+
static const struct json_obj_descr account_holder_descr[] = {
80+
JSON_OBJ_DESCR_PRIM(struct account_holder, id, JSON_TOK_STRING),
81+
JSON_OBJ_DESCR_PRIM(struct account_holder, firstName, JSON_TOK_STRING),
82+
JSON_OBJ_DESCR_PRIM(struct account_holder, lastName, JSON_TOK_STRING),
83+
JSON_OBJ_DESCR_PRIM(struct account_holder, email, JSON_TOK_STRING),
84+
JSON_OBJ_DESCR_OBJECT(struct account_holder, address, address_descr),
85+
};
86+
87+
static const struct json_obj_descr send_money_request_descr[] = {
88+
JSON_OBJ_DESCR_PRIM(struct send_money_request, amount, JSON_TOK_NUMBER),
89+
JSON_OBJ_DESCR_PRIM(struct send_money_request, sendOn, JSON_TOK_STRING),
90+
JSON_OBJ_DESCR_OBJECT(
91+
struct send_money_request, from, account_holder_descr),
92+
JSON_OBJ_DESCR_OBJECT(struct send_money_request, to, account_holder_descr),
93+
};
94+
95+
static int append_to_strbuf(const char *bytes, size_t len, void *data)
96+
{
97+
struct lwan_strbuf *strbuf = data;
98+
99+
return !lwan_strbuf_append_str(strbuf, bytes, len);
100+
}
101+
102+
static inline struct tm *localtime_now(void)
103+
{
104+
static __thread struct tm result;
105+
time_t now = time(NULL);
106+
return localtime_r(&now, &result);
107+
}
108+
109+
LWAN_HANDLER_ROUTE(send_money, "/send-money")
110+
{
111+
struct send_money_request smr;
112+
const struct lwan_value *body;
113+
114+
if (lwan_request_get_method(request) != REQUEST_METHOD_POST)
115+
return HTTP_BAD_REQUEST;
116+
117+
body = lwan_request_get_request_body(request);
118+
if (!body) {
119+
return HTTP_BAD_REQUEST;
120+
}
121+
122+
if (json_obj_parse(body->value, body->len, send_money_request_descr,
123+
N_ELEMENTS(send_money_request_descr),
124+
&smr) != (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3)) {
125+
return HTTP_BAD_REQUEST;
126+
}
127+
128+
char formatted_time[25];
129+
strftime(formatted_time, 25, "%FT%T%z", localtime_now());
130+
131+
struct receipt r = {
132+
.from_account = coro_printf(request->conn->coro, "%s %s",
133+
smr.from.firstName, smr.from.lastName),
134+
.to_account = coro_printf(request->conn->coro, "%s %s",
135+
smr.to.firstName, smr.to.lastName),
136+
.to_address = coro_printf(request->conn->coro, "%s, %s, %s, %s",
137+
smr.to.address.street, smr.to.address.city,
138+
smr.to.address.state, smr.to.address.zip),
139+
.created_on = formatted_time,
140+
.amount = smr.amount,
141+
};
142+
if (json_obj_encode_full(receipt_descr, N_ELEMENTS(receipt_descr), &r,
143+
append_to_strbuf, response->buffer, false) != 0) {
144+
return HTTP_INTERNAL_ERROR;
145+
}
146+
147+
response->mime_type = "application/json";
148+
return HTTP_OK;
149+
}
150+
151+
int main(void) { return lwan_main(); }

0 commit comments

Comments
 (0)