]> Repositorios git - scryer-prolog.git/commitdiff
HTTP Body
authorAdrián Arroyo Calle <[email protected]>
Sun, 20 Dec 2020 23:15:00 +0000 (00:15 +0100)
committerAdrián Arroyo Calle <[email protected]>
Sun, 20 Dec 2020 23:15:00 +0000 (00:15 +0100)
src/lib/http/http_server.pl

index 5eeb4847d1b80ba92f8347bc3fd06a5b298620cb..2eb503d900a22802ea792a606e529e64455e9c70 100644 (file)
@@ -1,4 +1,4 @@
-:- module(http_server, [http_listen/2, sample_handler/2, sample_body_handler/2, parse_request/5]).
+:- module(http_server, [http_listen/2]).
 
 :- use_module(library(sockets)).
 :- use_module(library(dcgs)).
@@ -42,16 +42,15 @@ accept_loop(Socket, Handlers) :-
                                 ;true
                         ),
                         format("~w ~s\n", [Method, Path]),
-                        call_handler(Path, HeadersKV, RequestBody, Handlers, Response),
-                        http_response(StatusCode, ResponseBody, RequestHeaders) = Response,
-                        format(Stream, "HTTP/1.0 ~d\r\n", [StatusCode]),
-                        forall(member(RequestHeaderKey-RequestHeaderValue, RequestHeaders), format(Stream, "~s: ~s\r\n", [RequestHeaderKey, RequestHeaderValue])),
-                        format(Stream, "\r\n~s", [ResponseBody])
+                        ( call_handler(Path, HeadersKV, RequestBody, Handlers, Response) ->
+                            send_response(Stream, Response)
+                        ;   format(Stream, "HTTP/1.0 500 Internal Server Error\r\n\r\n", [])
+                        )
                     );(
                         format(Stream, "HTTP/1.0 400 Bad Request\r\n\r\n", []) % bad format
                     )
             ),
-            close(Stream)
+            ! % Remove
         ), close(Stream)),
     accept_loop(Socket, Handlers).
 
@@ -62,14 +61,44 @@ call_handler(Path, Headers, _, Handlers, Response) :-
     call(Handler, Request, Response).
 
 call_handler(Path, Headers, Body, Handlers, Response) :-
-    chars_utf8bytes(CharBody, Body),
     member(post(Dcg, Handler), Handlers),
     phrase(Dcg, Path),!,
-    Request = http_request(Headers, CharBody),
+    build_response(Body, ResponseBody),
+    Request = http_request(Headers, ResponseBody),
     call(Handler, Request, Response).
 
 call_handler(_, _, _, http_response(404, "Not found")).
 
+build_response(ByteBody, text(TextBody)) :-
+    chars_utf8bytes(TextBody, ByteBody).
+build_response(ByteBody, binary(ByteBody)).
+
+send_response(Stream, http_response(StatusCode, text(TextResponse), Headers)) :-
+    format(Stream, "HTTP/1.0 ~d\r\n", [StatusCode]),
+    overwrite_header("Content-Type"-"text/plain", Headers, Headers0),
+    overwrite_header("Connection"-"Close", Headers0, Headers1),
+    write_headers(Stream, Headers1),
+    format(Stream, "\r\n~s", [TextResponse]).
+
+send_response(Stream, http_response(StatusCode, binary(BinaryResponse), Headers)) :-
+    format(Stream, "HTTP/1.0 ~d\r\n", [StatusCode]),
+    overwrite_header("Connection"-"Close", Headers, Headers0),
+    write_headers(Stream, Headers0),
+    format(Stream, "\r\n", []),
+    put_bytes(Stream, BinaryResponse).
+
+write_headers(Stream, Headers) :-
+    forall(member(Key-Value, Headers), format(Stream, "~s: ~s\r\n", [Key, Value])).
+
+overwrite_header(Key-Value, [], [Key-Value]).
+overwrite_header(Key-Value, [Header|Headers], HeadersOut) :-
+    Header = Key0-_,
+    Key0 \= Key,
+    overwrite_header(Key-Value, Headers, HeadersOut).
+overwrite_header(Key-Value, [Header|Headers], [NewHeader|Headers]) :-
+    Header = Key-_,
+    NewHeader = Key-Value.
+
 parse_request(http_version(Major, Minor), Method, Path) -->
     method(Method),
     " ",
@@ -139,8 +168,7 @@ get_bytes(Stream, Length, Acc, Res) :-
     get_bytes(Stream, Length - 1, [B|Acc], Res)
   ); reverse(Acc, Res)).
 
-sample_handler(http_request(Headers, _), Response) :-
-    member("User-Agent"-UserAgent, Headers),
-    Response = http_response(200, UserAgent, ["Content-Type"-"text/plain", "Connection"-"Close"]).
-
-sample_body_handler(http_request(Headers, Body), http_response(200, Body, ["Content-Type"-"application/json"])).
\ No newline at end of file
+put_bytes(_, []).
+put_bytes(Stream, [Byte|Bytes]) :-
+    put_byte(Stream, Byte),
+    put_bytes(Stream, Bytes).
\ No newline at end of file