HTTP Body
This commit is contained in:
@@ -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(sockets)).
|
||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
@@ -42,16 +42,15 @@ accept_loop(Socket, Handlers) :-
|
|||||||
;true
|
;true
|
||||||
),
|
),
|
||||||
format("~w ~s\n", [Method, Path]),
|
format("~w ~s\n", [Method, Path]),
|
||||||
call_handler(Path, HeadersKV, RequestBody, Handlers, Response),
|
( call_handler(Path, HeadersKV, RequestBody, Handlers, Response) ->
|
||||||
http_response(StatusCode, ResponseBody, RequestHeaders) = Response,
|
send_response(Stream, Response)
|
||||||
format(Stream, "HTTP/1.0 ~d\r\n", [StatusCode]),
|
; format(Stream, "HTTP/1.0 500 Internal Server Error\r\n\r\n", [])
|
||||||
forall(member(RequestHeaderKey-RequestHeaderValue, RequestHeaders), format(Stream, "~s: ~s\r\n", [RequestHeaderKey, RequestHeaderValue])),
|
)
|
||||||
format(Stream, "\r\n~s", [ResponseBody])
|
|
||||||
);(
|
);(
|
||||||
format(Stream, "HTTP/1.0 400 Bad Request\r\n\r\n", []) % bad format
|
format(Stream, "HTTP/1.0 400 Bad Request\r\n\r\n", []) % bad format
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
close(Stream)
|
! % Remove
|
||||||
), close(Stream)),
|
), close(Stream)),
|
||||||
accept_loop(Socket, Handlers).
|
accept_loop(Socket, Handlers).
|
||||||
|
|
||||||
@@ -62,14 +61,44 @@ call_handler(Path, Headers, _, Handlers, Response) :-
|
|||||||
call(Handler, Request, Response).
|
call(Handler, Request, Response).
|
||||||
|
|
||||||
call_handler(Path, Headers, Body, Handlers, Response) :-
|
call_handler(Path, Headers, Body, Handlers, Response) :-
|
||||||
chars_utf8bytes(CharBody, Body),
|
|
||||||
member(post(Dcg, Handler), Handlers),
|
member(post(Dcg, Handler), Handlers),
|
||||||
phrase(Dcg, Path),!,
|
phrase(Dcg, Path),!,
|
||||||
Request = http_request(Headers, CharBody),
|
build_response(Body, ResponseBody),
|
||||||
|
Request = http_request(Headers, ResponseBody),
|
||||||
call(Handler, Request, Response).
|
call(Handler, Request, Response).
|
||||||
|
|
||||||
call_handler(_, _, _, http_response(404, "Not found")).
|
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) -->
|
parse_request(http_version(Major, Minor), Method, Path) -->
|
||||||
method(Method),
|
method(Method),
|
||||||
" ",
|
" ",
|
||||||
@@ -139,8 +168,7 @@ get_bytes(Stream, Length, Acc, Res) :-
|
|||||||
get_bytes(Stream, Length - 1, [B|Acc], Res)
|
get_bytes(Stream, Length - 1, [B|Acc], Res)
|
||||||
); reverse(Acc, Res)).
|
); reverse(Acc, Res)).
|
||||||
|
|
||||||
sample_handler(http_request(Headers, _), Response) :-
|
put_bytes(_, []).
|
||||||
member("User-Agent"-UserAgent, Headers),
|
put_bytes(Stream, [Byte|Bytes]) :-
|
||||||
Response = http_response(200, UserAgent, ["Content-Type"-"text/plain", "Connection"-"Close"]).
|
put_byte(Stream, Byte),
|
||||||
|
put_bytes(Stream, Bytes).
|
||||||
sample_body_handler(http_request(Headers, Body), http_response(200, Body, ["Content-Type"-"application/json"])).
|
|
||||||
Reference in New Issue
Block a user