ninenines / cowboy Goto Github PK
View Code? Open in Web Editor NEWSmall, fast, modern HTTP server for Erlang/OTP.
Home Page: https://ninenines.eu
License: ISC License
Small, fast, modern HTTP server for Erlang/OTP.
Home Page: https://ninenines.eu
License: ISC License
In order to get Hixie76 through a HAProxy loadbalancer the server must send response headers before the request nonce is received. In other words: before haproxy will send extra data from the client it expects the server to respond to the header. Current cowboy implementation does not support that. Example (nc localhost 8080
and paste):
GET /echo/000/afc7f9ea-5b6f-4c94-bc2e-4fe7f5a74241/websocket HTTP/1.1
Host: localhost:8080
Accept-Encoding: identity
Origin: http://localhost:8080
Connection: Upgrade
Upgrade: WebSocket
Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
Result: cowboy waits.
Expected result: response headers.
How to trigger expected result: type eight more bytes and press enter.
Cookies don't seem to be handled right as large cookies cause an error.
Right now cookies headers are stored as headers with no code to parse them. We need to read them and store them in a separate list for easier handling.
We also need encoding support. The following project could be used: https://github.com/klaar/quoted.erl
Currently, every dispatch rule in Cowboy is dispatched from the root URL, i.e. /
. The dispatch table is thus "flat" and does not really reflect the hierarchical nature of the Web. I would like to be able to write the dispatch rules as a tree instead of a simple list, with nodes and leaves.
See the following dispatch rules:
{'_', [
{[<<"foo">>, <<"bar">>], ohai, []},
{[<<"foo">>, <<"qux">>], ohai, []},
{[<<"foo">>, <<"blah">>, <<"blah">>], ohai, []},
{'_', kthx, []}
]}
Compare with:
{'_', [
{[<<"foo">>], [
{[<<"bar">>], ohai, []},
{[<<"qux">>], ohai, []},
{[<<"blah">>, <<"blah">>], ohai, []}
]},
{'_', kthx, []}
]}
Of course, this would serve no purpose if it was just a way to save a few keystrokes. I also want this to change the way the returned #req
records are built.
A request to /foo/bar
currently returns a #req
record where path
equals to [<<"foo">>, <<"bar">>]
and raw_path
to something like <<"/foo/bar">>
. But what if ohai
is a file-oriented handler which files are to be served from <<"/path/to/files">>
? Let's add this path as a option to the handler in the dispatch rules:
{'_', [
{[<<"foo">>, <<"bar">>], ohai, [{root, <<"/path/to/files">>}]},
{[<<"foo">>, <<"qux">>], ohai, [{root, <<"/path/to/files">>}]},
{[<<"foo">>, <<"blah">>, <<"blah">>], ohai, [{root, <<"/path/to/files">>}]},
{'_', kthx, []}
]}
So the handler is now correctly configured, but the path
field is still [<<"foo">>, <<"bar">>]
, naively ohai
will try to serve <<"/path/to/files/foo/bar">>
instead of <<"/path/to/files/bar">>
. What can be done to strip this initial token? Yet another prefix
option could be introduced:
{'_', [
{[<<"foo">>, <<"bar">>], ohai, [{root, <<"/path/to/files">>}, {prefix, [<<"foo">>]}]},
{[<<"foo">>, <<"qux">>], ohai, [{root, <<"/path/to/files">>}, {prefix, [<<"foo">>]}]},
{[<<"foo">>, <<"blah">>, <<"blah">>], ohai, [{root, <<"/path/to/files">>}, {prefix, [<<"foo">>]}]},
{'_', kthx, []}
]}
In my opinion this is not the right way to go: there is now a lot of redundant information in the dispatch rules and nobody can guarantee every handler writer will use the same option name. What I would like to see is a hierarchical dispatch tree where only the matched segments from the tree leaves would end up in the path
field of the #req
record passed to the handler.
Given the following tree:
{'_', [
{[<<"foo">>], [
{[<<"bar">>], ohai, [{root, <<"/path/to/files">>}]},
{[<<"qux">>], ohai, [{root, <<"/path/to/files">>}]},
{[<<"blah">>, <<"blah">>], ohai, [{root, <<"/path/to/files">>}]}
]},
{'_', kthx, []}
]}
A request to /foo/bar
would return a #req
record with a path
field to [<<"bar">>]
and a raw_path
field left unchanged w.r.t. the former flat dispatch rules, thus making ohai
correctly try to serve <<"/path/to/files/bar">>
.
This change would ease configuration of my own fcgi handler and I think it would also simplify @klaar's cowboy_static handler while not breaking anything currently in use. The nodes could also have another element to set common options found in its children, like root
in my example but this is not relevant to my case.
Dunno if I explained myself correctly, feel free to ask me any question you have.
Therefore we should be able to terminate all running children when stopping a listener. And we should do it.
We want to allow returning {ok, Req, State, hibernate} or {reply, Data, Req, State, hibernate} to start hibernating a websocket process, just before the receive call.
Hey guys.
I've been working on a stream handler that acts as a common interface for many different ways of doing streaming, like websockets and long polling, and this has got me into questioning a choice I made about websockets before. I'm hoping feedback can help me decide on whether we should change the interface or leave it as is.
Basically, right now websockets have 3 functions: websocket_init, websocket_handle and websocket_terminate. My concern here is that websocket_handle actually has two uses: websocket_handle({websocket, Data}) and websocket_handle(Info). Would it make more sense to have websocket_handle(Data) and websocket_info(Info) instead?
Think about it, discuss, and let's decide on the best approach to use here.
Thanks.
Functions should fail as fast as possible to help a developer in finding problems. cowboy_http_req:binding() accepts binaries when it will never actually find a bound variable with a binary. It should do when is_atom() to help a developer catch mistakes early. If there's other cases of that for the cowboy api it would be nice if they failed immediately instead of pretending to not work when they in fact, will never work.
The stunnel tool allows to forward https/wss connections to http/ws directly. This means that websocket connections will fail because of the Sec-Websocket-Origin header that needs to reply a right ws/wss URL depending on what the browser sees and not on what the Cowboy server serves.
A patch submitted to misultin and pinged to me by RJ can be found here for more details: RJ/misultin@41f92a2
Patches and ct tests using stunnel welcome.
The following locations use the external quoted.erl library:
src/cowboy_dispatcher.erl:67: [quoted:from_url(Token) || Token <- EncodedPath].
src/cowboy_http_req.erl:456: [Token] -> {quoted:from_url(Token), true};
src/cowboy_http_req.erl:457: [Name, Value] -> {quoted:from_url(Name), quoted:from_url(Value)}
External dependencies make it more difficult to integrate cowboy into existing applications. In particular, this quoted library uses a NIF implementation, and while a non-NIF implementation also exists in the library, it takes some manual manipulation to use it - the concept being here not wanting to use a NIF dependency either.
So, I'm bringing this up to see what the mind set is behind the use of the quoted.erl library. I'd expect a native parser in cowboy - http handling is a major part of cowboy, it is odd that this aspect is outsourced... So does the roadmap include implementing this, and would a patch be rejected? If not could that patch just be the quoted.erl erlang module copied over with appropriate adjustments?
Here http://www.ostinelli.net/a-comparison-between-misultin-mochiweb-cowboy-nodejs-and-tornadoweb/ cowboy ends up losing a little bit to misultin.
Would be interesting to investigate why a little bit, though certainly not a priority.
For hybi10 the Upgrade
header should be checked case-insensitive.
GET /echo/000/0915ea93-b956-4dfe-bb0a-16f073df0cfc/websocket HTTP/1.1
Host: localhost:8080
Accept-Encoding: identity
Sec-WebSocket-Version: 8
Connection: Upgrade
Upgrade: WebSocket
Sec-WebSocket-Origin: http://pmx
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Result: 400 Bad Request.
Expected result: should work
How to trigger expected result: change WebSocket
to websocket
First tagged release.
Less important but still missing is the chunked transfer encoding for requests.
Hi there,
Me again. Have run into the same kind of trouble as last time.
Here's the case...
Was trying to get an SSL connection properly established.
Couldnt' really find any examples, but the test code contained some.
But...I worked hastily, so first I glanced over the full code and at first coded just the following:
cowboy:start_listener(https, 100,
cowboy_ssl_transport, [ {port, 16387}, {certfile, DataDirCert ++ "moorooboorai.com.crt"},
{keyfile, DataDirKey ++ "www_moorooboorai_com.key"}, {password, "really-really-secret"}],
cowboy_http_protocol, [{dispatch, Dispatch}]
),
Which didn't work. It ran, as in "fired up", but it then just kep silent on me when I tried to connect.
Funny. No crashes. No error reports.
Then I took a better look at the test code and picked up on crypto, public_key and ssl being started first.
So then I coded this.
application:start(crypto),
application:start(public_key),
application:start(ssl),
cowboy:start_listener(https, 100,
cowboy_ssl_transport, [ {port, 16387}, {certfile, DataDirCert ++ "moorooboorai.com.crt"},
{keyfile, DataDirKey ++ "www_moorooboorai_com.key"}, {password, "still-a-secret"}],
cowboy_http_protocol, [{dispatch, Dispatch}]
),
Although surely not the best place to put this - that's not the point - it worked.
In 'other' http libs I'm sure to get warnings about the apps not being started.
So, somehow, I think you guys are able to surpress or smother them.
Or - and that's a good possibility - I am taking some wrong turns.
Anyways. As before. Thought you guys would like to know about this.
Regards,
Jeroen.
At the moment cowboy uses error_terminate/2 which replies immediately with the error code.
The error_terminate behaviour should be definable either by passing a fun or callback module to the http protocol with the current behaviour continuing to be the default.
Hi!
Just installed Firefox 6.0, eager for it's now -again- native WebSocket support.
On first effort my client-side code broke, it used a new WebSocket call.Fair enough this now should be MozWebSocket. See https://developer.mozilla.org/en/WebSockets/WebSockets_reference/WebSocket, section Gecko Notes ~ if interested, that is.
Fiddled around a bit and noticed a very tiny change: the incoming request now spells <<"websocket">> instead of <<"WebSocket">>. This breaks the init (demo websocket) code. However, 'fixing' that by adding a now lowercase clause, doesn't help out. The websocket (wouldn't dare to spell any other way now) simply fails silently, with the browser unable to connect.
Did read the "websocket draft changed" issue, but couldn't find anything that would help out there... They are now apparently supporting "protocol version 07 for Firefox 6", as stated here:http://hacks.mozilla.org/2011/08/firefox6/, section NET.
So. Was wondering. Is there anything going on inside Cowboy that needs updating for this 'new' websocket Mozilla?
Eager to learn! (And thanks for this top-notch software so far...)
Regards,
Jeroen.
All ideas about improving the performance should be posted in this ticket.
Hi there, Cowboys!
Love the stuff so far. However, just got 'hung' on a bug (?) whilst developing a "sign in with Facebook" flow using Cowboy.
Offending stuff looking like this
Which (of course?) didn't return but got accepted anyways without an exception/error, what-have-you.
Case of a copy-past-devil combined with a too-hastily-writing-code illness.
Solution, as always, simple enough but not easily found when in haste: don't forget parameters
Which worked out fine.
But maybe you guys want to 'trip and halt (or raise exceptions)' or what-have-you on this?
Anyways, my two cents.
Regards,
Jeroen.
Probably makes some keep-alive connections fail earlier than expected.
Add req_empty_lines=0 in the state here to fix: https://github.com/extend/cowboy/blob/master/src/cowboy_http_protocol.erl#L249
Will commit later when I get more time to do it.
I have pulled and have 8c1ac63 as HEAD.
From checks it seems as if the record sent to parse_request has one extra field
When sending websocket requests to cowboy I get:
2011-10-06 18:00:31.612 [error] emulator Error in process <0.485.0> on node '[email protected]' with exit value: {function_clause,[{cowboy_http_protocol,parse_request,[{state,<0.377.0>,#Port<0.4100>,cowboy_tcp_transport,[{'_',[{[<<4 bytes>>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler,[{docroot,"/home/ubuntu/myserv/lib/myserv-0.7/p...
2011-10-06 18:00:31.639 [error] <0.378.0> Supervisor cowboy_requests_sup had child cowboy_requests_sup started with {cowboy_requests_sup,start_request,undefined} at <0.485.0> exit with reason no function clause matching cowboy_http_protocol:parse_request({state,<0.377.0>,#Port<0.4100>,cowboy_tcp_transport,[{'_',[{[<<112,105,110,103>>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler,[{docroot,[47,104,111,109,101,47,117,98,117,110,116,117,47,115,105,103,115,101,114,118,47,108,105,98,47,115,105,103,115,101,114,118,45,48,46,55,47,112,114,105,118,47,119,119,119]},{endpoint_type,ws}]}]}],undefined,0,5,5000,keepalive,<<71>>}) in context child_terminated
2011-10-06 18:00:41.430 [error] emulator Error in process <0.486.0> on node '[email protected]' with exit value: {function_clause,[{cowboy_http_protocol,parse_request,[{state,<0.377.0>,#Port<0.4159>,cowboy_tcp_transport,[{'_',[{[<<4 bytes>>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler,[{docroot,"/home/ubuntu/myserv/lib/myserv-0.7/p...
2011-10-06 18:00:41.437 [error] <0.378.0> Supervisor cowboy_requests_sup had child cowboy_requests_sup started with {cowboy_requests_sup,start_request,undefined} at <0.486.0> exit with reason no function clause matching cowboy_http_protocol:parse_request({state,<0.377.0>,#Port<0.4159>,cowboy_tcp_transport,[{'_',[{[<<112,105,110,103>>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler,[{docroot,[47,104,111,109,101,47,117,98,117,110,116,117,47,115,105,103,115,101,114,118,47,108,105,98,47,115,105,103,115,101,114,118,45,48,46,55,47,112,114,105,118,47,119,119,119]},{endpoint_type,ws}]}]}],undefined,0,5,5000,keepalive,<<71>>}) in context child_terminated
2011-10-06 18:00:42.737 [error] emulator Error in process <0.487.0> on node '[email protected]' with exit value: {function_clause,[{cowboy_http_protocol,parse_request,[{state,<0.377.0>,#Port<0.4160>,cowboy_tcp_transport,[{'_',[{[<<4 bytes>>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler,[{docroot,"/home/ubuntu/myserv/lib/myserv-0.7/p...
Currently, only a 400 can be returned, what if we wish to return our own statuses/bodies/headers? (For example, 503 when server is crowded).
We need to accept password-less SSL certificates. Right now the password is required.
On errors, websocket_terminate isn't called. We probably want to call it anyway so the handler can clean up.
http://dev.w3.org/html5/websockets/
Editor's Draft 28 July 2011
Instead of logging by default like most servers do we should just send notifications using gen_event which can then be handled by a separate process. This would allow us to get real-time stats, just log, or do any other operation on the events received.
UBUNTU Version: 11.10
Erlang version: R14B04
HEAD commit id: 66da37e
We have a test on amazon EC2 in which we have a single server and websocket clients connecting to it at a rate of 1000 connections per sec. The clients are also running on amazon. After 340000 clients, we begin to get:
([email protected])101> 16:17:38.189 [error] Supervisor cowboy_acceptors_sup had child {acceptor,<0.166.0>,79} started with cowboy_acceptor:start_link(#Port<0.4369>, cowboy_tcp_transport, cowboy_http_protocol, [{dispatch,[{'_',[{[<<"ping">>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler...}]}]}...], 1024, <0.164.0>, <0.165.0>) at <0.245.0> exit with reason {timeout,{gen_server,call,[<0.164.0>,{add_connection,default,<0.10127.10>}]}} in context child_terminated
16:17:56.330 [error] Supervisor cowboy_acceptors_sup had child {acceptor,<0.374.0>,93} started with cowboy_acceptor:start_link(#Port<0.4393>, cowboy_tcp_transport, myserv_http_or_flash_protocol, [{dispatch,[{'_',[{[<<"ping">>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler...}]}]}...], 1024, <0.372.0>, <0.373.0>) at <0.467.0> exit with reason {timeout,{gen_server,call,[<0.372.0>,{add_connection,default,<0.10137.10>}]}} in context child_terminated
16:17:56.396 [error] Supervisor cowboy_acceptors_sup had child {acceptor,<0.374.0>,95} started with cowboy_acceptor:start_link(#Port<0.4393>, cowboy_tcp_transport, myserv_http_or_flash_protocol, [{dispatch,[{'_',[{[<<"ping">>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler...}]}]}...], 1024, <0.372.0>, <0.373.0>) at <0.469.0> exit with reason {timeout,{gen_server,call,[<0.372.0>,{add_connection,default,<0.10138.10>}]}} in context child_terminated
16:17:56.421 [error] Supervisor cowboy_acceptors_sup had child {acceptor,<0.374.0>,20} started with cowboy_acceptor:start_link(#Port<0.4393>, cowboy_tcp_transport, myserv_http_or_flash_protocol, [{dispatch,[{'_',[{[<<"ping">>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler...}]}]}...], 1024, <0.372.0>, <0.373.0>) at <0.394.0> exit with reason {timeout,{gen_server,call,[<0.372.0>,{add_connection,default,<0.10139.10>}]}} in context child_terminated
16:17:56.504 [error] Supervisor cowboy_acceptors_sup had child {acceptor,<0.374.0>,73} started with cowboy_acceptor:start_link(#Port<0.4393>, cowboy_tcp_transport, myserv_http_or_flash_protocol, [{dispatch,[{'_',[{[<<"ping">>],myserv_healthcheck_handler,[]},{'_',myserv_websocket_handler...}]}]}...], 1024, <0.372.0>, <0.373.0>) at <0.447.0> exit with reason {timeout,{gen_server,call,[<0.372.0>,{add_connection,default,<0.10140.10>}]}} in context child_terminated
16:17:56.557 [error] gen_server redis_srv terminated with reason: {timeout,{gen_server,call,[stat_srv,{global_metrics,hide}]}}
16:17:56.596 [error] CRASH REPORT Process redis_srv with 1 neighbours crashed with reason: {timeout,{gen_server,call,[stat_srv,{global_metrics,hide}]}}
I think this may be a timeout in https://github.com/extend/cowboy/blob/25ae2028d6a9ce516b01f0ec126abeab00eb329d/src/cowboy_listener.erl#L90
Do you have any idea what may be causing this? When running a similar test on UBUNTU 11.04 and erlang R14B03 with older cowboy revisions I was able to get about 500000 connections, now I am getting problems after ~340000.
It's implemented by all servers except IE and is probably a better choice than websockets if you don't need to push data from the client often.
Cowboy_http_req:body requires content-length
header to be set.
https://github.com/extend/cowboy/blob/master/src/cowboy_http_req.erl#L278
This is incorrect AFAICT. For example node.js
http.request
by default uses Transfer-Encoding: chunked
on outgoing requests:
POST / HTTP/1.1
Host: localhost:8080
Connection: close
Transfer-Encoding: chunked
[...]
Similar to MochiWeb's mochiweb_request:recv_body/1
:
%% @spec recv_body(integer()) -> binary()
%% @doc Receive the body of the HTTP request (defined by Content-Length).
%% Will receive up to MaxBody bytes.
recv_body(MaxBody) ->
...
We need the following options:
It should trigger errors instead of just truncating like erlang:decode_packet is doing.
I think, it should be good to have ability to set cookies in the request handling function, not only in the end of it:
{ok, Req1} = cowboy_http_req:set_cookie(Req, Key, Value),
I can add this feature, if you are not against.
I'm getting these errors:
=ERROR REPORT==== 30-Oct-2011::02:22:38 ===
Error in process <0.13205.1> on node 'cool@node' with exit value: {{badmatch,{error,timeout}},[{cowboy_http_websocket,websocket_handshake,3}]}
Anyone else getting this?
Cowboy needs to have the option to allow having a receive loop in an HTTP handler, just like websocket, except it would only allow one reply (atomic or streamed). The receive loop would be calling a separate function (for example loop/3, info/3 or handle/3) with the message received. You can enable looping by returning {loop, Req, State} or {loop, Req, State, hibernate} from handle/2. The callback is of course optional and normal HTTP handlers don't need to define it. Finally, this mechanism will handle connection closing when it detects it. Timeouts handling will be left to the application, like websockets.
If you're using keep-alive and never close the connection, some of the catch or try/catch constructs will just keep adding to the stacktrace (or some other kind of stack for exceptions) and memory will quickly be filled. Apparently any recursion within a single "catch" or within a "try of" or within a "try catch" would just add to the stack.
Thanks to lpgauth for reporting this issue initially and the IRC guys for the additional help and explanations.
An improvement on the previous behaviour was introduced in: d9da533
The problem is that right now, the module tuple for the supervisor is []. When the OTP release handler will try to upgrade code, it will navigate through the OTP supervision tree and ask all of the supervisors to tell them what kind of code their children are running. By leaving it to an empty list, the module will be ignored and not upgraded.
To fix this, the module name must be added to the empty list ([cowboy_acceptor]). However, the acceptors are accepting (a blocking operation) and will be killed after a while if they do not reply to release_handler's requests.
The behaviour of the acceptors should be changed to accept only for a few (milli)seconds at a time, look for new messages (including upgrade ones, coming from the sys
module), react to them, and then start accepting over again.
In version 0.2.0 a binary expression is used to build each line in the header. See: https://github.com/extend/cowboy/blob/bb469f6c3d2745251b333c89ef146624c934d5e2/src/cowboy_http_req.erl#L345
Because of this all header values must be converted to binaries before a response is sent to the client. This is a minor annoyance because I must remember this as a user. This also leaves room for a minor performance optimization, all header values that are generated as iolists by the user must be copied into a binary twice.
The expression to generate headers would be better if written as:
Headers5 = [[Key, <<": ">>, Value, <<"\r\n">>]
|| {Key, Value} <- Headers4],
Cowboy should not set content-length
for websockets.
GET /echo/000/f2257c26-4889-409a-92ed-ef470750b93a/websocket HTTP/1.1
Host: localhost:8080
Accept-Encoding: identity
Sec-WebSocket-Version: 7
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Origin: http://pmx
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Content-Length: 0
Date: Tue, 18 Oct 2011 14:39:20 GMT
Sec-Websocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Server: Cowboy
Upgrade: websocket
Result: Content-length header present
Expected result: no content-length header
From: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
Additionally, if the client is a web browser, it supplies /origin/.
Later:
- Optionally, an "Origin" header field. This header field is sent
by all browser clients. A connection attempt lacking this
header field SHOULD NOT be interpreted as coming from a browser
client.
As far as I remember Cowboy websocket machinery requires Origin header.
Something ugly like this can be done in the meantime, but it'd be better to have an extra function somewhere to do it without resorting to this trick: https://github.com/Vagabond/gen_smtp/blob/cowboy-protocol/src/gen_smtp_server_session.erl#L581
Got cowboy crashed with this script:
for a in
seq 1 100500; do ( (echo "GET / HTTP/1.1"|nc 10.1.3.251 8081 2>/dev/null 1>>/root/log) & ) ;done
Logs are full of errors like
=ERROR REPORT==== 11-Nov-2011::18:48:47 ===
Error in process <0.434.0> on node '[email protected]' with exit value: {undef,[{quoted,from_url,[<<6 bytes>>]},{cowboy_dispatcher,'-do_split_path/2-lc$^0/1-0-',1},{cowboy_dispatcher,split_path,1},{cowboy_http_protocol,request,2}]}
It would be great if cowboy handled Content encoding transparently and took care of compressing the reply body.
An example of or an included static file http handler would be very useful.
A common use case is when we want to embed cowboy underneath the supervisor tree of another application. In this case, we don't want the listener to be added to the supervisor of cowboy, but rather, we want it to be added underneath a supervisor in the hosting application.
An easy way to do this is to create a s child spec invoking cowboy_listener_sup:start_link/5
with the correct parameters. However, this suggestion is to make the cowboy
module contain a function that will produce the right kind of ChildSpec
for us. That way, embedding cowboy in your supervisor amounts to calling this function and shoving the returned spec into your supervisor tree structure.
I have a simple websocket server that gives this output:
websocket handler got request: {http_req,#Port<0.2747>,cowboy_tcp_transport,
keepalive,'GET',
{1,1},
undefined,
[<<"nathon">>,<<"org">>],
undefined,<<"nathon.org">>,9999,
[<<"websocket">>],
undefined,<<"/websocket">>,undefined,<<>>,[],
[{'Accept-Charset',
<<"ISO-8859-1,utf-8;q=0.7,;q=0.3">>},
{'Accept-Language',<<"en-US,en;q=0.8">>},
{'Accept-Encoding',<<"gzip,deflate,sdch">>},
{'Accept',
<<"text/html,application/xhtml+xml,application/xml;q=0.9,/*;q=0.8">>},
{'User-Agent',
<<"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.220 Safari/535.1">>},
{'Cache-Control',<<"max-age=0">>},
{'Connection',<<"keep-alive">>},
{'Host',<<"nathon.org">>}],
undefined,waiting,<<>>,waiting}
Opening file: "../etg/priv/docroot/websocket.html"
Protocol=tcp Host=<<"nathon.org">> Port=9999 Path=<<"/websocket">> QS=undefined
=ERROR REPORT==== 5-Oct-2011::17:35:37 ===
Error in process <0.91.0> on node 'etg@icicle' with exit value: {badarg,[{erlang,bit_size,[undefined]},{cowboy_http_websocket,hixie76_location,5},{cowboy_http_websocket,websocket_handshake,3}]}
=SUPERVISOR REPORT==== 5-Oct-2011::17:35:37 ===
Supervisor: {<0.76.0>,cowboy_requests_sup}
Context: child_terminated
Reason: {badarg,[{erlang,bit_size,[undefined]},
{cowboy_http_websocket,hixie76_location,5},
{cowboy_http_websocket,websocket_handshake,3}]}
Offender: [{pid,<0.91.0>},
{name,cowboy_requests_sup},
{mfargs,{cowboy_requests_sup,start_request,undefined}},
{restart_type,temporary},
{shutdown,brutal_kill},
{child_type,worker}]
I know it used to work in d0f711a.
When a keep-alive connection timeout occurs, cowboy sends an 408 with "connection: close". Erlang's httpc ignores it in case it is not part of the first response, I suspect other clients may ignore it as well. For such clients, I think that Cowboy should also close the connection on its side (otherwise the buggy client will keep sending requests after it got 'connection: close' that cowboy will either ignore or response to, but never close the socket).
In cowboy_http_websocket:websocket_send/2
:
https://github.com/extend/cowboy/blob/master/src/cowboy_http_websocket.erl#L359
It would be fantastic to have a RESTful callback interface like webmachine but much much faster, and possibly easier to debug with erlang error reports. Specifically one that is easier to read and understand than the webmachine decision core and does not produce enormous stack traces.
A sweet addon would be a built in web interface for live metrics, debugging, and stats.
Ideas (based on the idea gen_event logging)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.