From 8497c8bbcdcfd8754c500e65557ee09d9bd1bed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Thu, 20 Sep 2012 06:22:51 +0200 Subject: Don't use decode_packet/3 for parsing the request-line First step in making all methods and header names binaries to get rid of many inconsistencies caused by decode_packet/3. Methods are all binary now. Note that since they are case sensitive, the usual methods become <<"GET">>, <<"POST">> and so on. --- src/cowboy_http.erl | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'src/cowboy_http.erl') diff --git a/src/cowboy_http.erl b/src/cowboy_http.erl index f3457dc..83a67fe 100644 --- a/src/cowboy_http.erl +++ b/src/cowboy_http.erl @@ -17,6 +17,7 @@ -module(cowboy_http). %% Parsing. +-export([request_line/1]). -export([list/2]). -export([nonempty_list/2]). -export([content_type/1]). @@ -50,8 +51,6 @@ -export([urlencode/2]). -export([x_www_form_urlencoded/2]). --type method() :: 'OPTIONS' | 'GET' | 'HEAD' - | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | binary(). -type uri() :: '*' | {absoluteURI, http | https, Host::binary(), Port::integer() | undefined, Path::binary()} | {scheme, Scheme::binary(), binary()} @@ -73,7 +72,6 @@ -type headers() :: [{header(), iodata()}]. -type status() :: non_neg_integer() | binary(). --export_type([method/0]). -export_type([uri/0]). -export_type([version/0]). -export_type([header/0]). @@ -86,6 +84,46 @@ %% Parsing. +%% @doc Parse a request-line. +-spec request_line(binary()) + -> {binary(), binary(), version()} | {error, badarg}. +request_line(Data) -> + token(Data, + fun (Rest, Method) -> + whitespace(Rest, + fun (Rest2) -> + uri_to_abspath(Rest2, + fun (Rest3, AbsPath) -> + whitespace(Rest3, + fun (<< "HTTP/", Maj, ".", Min, _/binary >>) + when Maj >= $0, Maj =< $9, + Min >= $0, Min =< $9 -> + {Method, AbsPath, {Maj - $0, Min - $0}}; + (_) -> + {error, badarg} + end) + end) + end) + end). + +%% We just want to extract the path/qs and skip everything else. +%% We do not really parse the URI, nor do we need to. +uri_to_abspath(Data, Fun) -> + case binary:split(Data, <<" ">>) of + [_] -> %% We require the HTTP version. + {error, badarg}; + [URI, Rest] -> + case binary:split(URI, <<"://">>) of + [_] -> %% Already is a path or "*". + Fun(Rest, URI); + [_, NoScheme] -> + case binary:split(NoScheme, <<"/">>) of + [_] -> <<"/">>; + [_, NoHost] -> Fun(Rest, << "/", NoHost/binary >>) + end + end + end. + %% @doc Parse a non-empty list of the given type. -spec nonempty_list(binary(), fun()) -> [any(), ...] | {error, badarg}. nonempty_list(Data, Fun) -> -- cgit v1.2.3