Skip to content

Commit fbf2b71

Browse files
committed
first commit
0 parents  commit fbf2b71

34 files changed

+3259
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
crut
2+
*.o
3+
*.test
4+
cscope.*

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "Lib/mongoose"]
2+
path = Lib/mongoose
3+
url = https://github.com/netCommonsEU/mongoose.git

COPYING

+661
Large diffs are not rendered by default.

Lib/mongoose

Submodule mongoose added at 50b7ec5

Makefile

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
2+
current_dir := $(patsubst %/,%,$(dir $(mkfile_path)))
3+
4+
SRC=$(wildcard src/*.c)
5+
OBJS=$(SRC:.c=.o)
6+
7+
EXE=crut
8+
9+
LIB_CFLAGS+=-I$(current_dir)/src/ -I$(current_dir)/Lib/mongoose/
10+
11+
ifdef ENABLE_SSL
12+
CFLAGS+=-DMG_ENABLE_SSL
13+
LDFLAGS+= -lssl -lcrypto
14+
MONGOOSE_OPTS+=-DMG_SSL_IF=MG_SSL_IF_OPENSSL
15+
endif
16+
17+
ifdef DEBUG
18+
CFLAGS+=-g -W -Wall -Wno-unused-function -Wno-unused-parameter -O0
19+
else
20+
CFLAGS+=-O6
21+
endif
22+
23+
LIBS+=$(current_dir)/Lib/mongoose/mongoose.o
24+
MONGOOSE_OPTS+=-DMG_DISABLE_MQTT -DMG_DISABLE_JSON_RPC -DMG_DISABLE_SOCKETPAIR -DMG_DISABLE_CGI
25+
26+
LDFLAGS+= -lm
27+
28+
all: $(EXE)
29+
30+
$(EXE): $(LIBS) $(OBJS) crut.c
31+
$(CC) -o $(EXE) crut.c $(OBJS) $(current_dir)/Lib/mongoose/mongoose.o $(CFLAGS) $(LIB_CFLAGS) $(LDFLAGS)
32+
33+
%.o: %.c
34+
$(CC) $< -o $@ -c $(LIB_CFLAGS) $(CFLAGS)
35+
36+
$(current_dir)/Lib/mongoose/mongoose.o:
37+
git submodule init $(current_dir)/Lib/mongoose/
38+
git submodule update $(current_dir)/Lib/mongoose/
39+
make -C $(current_dir)/Lib/mongoose/ CFLAGS="$(CFLAGS)" MONGOOSE_OPTS="$(MONGOOSE_OPTS)"
40+
41+
tests: $(LIBS) $(OBJS)
42+
make -C $(current_dir)/Test/
43+
$(current_dir)/Test/run_tests.sh
44+
45+
clean:
46+
rm -f *.o $(EXE) $(OBJS) $(LIBS)
47+
48+
.PHONY: all clean

Public/index.html

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
7+
<title>CRut</title>
8+
9+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
10+
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
11+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
12+
13+
</head>
14+
<body>
15+
<div class="container">
16+
<div class="page-header text-center">
17+
<h1>CRut</h1>
18+
Internet-of-Things ReST application framework
19+
</div>
20+
</div>
21+
</body>
22+
</html>
23+

README.md

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# CRut, a ReST application framework
2+
CRut is web application framework for services written in C.
3+
It is realized so to save the more resources as possible and to be run on Internet-of-Things devices.
4+
It has been developed for the [PeerStreamer-ng](http://peerstreamer.eu) web application, a service for real-time P2P streaming.
5+
6+
Developers are asked to define and couple HTTP request patterns (i.e., URI) and methods.
7+
CRut also serves the files placed in the _Public/_ folder.
8+
9+
By default, CRut runs on port 3000.
10+
11+
## Compile and run
12+
```
13+
make
14+
./crut
15+
```
16+
Point your web browser at _http://localhost:3000_.
17+
18+
## Create your routes
19+
The HTTP request patters comprise of
20+
21+
* an HTTP method;
22+
* a regex for the URL.
23+
24+
HTTP methods are: GET, PUT, POST, UPDATE, DELETE, OPTION, HEAD.
25+
Regex allows the specification of a broad range of HTTP resource patters; for example, if you want to match the resource with URL _/channels/BBC_, you can write: "/channels/[A-z0-9]+$".
26+
The previous regex will match all the URLs of the form _/channels/<id>_ where _<id>_ is any string comprising of lower and upper case letters and numbers.
27+
28+
A path handler is a C function pointer with type
29+
```
30+
void (*path_handler)(struct mg_connection *nc, struct http_message *hm);
31+
```
32+
33+
A route is the triple __HTTP method, URL regex, path handler__.
34+
Routes are defined so to react to specific HTTP requests with some C code.
35+
Routes can be defined in the _src/routes.c_ file with the following line:
36+
```
37+
res |= router_add_route(r, "POST", "^[/]+channels/[A-z0-9]+$", path_handler);
38+
```
39+
where _res_ and _r_ are scope specific variable to be used as-is.
40+
41+
## Define your handlers
42+
Defining a path handler is easy as opening _src/path_handlers.c_ and writing:
43+
```
44+
void path_handler(struct mg_connection *nc, struct http_message *hm)
45+
{
46+
mg_http_short_answer(nc, 200);
47+
}
48+
```
49+
The example code above will answer to incoming HTTP requests with a polite "HTTP 200 OK" message.
50+
51+
Handlers can take advantage from some helpers for getting request variable values;
52+
53+
* mg_uri_field(hm, pos) returns a char array pointer with the value of the URI field specified by _pos_; for example, for the request _/channels/BBC_, with _pos=1_ it will return "BBC".
54+
* mg_get_http_var(&hm->body, "data", buff, BUFF_LENGTH) stores in the buffer pointed by _buff_ the value of the HTTP variable "data" encoded in the request.
55+
56+
The helpers also include some functions for answering:
57+
58+
* mg_http_short_answer(nc, code); will send the HTTP request with the status code _code_ and the brief corresponding message;
59+
* mg_http_text_answer(nc, code, body); adds the possibility to also specify the response message;
60+
* mg_http_json_answer(nc, code, body); adds the possibility to specify a JSON body (it automatically set the Content-type header).
61+
* mg_http_answer(nc, code, content_type, body); sends an HTTP requests setting the content type and the response body.
62+
63+
## SSL
64+
CRut supports SSL, just enable it at compilation time:
65+
```
66+
ENABLE_SSL=1 make
67+
```
68+
69+
## Tests
70+
CRut comes with a unit-test suite (in _/Test_).
71+
To run all of them at once type:
72+
```
73+
make tests
74+
```
75+
It requires [valgrind](http://valgrind.org/) to be installed and present in the PATH.
76+
77+
CRut can also be compiled in debug mode for enabling extra output:
78+
```
79+
DEBUG=1 make
80+
```
81+
82+
## Tutorials
83+
A [tutorial](https://ans.disi.unitn.it/users/baldesi//programming/c/rest/raspberry-pi/web/crut/2019/02/13/web-interface-for-raspberry-pi-gpio.html) about using CRut to create a web app turning Raspberry pi leds on and off is avaiable.

Test/Makefile

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
SRC=$(wildcard *.c)
2+
OBJS=$(SRC:.c=.test)
3+
4+
TARGET_SRC += $(wildcard ../src/*.c)
5+
TARGET_OBJS=$(TARGET_SRC:.c=.o)
6+
7+
LDFLAGS+=-lm
8+
CFLAGS += -g -W -Wall -Wno-unused-function -Wno-unused-parameter -O0 -I../src -I../Lib/mongoose
9+
10+
all: $(TARGET_SRC) $(TARGET_OBJS) $(OBJS)
11+
12+
%.test: %.c $(TARGET_OBJS)
13+
$(CC) -o $@ $< $(CFLAGS) $(TARGET_OBJS) ../Lib/mongoose/mongoose.o $(LIBS) $(LDFLAGS)
14+
15+
clean:
16+
rm -f *.test $(LIBS)
17+
18+
.PHONY: all clean
19+

Test/http_test.sh

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/bin/bash
2+
3+
URI="http://127.0.0.1:3000/"
4+
5+
info() {
6+
echo -e "\E[33m$@\033[0m"
7+
}
8+
9+
error() {
10+
echo -e "\E[31m$@\033[0m"
11+
}
12+
13+
success() {
14+
echo -e "\E[32m$@\033[0m"
15+
}
16+
17+
assert_equal() {
18+
# assert_equal <line> <val1> <val2>
19+
line=$1
20+
val1=$2
21+
val2="$3"
22+
if [[ "$val1" == "$val2" ]]; then
23+
echo -n .
24+
return
25+
else
26+
error "\nLine $1: Failure, \"$val1\" mismatches \"$val2\""
27+
exit 1
28+
fi
29+
}
30+
31+
assert_not_equal() {
32+
# assert_not_equal <line> <val1> <val2>
33+
line=$1
34+
val1=$2
35+
val2="$3"
36+
if [[ "$val1" != "$val2" ]]; then
37+
echo -n .
38+
return
39+
else
40+
error "\nLine $1: Failure, \"$val1\" matches \"$val2\""
41+
exit 1
42+
fi
43+
}
44+
45+
function test_url() {
46+
# test_url <METHOD> <URL> <DATA>
47+
METHOD=$1
48+
URL=$2
49+
if [ -z $3 ]; then
50+
curl -X $METHOD $URI/$URL 2>/dev/null
51+
else
52+
DATA="$3"
53+
curl -X $METHOD --data "$DATA" $URI/$URL 2>/dev/null
54+
fi
55+
return $?
56+
}
57+
58+
which curl > /dev/null 2>&1
59+
if [[ $? -ne 0 ]]; then
60+
error "Executable curl not found"
61+
exit 1
62+
fi
63+
64+
res=$(test_url GET )
65+
if [[ $? -ne 0 ]]; then
66+
error "CRut is not responding at $URI.\nIs it running?"
67+
exit 1
68+
fi
69+
70+
## Try the GET
71+
res=$(test_url GET non-existing key=value)
72+
assert_equal $LINENO "$res" "Not Found"
73+
74+
success "\nTest run successfully"

0 commit comments

Comments
 (0)