|
|
@ -44,25 +44,25 @@ response(Data) -> |
|
|
|
-spec response(undefined | recvState(), binary:cp(), binary:cp(), binary()) -> {ok, recvState()} | error(). |
|
|
|
response(undefined, Rn, RnRn, Data) -> |
|
|
|
case parseStatusLine(Data, Rn) of |
|
|
|
{StatusCode, Reason, Rest} -> |
|
|
|
{StatusCode, Rest} -> |
|
|
|
case splitHeaders(Rest, Rn, RnRn) of |
|
|
|
{undefined, Headers, Body} -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = undefined, body = Body}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = undefined, body = Body}}; |
|
|
|
{0, Headers, Rest} -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = 0, body = Rest}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = 0, body = Rest}}; |
|
|
|
{chunked, Headers, Body} -> |
|
|
|
RecvState = #recvState{stage = body, contentLength = chunked, statusCode = StatusCode, reason = Reason, headers = Headers}, |
|
|
|
RecvState = #recvState{stage = body, contentLength = chunked, statusCode = StatusCode, headers = Headers}, |
|
|
|
response(RecvState, Rn, RnRn, Body); |
|
|
|
{ContentLength, Headers, Body} -> |
|
|
|
BodySize = erlang:size(Body), |
|
|
|
if |
|
|
|
BodySize == ContentLength -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
BodySize > ContentLength -> |
|
|
|
?WARN(agTcpAgencyIns, "11 contentLength get to long data why? more: ~p ~n",[BodySize - ContentLength]), |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
true -> |
|
|
|
{ok, #recvState{stage = body, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = ContentLength, body = Body}} |
|
|
|
{ok, #recvState{stage = body, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}} |
|
|
|
end; |
|
|
|
not_enough_data -> |
|
|
|
%% headers都不足 这也可以能发生么 |
|
|
@ -98,31 +98,35 @@ response(#recvState{stage = body, contentLength = ContentLength, body = Body} = |
|
|
|
true -> |
|
|
|
{ok,RecvState#recvState{body = CurData}} |
|
|
|
end; |
|
|
|
response(#recvState{stage = header, body = Body}, Rn, RnRn, Data) -> |
|
|
|
CurData = <<Body/binary, Data/binary>>, |
|
|
|
case parseStatusLine(CurData, Rn) of |
|
|
|
{StatusCode, Reason, Rest} -> |
|
|
|
response(#recvState{stage = header, body = OldBody}, Rn, RnRn, Data) -> |
|
|
|
CurBody = <<OldBody/binary, Data/binary>>, |
|
|
|
case parseStatusLine(CurBody, Rn) of |
|
|
|
{StatusCode, Rest} -> |
|
|
|
case splitHeaders(Rest, Rn, RnRn) of |
|
|
|
{undefined, Headers, Body} -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = undefined, body = Body}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = undefined, body = Body}}; |
|
|
|
{0, Headers, Body} -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = 0, body = Body}}; |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = 0, body = Body}}; |
|
|
|
{chunked, Headers, Rest} -> |
|
|
|
RecvState = #recvState{stage = body, contentLength = chunked, statusCode = StatusCode, reason = Reason, headers = Headers}, |
|
|
|
RecvState = #recvState{stage = body, contentLength = chunked, statusCode = StatusCode, headers = Headers}, |
|
|
|
response(RecvState, Rn, RnRn, Rest); |
|
|
|
{ContentLength, Headers, Body} -> |
|
|
|
case erlang:size(Body) >= ContentLength of |
|
|
|
BodySize = erlang:size(Body), |
|
|
|
if |
|
|
|
BodySize == ContentLength -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
BodySize > ContentLength -> |
|
|
|
?WARN(agTcpAgencyIns, "33 contentLength get to long data why? more: ~p ~n",[BodySize - ContentLength]), |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
true -> |
|
|
|
{done, #recvState{stage = done, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = ContentLength, body = Body}}; |
|
|
|
_ -> |
|
|
|
{ok, #recvState{stage = body, statusCode = StatusCode, reason = Reason, headers = Headers, contentLength = ContentLength, body = Body}} |
|
|
|
{ok, #recvState{stage = body, statusCode = StatusCode, headers = Headers, contentLength = ContentLength, body = Body}} |
|
|
|
end; |
|
|
|
not_enough_data -> |
|
|
|
%% headers都不足 这也可以能发生么 |
|
|
|
{ok, #recvState{stage = header, body = CurData}} |
|
|
|
{ok, #recvState{stage = header, body = CurBody}} |
|
|
|
end; |
|
|
|
not_enough_data -> |
|
|
|
{ok, #recvState{stage = header, body = CurData}}; |
|
|
|
{ok, #recvState{stage = header, body = CurBody}}; |
|
|
|
{error, Reason} -> |
|
|
|
{error, Reason} |
|
|
|
end. |
|
|
@ -159,35 +163,35 @@ parseStatusLine(Data, Rn) -> |
|
|
|
not_enough_data; |
|
|
|
[Line, Rest] -> |
|
|
|
case parseStatusReason(Line) of |
|
|
|
{ok, StatusCode, Reason} -> |
|
|
|
{StatusCode, Reason, Rest}; |
|
|
|
{ok, StatusCode} -> |
|
|
|
{StatusCode, Rest}; |
|
|
|
{error, Reason} -> |
|
|
|
{error, Reason} |
|
|
|
end |
|
|
|
end. |
|
|
|
|
|
|
|
parseStatusReason(<<"HTTP/1.1 200 OK">>) -> |
|
|
|
{ok, 200, <<"OK">>}; |
|
|
|
{ok, 200}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 204 No Content">>) -> |
|
|
|
{ok, 204, <<"No Content">>}; |
|
|
|
{ok, 204}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 301 Moved Permanently">>) -> |
|
|
|
{ok, 301, <<"Moved Permanently">>}; |
|
|
|
{ok, 301}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 302 Found">>) -> |
|
|
|
{ok, 302, <<"Found">>}; |
|
|
|
{ok, 302}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 403 Forbidden">>) -> |
|
|
|
{ok, 403, <<"Forbidden">>}; |
|
|
|
{ok, 403}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 404 Not Found">>) -> |
|
|
|
{ok, 404, <<"Not Found">>}; |
|
|
|
{ok, 404}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 500 Internal Server Error">>) -> |
|
|
|
{ok, 500, <<"Internal Server Error">>}; |
|
|
|
{ok, 500}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 502 Bad Gateway">>) -> |
|
|
|
{ok, 502, <<"Bad Gateway">>}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 ", N1, N2, N3, " ", Reason/bits>>) |
|
|
|
{ok, 502}; |
|
|
|
parseStatusReason(<<"HTTP/1.1 ", N1, N2, N3, " ", _Reason/bits>>) |
|
|
|
when $0 =< N1, N1 =< $9, |
|
|
|
$0 =< N2, N2 =< $9, |
|
|
|
$0 =< N3, N3 =< $9 -> |
|
|
|
StatusCode = (N1 - $0) * 100 + (N2 - $0) * 10 + (N3 - $0), |
|
|
|
{ok, StatusCode, Reason}; |
|
|
|
{ok, StatusCode}; |
|
|
|
parseStatusReason(<<"HTTP/1.0 ", _/binary>>) -> |
|
|
|
{error, unsupported_feature}; |
|
|
|
parseStatusReason(_) -> |
|
|
|