Code Monkey home page Code Monkey logo

cowlib's Introduction

Cowlib

Cowlib is a support library for manipulating Web protocols.

Goals

Cowlib provides libraries for parsing and building messages for various Web protocols, including HTTP/1.1, HTTP/2 and Websocket.

It is optimized for completeness rather than speed. No value is ignored, they are all returned.

Support

cowlib's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cowlib's Issues

Got error when sending trailers

The syntax is Elixir, but similar with Erlang. cowlib version: 2.8.0

19:30:42.279 [error] Ranch listener "Interop.Endpoint" had connection process started with :cowboy_clear:start_link/4 at #PID<0.443.0> exit with reason:
{
  {:case_clause,
    {:trailers,
      [{"grpc-message", ""}, {"grpc-status", "0"}]
    }
  },
  [
    {:cow_http2_machine, :queue_data, 4, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowlib/src/cow_http2_machine.erl', line: 1339]},
    {:cow_http2_machine, :send_or_queue_data, 4, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowlib/src/cow_http2_machine.erl', line: 1199]},
    {:cowboy_http2, :maybe_send_data, 4, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowboy/src/cowboy_http2.erl', line: 770]},
    {:cowboy_http2, :commands, 3, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowboy/src/cowboy_http2.erl', line: 634]},
    {:cowboy_http2, :loop, 2, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowboy/src/cowboy_http2.erl', line: 247]},
    {:cowboy_http, :parse, 2, [file: '/Users/tony/repo/tony612/grpc-elixir/interop/deps/cowboy/src/cowboy_http.erl', line: 311]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 249]}
  ]
}

cow_sse.erl syntax error on Erlang 18.3

Hello. Shall cowlib still work on 18.3? After some of the last updates I am getting

===> Compiling _build/default/lib/cowlib/src/cow_sse.erl failed
_build/default/lib/cowlib/src/cow_sse.erl:32: syntax error before: ':='

crypto:rand_bytes/1 is deprecated

While compiling cowlib on Erlang/OTP 19.2 I get the following warning:

src/cow_multipart.erl:392: Warning: crypto:rand_bytes/1 is deprecated and will be removed in a future release; use crypto:strong_rand_bytes/1

cow_http_hd:reg_name/2 should accept url encoded values

According to RFC 7230, section 5.4, the host header should accept:

Host = uri-host [ ":" port ] ; Section 2.7.1

and uri-host is defined to be:

uri-host      = <host, see [RFC3986], Section 3.2.2>

which in RFC3986, section 3.2.2 is defined to be:

host        = IP-literal / IPv4address / reg-name
reg-name    = *( unreserved / pct-encoded / sub-delims )
pct-encoded   = "%" HEXDIG HEXDIG

and as a result cow_http_hd:reg_name/2 should accept url encoded values.

A patched hackney trace shows this being rejected by the current code in cowboy master:

[hackney trace 40 <0.498.0> 2017:01:28 21:46:36 4833] perform request 
   Content: [{module,hackney_request},
             {line,97},
             {header_data,<<"GET /erllambda/erllambda_test HTTP/1.1\r\naccept: application/json\r\nUser-Agent: hackney/1.6.4\r\nHost: %2ftmp%2ferllambda.sock\r\n\r\n">>},
             {perform_all,true},
             {expect,false}]

[hackney trace 80 <0.498.0> 2017:01:28 21:46:36 4834] got response 
   Content: [{module,hackney},
             {line,372},
             {response,
                 {ok,400,
                     [{<<"content-length">>,<<"0">>}],
                     {client,
                         {1485,639996,831109},
                         {metrics_ng,metrics_dummy},
                         hackney_local_tcp,"/tmp/erllambda.sock",0,
                         <<"/tmp/erllambda.sock:0">>,[],#Port<0.16995>,
                         {default,#Ref<0.0.2.8596>,
                             {"/tmp/erllambda.sock",0,hackney_local_tcp},
                             <0.500.0>,hackney_local_tcp},
                         #Ref<0.0.2.8596>,true,hackney_pool,5000,false,5,
                         false,5,nil,nil,
                         {hparser,response,4096,10,0,on_body,<<>>,
                             {1,1},
                             undefined,[],0,undefined,undefined,undefined,
                             undefined,waiting},
                         connected,waiting,nil,normal,false,false,false,
                         undefined,false,#Fun<hackney_request.send.2>,waiting,
                         nil,4096,<<>>,[],
                         {1,1},
                         0,nil,nil,<<"GET">>,<<"/erllambda/erllambda_test">>,
                         nil}}},
             {client,
                 {client,
                     {1485,639996,831109},
                     {metrics_ng,metrics_dummy},
                     hackney_local_tcp,"/tmp/erllambda.sock",0,
                     <<"/tmp/erllambda.sock:0">>,[],#Port<0.16995>,
                     {default,#Ref<0.0.2.8596>,
                         {"/tmp/erllambda.sock",0,hackney_local_tcp},
                         <0.500.0>,hackney_local_tcp},
                     #Ref<0.0.2.8596>,true,hackney_pool,5000,false,5,false,5,
                     nil,nil,nil,connected,start,nil,normal,false,false,false,
                     undefined,false,nil,waiting,nil,4096,<<>>,[],undefined,
                     nil,nil,nil,nil,undefined,nil}}]

Problems with multipart boundary generation

Either cow_multipart:boundary() returns values that are incorrect, or cow_http_hd:parse_content_type(Hd) fails to parse valid headers (for example using multipart/form-data;boundary=Boundary, with Boundary including a slash).

More investigation needed, and the test for boundary creation should include parsing this header by cow_http_hd:parse_content_type since the header includes the boundary.

mts mimetype

.mts files are defined as <<"model">>, <<"vnd.mts">> in cow_mimetypes

I think it should be video/MP2T as shown in this RFC and on Wikipedia on the table on the right.

The file extensions generally used with AVCHD are called .mts and .m2ts. Both MTS and .m2ts are based on MPEG 2 standards (which is a type of MPEG format).

Call gun:cancel may lead to disconnect the whole connection.

After called gun:cancel, the corresponding stream would be removed in the state machine.
But it's possible it's response on the way, when gun receive the response, will disconnect the tcp connection with the reason:
{error, {connection_error, stream_closed,
'HEADERS frame received on a stream in closed or half-closed state. (RFC7540 5.1)'}, State}

In the function cow_http2_machine:client_headers_frame, the context stream can't be red out.

make tests fails, triq dependency seems to be missing

tried also with make triq but fails with another error.

tried adding

TEST_DEPS = triq
dep_triq = ...

in the Makefile and running make deps but it didn't work

output (some output removed):

make tests

 GEN    clean
 GEN    clean-app
 GEN    clean-ct
 ERLC   cow_multipart.erl cow_qs.erl cow_http_hd.erl cow_http.erl cow_spdy.erl cow_http_te.erl cow_date.erl cow_ws.erl cow_mimetypes.erl cow_cookie.erl
src/cow_http_hd.erl:129: can't find include lib "triq/include/triq.hrl"
src/cow_http_hd.erl:131: undefined macro 'LET/3'

...

src/cow_http_hd.erl:2223: Warning: function range/0 is unused
erlang.mk:257: recipe for target 'ebin/cowlib.app' failed
make: *** [ebin/cowlib.app] Error 1

Compiler Warnings

There are a few compiler warnings in OTP 19.0:

cowlib/src/cow_ws.erl:563: Warning: crypto:rand_bytes/1 is deprecated and will be removed in a future release; use crypto:strong_rand_bytes/1
......

Add support for IMF-fixdate formated date generation

RFC 7231 describes IMF-fixdate as a prefered format for the "Date" header field. This format is required by Amazon S3 (RFC 7231 obsoletes RFC 2616) and Riak S2. There is little difference between IMF-fixdate and RFC 2109 date formats, so it looks like we could reuse most of the code.

From RFC 7231 - Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content - 7.1.1.2. Date:

The "Date" header field represents the date and time at which the
message was originated, having the same semantics as the Origination
Date Field (orig-date) defined in Section 3.6.1 of [RFC5322]. The
field value is an HTTP-date, as defined in Section 7.1.1.1.

 Date = HTTP-date

An example is

 Date: Tue, 15 Nov 1994 08:12:31 GMT

undefined parse transform 'horse_autoexport'

clean clone, run make tests and get:

 ERLC   cow_multipart.erl cow_qs.erl cow_http_hd.erl cow_http.erl cow_spdy.erl cow_http_te.erl cow_date.erl cow_ws.erl cow_mimetypes.erl cow_cookie.erl
src/cow_multipart.erl: undefined parse transform 'horse_autoexport'
erlang.mk:359: recipe for target 'ebin/cowlib.app' failed
make[1]: *** [ebin/cowlib.app] Error 1
erlang.mk:402: recipe for target 'test-build' failed
make: *** [test-build] Error 2

cow_qs:unhex/1 can fail due to malformed input

It would be nice if the error could be explicit instead of function_clause just to make it simpler in the logs:

Ranch listener <0.1188.0> had connection process started with cloudi_x_cowboy_protocol:start_link/4 at <0.28900.17> exit with reason: {[{reason,function_clause},{mfa,{cloudi_http_cowboy_handler,handle,2}},{stacktrace,[{cloudi_x_cow_qs,unhex,"%",[{file,"src/cloudi_x_cow_qs.erl"},{line,345}]},{cloudi_x_cow_qs,parse_qs_name,3,[{file,"src/cloudi_x_cow_qs.erl"},{line,35}]},{cloudi_x_cowboy_req,qs_vals,1,[{file,"src/cloudi_x_cowboy_req.erl"},{line,294}]},{cloudi_http_cowboy_handler,handle,2,[{file,"src/cloudi_http_cowboy_handler.erl"},{line,136}]},{cloudi_x_cowboy_handler,handler_handle,4,[{file,"src/cloudi_x_cowboy_handler.erl"},{line,118}]},{cloudi_x_cowboy_protocol,execute,4,[{file,"src/cloudi_x_cowboy_protocol.erl"},{line,529}]}]},{req,[{socket,#Port<0.172196>},{transport,cloudi_x_ranch_tcp},{connection,keepalive},{pid,<0.28900.17>},{method,<<"POST">>},{version,'HTTP/1.1'},{peer,{{10,11,134,163},32523}},{host,<<"localhost">>},{host_info,undefined},{port,80},{path,<<"/cgi-bin/php/%63%67%69%6E/%70%68%70">>},{path_info,undefined},{qs,<<"%2D%64+%61%6C%75%6F%6E+%2D%64+%6D%6F%64+%2D%64+%73%75%68%6F%6E%3D%6F%6E+%2D%64+%75%6E%63%74%73%3D%22%22+%2D%64+%64%6E%65+%2D%64+%61%75%74%6F%5F%70%72%%74+%2D%64+%63%67%69%2E%66%6F%72%63%65%5F%72%65%64%69%72%65%63%74%3D%30+%2D%64+%74%5F%3D%30+%2D%64+%75%74+%2D%6E">>},{qs_vals,undefined},{bindings,[]},{headers,[{<<"host">>,<<"localhost">>},{<<"content-type">>,<<"text/html">>},{<<"x-forwarded-for">>,<<"95.211.184.137">>},{<<"x-forwarded-port">>,<<"80">>},{<<"x-forwarded-proto">>,<<"http">>},{<<"content-length">>,<<"1">>},{<<"connection">>,<<"keep-alive">>}]},{p_headers,[{<<"connection">>,[<<"keep-alive">>]}]},{cookies,undefined},{meta,[]},{body_state,waiting},{multipart,undefined},{buffer,<<"a">>},{resp_compress,false},{resp_state,waiting},{resp_headers,[]},{resp_body,<<>>},{onresponse,undefined}]},{state,...}],[{cloudi_x_cowboy_protocol,execute,4,[{file,"src/cloudi_x_cowboy_protocol.erl"},{line,529}]}]}

cowlib 2.7.2 is 2.7.0?

I saw cowlib 2.7.2, 2.7.1 from hex, so updated dependencies.. and mix does not work with following message:

Unchecked dependencies for environment dev:
* cowlib (Hex package)
  the dependency does not match the requirement "~> 2.7.2", got "2.7.0"
** (Mix) Can't continue due to errors on dependencies

I checked a few files, and it seems like cowlib 2.7.2 from hex says it's version 2.7.0 actually.

cat deps/cowlib/hex_metadata.config

{<<"app">>,<<"cowlib">>}.
{<<"build_tools">>,[<<"rebar3">>]}.
{<<"description">>,<<"Support library for manipulating Web protocols.">>}.
{<<"files">>,
 [<<"erlang.mk">>,<<"LICENSE">>,<<"Makefile">>,<<"README.asciidoc">>,
  <<"src">>,<<"src/cow_base64url.erl">>,<<"src/cow_cookie.erl">>,
  <<"src/cow_date.erl">>,<<"src/cow_hpack.erl">>,<<"src/cow_http.erl">>,
  <<"src/cow_http2.erl">>,<<"src/cow_http2_machine.erl">>,
  <<"src/cow_http_hd.erl">>,<<"src/cow_http_te.erl">>,
  <<"src/cow_iolists.erl">>,<<"src/cow_mimetypes.erl">>,
  <<"src/cow_mimetypes.erl.src">>,<<"src/cow_multipart.erl">>,
  <<"src/cow_qs.erl">>,<<"src/cow_spdy.erl">>,<<"src/cow_spdy.hrl">>,
  <<"src/cow_sse.erl">>,<<"src/cow_uri.erl">>,<<"src/cow_ws.erl">>,
  <<"src/cowlib.app.src">>,<<"include">>,<<"include/cow_inline.hrl">>,
  <<"include/cow_parse.hrl">>]}.
{<<"licenses">>,[<<"ISC">>]}.
{<<"links">>,[{<<"GitHub">>,<<"https://github.com/ninenines/cowboy">>}]}.
{<<"name">>,<<"cowlib">>}.
{<<"requirements">>,[]}.
{<<"version">>,<<"2.7.2">>}.

cat deps/cowlib/src/cowlib.app.src

{application, 'cowlib', [
	{description, "Support library for manipulating Web protocols."},
	{vsn, "2.7.0"},
	{modules, ['cow_base64url','cow_cookie','cow_date','cow_hpack','cow_http','cow_http2','cow_http2_machine','cow_http_hd','cow_http_te','cow_iolists','cow_mimetypes','cow_multipart','cow_qs','cow_spdy','cow_sse','cow_uri','cow_ws']},
	{registered, []},
	{applications, [kernel,stdlib,crypto]},
	{env, []}
]}.

duplicate headers should be de-duped in cow_spdy:build_headers/2

Properly implemented spdy clients will issue an error when there are duplicate header names. Since this isn't totally obvious and because cowboy_req can be used for both http and spdy I would say it be de-duped at the cowlib level.

https://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3-1#TOC-2.6.10-Name-Value-Header-Block

Duplicate header names are not allowed. To send two identically named headers, send a header with two values, where the values are separated by a single NUL (0) byte. A header value can either be empty (e.g. the length is zero) or it can contain multiple, NUL-separated values, each with length greater than zero. The value never starts nor ends with a NUL character. Recipients of illegal value fields MUST issue a stream error (Section 2.4.2) with the status code PROTOCOL_ERROR for the stream-id.

cow_qs:parse_qs crash on bad user request

following qs value would make it crash
cow_qs:parse_qs(<<"=aaaaaaaaaaaaaaaaaaa">>).

with error:
** exception error: no function clause matching
cow_qs:parse_qs_name(<<"=aaaaaaaaaaaaaaaaaaa">>,[],<<>>) (src/cow_qs.erl, line 34)

and thus crash the server request processing process, would it crash or as the doc said, return fail status and thus caller can return the default value?

websockets error for iolist data

It is Impossible to send anything but binary into websocket

this code doesn't work

websocket_handle({text, Msg}, Req, State) ->
    Reply = ["a", "b"]
    {reply, {text, Reply}, Req, State};

because in cow_ws payload_length calculated by direct call of byte_size function

frame({text, Payload}, _) ->
    Len = payload_length(Payload),
    [<< 1:1, 0:3, 1:4, 0:1, Len/bits >>, Payload];
frame({binary, Payload}, _) ->
    Len = payload_length(Payload),
    [<< 1:1, 0:3, 2:4, 0:1, Len/bits >>, Payload].

payload_length(Payload) ->
    case byte_size(Payload) of
        N when N =< 125 -> << N:7 >>;
        N when N =< 16#ffff -> << 126:7, N:16 >>;
        N when N =< 16#7fffffffffffffff -> << 127:7, N:64 >>
    end.

Maybe add an iolist_to_binary call for non-binary data?

Upgrade tokens are case sensitive

Based on a recent discussion on httpbis. Confusion around websocket/WebSocket, it sounds like Cowboy should accept both for that particular case.

Chokes on (invalid) bodies that contain leading spaces

I get the following crash when attempting to make a GET-request with gun to www.tripod.com:

15:21:22.106 [error] CRASH REPORT Process <0.20289.10> with 0 neighbours crashed with reason: no function clause matching cow_http_te:chunked_len(<<" \r\n<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>301 Moved Permanently...">>, 0, <<>>, 253) line 173

Code to reproduce:

application:ensure_all_started(gun).

{ok, ConnPid} = gun:open("www.tripod.com", 80).
{ok, _Protocol} = gun:await_up(ConnPid).

StreamRef = gun:get(ConnPid, "/").

case gun:await(ConnPid, StreamRef) of
    {response, fin, _Status, _Headers} ->
            no_data;
    {response, nofin, _Status, _Headers} ->
            {ok, _Body} = gun:await_body(ConnPid, StreamRef);
    Other ->
            io:format("Other ~p~n", [Other])
end.

The server identifies itself as "Squeegit/1.2.5 (3_sir)" which appears to be some AngelFire legacy server.

sec-websocket-protocol values are case insensitive

According to this document, https://ninenines.eu/docs/en/cowboy/1.0/manual/cowboy_req/

The values for the header sec-websocket-protocol are case sensitive. However I am noticing that after parsing the header using cowboy_req, the value is coming back lower case.

Relevant bits of code are here:

https://github.com/ninenines/cowlib/blob/master/src/cow_http_hd.erl#L2626-L2627
https://github.com/ninenines/cowlib/blob/master/src/cow_http_hd.erl#L3382-L3392

I suspect this is a bug, but not 100% sure. I'm looking for the spec and clarification that tells me if the values for sec-websocket-protocol should be sensitive or not.

cow_sse.erl failed

===> Compiling _build/default/lib/cowlib/src/cow_sse.erl failed
_build/default/lib/cowlib/src/cow_sse.erl:32: syntax error before: ':='

_build/default/lib/cowlib/src/cow_sse.erl:44: type event() undefined

cow_qs:qs/1 percent-encode the reserved characters like comma

According to the examples in OpenAPI
The query in URI could be something like /users?id=3,4,5.
And according to RFC3986:

The purpose of reserved characters is to provide a set of delimiting
characters that are distinguishable from other data within a URI.
URIs that differ in the replacement of a reserved character with its
corresponding percent-encoded octet are not equivalent. Percent-
encoding a reserved character, or decoding a percent-encoded octet
that corresponds to a reserved character, will change how the URI is
interpreted by most applications. Thus, characters in the reserved
set are protected from normalization and are therefore safe to be
used by scheme-specific and producer-specific algorithms for
delimiting data subcomponents within a URI.

I suppose enforcing the percent-encode for reserved characters is not that reasonable. Could you help take a look?

cow_hpack:table_insert may have the state with dyn_table contains entry that is larger than the max_size

According to RFC7541 4.4:

If the size of the new entry is less than or equal to the maximum size, that entry is added to the table. It is not an error to attempt to add an entry that is larger than the maximum size; an attempt to add an entry larger than the maximum size causes the table to be emptied of all existing entries and results in an empty table.

If the EntrySize itself larger than the max_size in state, the cow_hpack:table_insert/2 will still return a state with this entry in the dyn_table, it should return the state with empty dyn_table if the EntrySize > MaxSize.

cow_qs:qs can not have integer value?

Hi!
cow_qs:qs([{<<"digit">>, 1}]). will throw error:

** exception error: no function clause matching cow_qs:urlencode(1,<<"&digit=">>) (/home/dcy/hisir/epush/_build/default/lib/cowlib/src/cow_qs.erl, line 429)
     in function  cow_qs:qs/2 (/home/dcy/hisir/epush/_build/default/lib/cowlib/src/cow_qs.erl, line 183

Can't it have integer value?

Update hex version

Hey,
following this commit, a7d5141#diff-5b3b33d473fd0bc66ff7e18709099694L427

I see that the hex package does not have this commit, as a result the make task fails on OTP 19. Here is the log:

Sushruths-MacBook-Pro:barrel-platform sivsushruth$ MIX_DEBUG=1 mix compile
** Running mix loadconfig (inside Barrel.Mixfile)
** Running mix compile (inside Barrel.Mixfile)
** Running mix loadpaths (inside Barrel.Mixfile)
** Running mix archive.check (inside Barrel.Mixfile)
** Running mix deps.check (inside Barrel.Mixfile)
** Running mix deps.precompile (inside Barrel.Mixfile)
==> cowlib
 ERLC   cow_cookie.erl cow_date.erl cow_http.erl cow_http_hd.erl cow_http_te.erl cow_mimetypes.erl cow_multipart.erl cow_qs.erl cow_spdy.erl
compile: warnings being treated as errors
src/cow_multipart.erl:392: crypto:rand_bytes/1 is deprecated and will be removed in a future release; use crypto:strong_rand_bytes/1
make[1]: *** [ebin/cowlib.app] Error 1
make: *** [all] Error 2
** (Mix.Error) Could not compile dependency :cowlib, "make" command failed. You can recompile this dependency with "mix deps.compile cowlib", update it with "mix deps.update cowlib" or clean it with "mix deps.clean cowlib"
    (mix) lib/mix.ex:274: Mix.raise/1
    (mix) lib/mix/project.ex:211: Mix.Project.in_project/4
    (elixir) lib/file.ex:1145: File.cd!/2
    (mix) lib/mix/dep.ex:173: Mix.Dep.in_dependency/3
    (mix) lib/mix/tasks/deps.compile.ex:206: Mix.Tasks.Deps.Compile.do_command/5
    (mix) lib/mix/tasks/deps.compile.ex:76: anonymous fn/4 in Mix.Tasks.Deps.Compile.compile/2
    (elixir) lib/enum.ex:1184: Enum."-map/2-lists^map/1-0-"/2
    (mix) lib/mix/tasks/deps.compile.ex:65: Mix.Tasks.Deps.Compile.compile/2

I feel version number needs update and republished to hex.
Thoughts @essen ?

windows build issues again on 1.3

Hi,

Please s it possible you apply similar updates as you did the last time to the Cowboy family of libs to avoid this windows build errors that seem to creep up in your newer builds.

Maybe if you use the updated erlang.mk file from the last time...

Regards.

base64 url encode/decode

The characters "=", "/", "+" are not allowed in query params and cookies.
http://en.wikipedia.org/wiki/Base64#URL_applications
Following are base64 encode/decode functions that are safe in URL and cookies.
Base64 values are often used to sign API requests base64(hmac(data)).

Other implementations:
https://github.com/basho/riak_control/blob/master/src/base64url.erl
https://github.com/mochi/mochiweb/blob/master/src/mochiweb_base64url.erl

encode_base64_url(Url) ->
    encode_base64_url(base64:encode(Url), <<>>).

encode_base64_url(<<$=, Rest/binary>>, Res) ->
    encode_base64_url(Rest, <<Res/binary, $.>>);
encode_base64_url(<<$/, Rest/binary>>, Res) ->
    encode_base64_url(Rest, <<Res/binary, $_>>);
encode_base64_url(<<$+, Rest/binary>>, Res) ->
    encode_base64_url(Rest, <<Res/binary, $->>);
encode_base64_url(<<C:8, Rest/binary>>, Res) ->
    encode_base64_url(Rest, <<Res/binary, C>>);
encode_base64_url(<<>>, Res) -> Res.

decode_base64_url(Url64) when is_list(Url64) ->
    decode_base64_url(list_to_binary(Url64));

decode_base64_url(Url64) ->
    Padding = case byte_size(Url64) rem 4 of
        2 ->
            <<"==">>;
        3 ->
            <<"=">>;
        _ ->
            <<"">>
    end,
    base64:decode(decode_base64_url(<<Url64/binary, Padding/binary>>, <<>>)).

decode_base64_url(<<$., Rest/binary>>, Res) ->
    decode_base64_url(Rest, <<Res/binary, $=>>);
decode_base64_url(<<$_, Rest/binary>>, Res) ->
    decode_base64_url(Rest, <<Res/binary, $/>>);
decode_base64_url(<<$-, Rest/binary>>, Res) ->
    decode_base64_url(Rest, <<Res/binary, $+>>);
decode_base64_url(<<C:8, Rest/binary>>, Res) ->
    decode_base64_url(Rest, <<Res/binary, C>>);
decode_base64_url(<<>>, Res) -> Res.

Can't parse headers which are not one packet.

I have binary string of headers:


A = <<"Host: free-proxy.cz\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3\r\nAccept-Encoding: gzip, deflate\r\nReferer: https://yandex.ru/clck/jsredir?bu=3fa1&from=yandex.ru%3Bsearch%2F%3Bweb%3B%3B&text=&etext=2076.b5GauwlHkdkF6iWi3-g_YKLfHsBVksix2txIU_QQIVmeJm6TOskSSSYb4Dhn8Dp7.1d60900edbe73c180a6fe4ffec134d2acd72f364&uuid=&state=PEtFfuTeVD5kpHnK9lio9dFa2ePbDzX7kDTG1R8Zf0DD4IGUNQDuhGKi4brPl_RBngCmTtTUX7iLjRo-k08ymQ,,&&cst=AiuY0DBWFJ5fN_r-AEszk2ne6EoDAqLP5zgBY-i4ZWQs-NwL36lnqauAJ9xQY7ILngPL0MRNui1E_7cf2rTG-y8GdjebO2kmYikyF-xH6XonhZZIUAv58izrkstdNkzf0uS4Hu2ZqNdRBzketZ6Y398O6D5fuefPlnF5Jq9edXZ-Gc9fp6gmRCH0WALbk-FmUVSlhDQmCbdCDMafBksCR4RnzM2ZbeqOeGc_gikxx_aAgod-5lDLTJD-XYWlXJOdWVEG2LD9elIt-9bqFi3A9Aul6kUf5tc11Z4Q53gtVtqA9BJM7gIl3U_-uCYaJ4ne9mf1S19Ik-sPxqq6BqlpJ0znoWP-Ty7-inFUbdc0NdVi09H-sTn5dLxDrEm7IheJ-k4jMAFf8v-zK9bbTTfjMdPuE5egosnjFTN5wvCOYsOUCEB4fj7epPFmlXTUUIoh8oZf4W0I-mS3TKJ1_FTd2iE4fD6mfIsYLUIn56ojbuhEC5vkXoE6rnX2NglZRRynGTwGI43EylEGAChvTYT-6CZuoM07Xpjcr6Q_6hfNuGDsiOaj-VcF5lvKpz4qk7C-8guHj5fzP6Mi0hOMQugagXMUS34pVlp5NzDL4RFliOTTNpp9iKfPv0ypHI7SrHT_5UOUcgriUHjv30CNrrNzQcsKbziwBVicKGK-svts8rF_C0jTeBwwEAgeoFF_F1oGbCHoffwwe7B6bQmE2FEiJjOwwmr2uM_5OvWEiBSl5lQ,&data=UlNrNmk5WktYejR0eWJFYk1LdmtxdDZkOV9BTXZoM2pCNS1EaWJON">>.

cow_http:parse_headers(A).
** exception error: no function clause matching cow_http:parse_hd_value(<<>>, 
[{<<"accept-encoding">>,<<"gzip, deflate">>}, 
{<<"accept-language">>, <<"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3">>},
{<<"accept">>, <<"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8">>},
{<<"user-agent">>, <<"Mozilla/5.0 (X11; Linux x86_64; rv:63.0) Gecko/20100101 Firefox/63.0">>},
{<<"host">>,<<"free-proxy.cz">>}],
<<"referer">>, <<"https://yandex.ru/clck/jsredir?bu=3fa1&from=yandex.ru%3Bsearch%2F%3Bweb%3B%3B&text=&etext=2076.b5Gau"...>>) 
(/............/cow_http.erl, line 209)

Seems it is not finished and should be continued on next packet, but i don't understand way how i can understand is header string completed for parsing or not. Could you help me ? How i can expects end of header at next packet ?

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.