1
0
mirror of https://github.com/urlysses/1991.git synced 2024-11-30 06:21:41 -05:00

Add basic CRUD support.

TODO:
+ Make content-type available.
+ Make sure multipart/form-data works (not sure?).
+ Clean up recent code additions.
This commit is contained in:
urlysses 2017-02-26 00:54:43 -05:00
parent 424aced3ec
commit d775fd9ae6
3 changed files with 154 additions and 4 deletions

86
1991.fs
View File

@ -11,6 +11,10 @@ include unix/socket.fs
while 2over nip /string while 2over nip /string
r> 1+ >r r> 1+ >r
repeat 2drop 2drop r> ; repeat 2drop 2drop r> ;
: -leading ( addr len -- addr' len' )
begin over c@ bl = while 1 /string repeat ;
: trim ( addr len -- addr' len')
-leading -trailing ;
: exchange ( a1 a2 -- ) : exchange ( a1 a2 -- )
2dup c@ swap c@ rot c! swap c! ; 2dup c@ swap c@ rot c! swap c! ;
: reverse ( caddr u -- ) \ reverse a string : reverse ( caddr u -- ) \ reverse a string
@ -65,6 +69,20 @@ pubvar tmpQueryString
+s \ adding our new query values. +s \ adding our new query values.
set-tmp-query-string ; set-tmp-query-string ;
\ Request body
pubvar requestBody
: set-request-body ( addr u -- )
requestBody 2! ;
: get-request-body ( -- addr u )
requestBody 2@ ;
\ Request method
pubvar requestMethod
: set-request-method ( addr u -- )
requestMethod 2! ;
: get-request-method ( -- addr u )
requestMethod 2@ ;
\ User-defined routing \ User-defined routing
wordlist constant routes wordlist constant routes
pubvar reqroute pubvar reqroute
@ -317,8 +335,35 @@ s" image/x-icon" filetype: ico
2swap content-type \ Set content-type 2swap content-type \ Set content-type
s+ ; \ Join s+ ; \ Join
: get-content-length ( addr u -- clen )
s" Content-Length:" search if
2dup s\" \n" search drop nip -
s" Content-Length:" nip /string
trim
s>number?
2drop
else
2drop
0
then ;
: read-request-body ( socket u -- )
\ Takes the socket and the length of the
\ body (Content-Length).
here swap aligned read-socket
set-request-body ;
: read-request ( socket -- addr u ) : read-request ( socket -- addr u )
pad 4096 read-socket ; \ Returns the request header
\ but also collects the request body.
dup >r
pad 4096 read-socket
r> dup 2over rot drop
get-content-length ?dup if
read-request-body
else
s" " set-request-body
drop
then ;
: send-response ( addr u socket -- ) : send-response ( addr u socket -- )
dup >r write-socket r> close-socket ; dup >r write-socket r> close-socket ;
@ -356,8 +401,42 @@ s" image/x-icon" filetype: ico
: 404content-type txt ; : 404content-type txt ;
: 404html s" 404" ; : 404html s" 404" ;
: valid-method? ( addr u -- addr' u' bool )
2dup s" GET" search if
2nip
-1
s" GET" set-request-method
exit
then
2drop
2dup s" POST" search if
2nip
-1
s" POST" set-request-method
exit
then
2drop
2dup s" PUT" search if
2nip
-1
s" PUT" set-request-method
exit
then
2drop
2dup s" DELETE" search if
2nip
-1
s" DELETE" set-request-method
exit
then
2drop
0 ;
: either-resolve ( addr u -- resolveaddr resolveu ) : either-resolve ( addr u -- resolveaddr resolveu )
s" GET" search if valid-method? if
s" html" get-filetype set-content-type \ reset the request's content-type s" html" get-filetype set-content-type \ reset the request's content-type
requested-route requested-route
2dup find-route dup if 2dup find-route dup if
@ -374,7 +453,8 @@ s" image/x-icon" filetype: ico
then then
then then
200 get-content-type set-header +s 200 get-content-type set-header +s
rdrop exit then ; rdrop exit
then ;
: or-404 ( addr u -- 404addr 404u ) : or-404 ( addr u -- 404addr 404u )
2drop 2drop

View File

@ -8,6 +8,6 @@ A server-side web framework written in Forth.
+ [x] file-serving if no user-defined routes match. Search "public/" dir + [x] file-serving if no user-defined routes match. Search "public/" dir
unless otherwise specified by user. unless otherwise specified by user.
+ [x] query arguments + [x] query arguments
+ [ ] PUT, POST, DELETE + [x] PUT, POST, DELETE
+ [x] templating + [x] templating
+ [x] fuzzy-/pattern-match-enabled user routes (e.g., /something/*/wildcard)? + [x] fuzzy-/pattern-match-enabled user routes (e.g., /something/*/wildcard)?

70
examples/public/crud.html Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>GET, PUT, POST, DELETE</title>
</head>
<body>
<input type="submit" value="GET" id="get">
<input type="submit" value="POST" id="post">
<input type="submit" value="PUT" id="put">
<input type="submit" value="DELETE" id="delete">
<script type="text/javascript">
// https://gist.github.com/EtienneR/2f3ab345df502bd3d13e
(function () {
function onload () {
var rt = xhr.responseText;
console.log(rt, xhr.readyState, xhr.status);
}
var url = "/api/v1/users";
var xhr = new XMLHttpRequest();
var get = document.querySelector("#get");
var post = document.querySelector("#post");
var put = document.querySelector("#put");
var del = document.querySelector("#delete");
// GET
get.onclick = function () {
xhr.open("GET", url + "/1", true);
xhr.onload = onload;
xhr.send(null);
};
// POST
// TODO: 201 status
post.onclick = function () {
var data = {};
data.firstname = "Aaaa";
data.lastname = "Bbbb";
var json = JSON.stringify(data);
xhr = new XMLHttpRequest();
xhr.open("POST", url + "/1", true);
xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
xhr.onload = onload;
xhr.send(json);
};
// PUT
put.onclick = function () {
var data = {};
data.firstname = "Aaaa2";
data.lastname = "Bbbb2";
var json = JSON.stringify(data);
xhr = new XMLHttpRequest();
xhr.open("PUT", url + "/2", true);
xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");
xhr.onload = onload;
xhr.send(json);
};
// DELETE
del.onclick = function () {
xhr = new XMLHttpRequest();
xhr.open("DELETE", url + "/2", true);
xhr.onload = onload;
xhr.send(null);
};
}());
</script>
</body>
</html>