From 889f26865006095bab986113ba249632523cd414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 17 Sep 2018 11:36:39 +0200 Subject: Add cow_http:parse_request_line/1 --- src/cow_http.erl | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- src/cow_http_hd.erl | 1 + 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/cow_http.erl b/src/cow_http.erl index 0eccd16..5701b02 100644 --- a/src/cow_http.erl +++ b/src/cow_http.erl @@ -14,7 +14,7 @@ -module(cow_http). -%% @todo parse_request_line +-export([parse_request_line/1]). -export([parse_status_line/1]). -export([status_to_integer/1]). -export([parse_headers/1]). @@ -38,6 +38,53 @@ -include("cow_inline.hrl"). +%% @doc Parse the request line. + +-spec parse_request_line(binary()) -> {binary(), binary(), version(), binary()}. +parse_request_line(Data) -> + {Pos, _} = binary:match(Data, <<"\r">>), + <> = Data, + [Method, Target, Version0] = binary:split(RequestLine, <<$\s>>, [trim_all, global]), + Version = case Version0 of + <<"HTTP/1.1">> -> 'HTTP/1.1'; + <<"HTTP/1.0">> -> 'HTTP/1.0' + end, + {Method, Target, Version, Rest}. + +-ifdef(TEST). +parse_request_line_test_() -> + Tests = [ + {<<"GET /path HTTP/1.0\r\nRest">>, + {<<"GET">>, <<"/path">>, 'HTTP/1.0', <<"Rest">>}}, + {<<"GET /path HTTP/1.1\r\nRest">>, + {<<"GET">>, <<"/path">>, 'HTTP/1.1', <<"Rest">>}}, + {<<"CONNECT proxy.example.org:1080 HTTP/1.1\r\nRest">>, + {<<"CONNECT">>, <<"proxy.example.org:1080">>, 'HTTP/1.1', <<"Rest">>}} + ], + [{V, fun() -> R = parse_request_line(V) end} + || {V, R} <- Tests]. + +parse_request_line_error_test_() -> + Tests = [ + <<>>, + <<"GET">>, + <<"GET /path\r\n">>, + <<"GET /path HTTP/1.1">>, + <<"GET /path HTTP/1.1\r">>, + <<"GET /path HTTP/1.1\n">>, + <<"GET /path HTTP/0.9\r\n">>, + <<"content-type: text/plain\r\n">>, + <<0:80, "\r\n">> + ], + [{V, fun() -> {'EXIT', _} = (catch parse_request_line(V)) end} + || V <- Tests]. + +horse_parse_request_line_get_path() -> + horse:repeat(200000, + parse_request_line(<<"GET /path HTTP/1.1\r\n">>) + ). +-endif. + %% @doc Parse the status line. -spec parse_status_line(binary()) -> {version(), status(), binary(), binary()}. diff --git a/src/cow_http_hd.erl b/src/cow_http_hd.erl index 76d2d44..1e8faaf 100644 --- a/src/cow_http_hd.erl +++ b/src/cow_http_hd.erl @@ -858,6 +858,7 @@ horse_parse_allow() -> -> {basic, binary(), binary()} | {bearer, binary()} | {digest, [{binary(), binary()}]}. +%% @todo The token is case-insensitive. https://tools.ietf.org/html/rfc7235#section-2.1 parse_authorization(<<"Basic ", R/bits >>) -> auth_basic(base64:decode(R), <<>>); parse_authorization(<<"Bearer ", R/bits >>) when R =/= <<>> -> -- cgit v1.2.3