Closed 7stud closed 5 years ago
The stacktrace doesn't make sense, it seems like you could have a different cowboy_constraints
module version than the one in 2.6.1
interfering. Perhaps you have something in ERL_LIBS
that use Cowboy and it picks up the module from there?
The stacktrace doesn't make sense, it seems like you could have a different
cowboy_constraints
module version than the one in2.6.1
interfering. Perhaps you have something inERL_LIBS
that use Cowboy and it picks up the module from there?
Thanks for taking a look.
All my environment variables are shown below. Here is what I have for ERL_LIBS:
"ERL_LIBS=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps:/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps"
The first directory doesn't exist:
~/erlang_programs/cowboy_apps/hello_erlang$ cd /Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps
-bash: cd: /Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps: No such file or directory
~/erlang_programs/cowboy_apps/hello_erlang$
Edit: Well, if I do the same thing in the cowboy shell, this is what I get:
(hello_erlang@127.0.0.1)1> cd("/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps").
/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release
ok
(hello_erlang@127.0.0.1)2> ls().
bin erl_crash.dump
erts-8.2 erts-9.3
hello_erlang_release-1.tar.gz lib
log releases
ok
And, then:
(hello_erlang@127.0.0.1)3> cd("lib").
/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release/lib
ok
(hello_erlang@127.0.0.1)4> ls().
asn1-4.0.4 asn1-5.0.5 cowboy-2.0.0-pre.9
cowlib-2.0.0-pre.1 crypto-3.7.2 crypto-4.2.1
hello_erlang-0.1.0 kernel-5.1.1 kernel-5.4.3
public_key-1.3 public_key-1.5.2 ranch-1.4.0
runtime_tools-1.11 runtime_tools-1.12.5 sasl-3.0.2
sasl-3.1.1 ssl-8.1 ssl-8.2.4
stdlib-3.2 stdlib-3.4.4
ok
The cowboy version listed there is: cowboy-2.0.0-pre.9
. But, there is also a cowboy directory (without a version) in the other directory shown in ERL_LIBS:
(hello_erlang@127.0.0.1)10> cd("/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps"). /Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps
ok
(hello_erlang@127.0.0.1)11> ls().
cowboy cowlib gun ranch
ok
(hello_erlang@127.0.0.1)12> cd(cowboy).
/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps/cowboy
ok
(hello_erlang@127.0.0.1)13> ls().
.git .gitattributes .gitignore
CHANGELOG.md CONTRIBUTING.asciidoc LICENSE
README.asciidoc cowboy.d doc
ebin erlang.mk examples
makefile makefile.bak plugins.mk
rebar.config src test
ok
(hello_erlang@127.0.0.1)14> cd(src).
/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps/cowboy/src
ok
(hello_erlang@127.0.0.1)15> ls().
cowboy.erl cowboy_app.erl
cowboy_bstr.erl cowboy_clear.erl
cowboy_clock.erl cowboy_compress_h.erl
cowboy_constraints.erl cowboy_handler.erl
cowboy_http.erl cowboy_http2.erl
cowboy_iolists.erl cowboy_loop.erl
cowboy_middleware.erl cowboy_req.erl
cowboy_rest.erl cowboy_router.erl
cowboy_static.erl cowboy_stream.erl
cowboy_stream_h.erl cowboy_sub_protocol.erl
cowboy_sup.erl cowboy_tls.erl
cowboy_websocket.erl
ok
(hello_erlang@127.0.0.1)17> os:cmd("cat cowboy.erl").
"%% Copyright (c) 2011-2017, Loïc Hoguin <essen@ninenines.eu>\n%%\n%% Permission to use, copy, modify, and/or distribute this software for any\n%% purpose with or without fee is hereby granted, provided that the above\n%% copyright notice and this permission notice appear in all copies.\n%%\n%% THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-module(cowboy).\n\n-export([start_clear/3]).\n-export([start_tls/3]).\n-export([stop_listener/1]).\n-export([set_env/3]).\n\n%% @todo Detailed opts.\n-type opts() :: map().\n-export_type([opts/0]).\n\n-type fields() :: [atom()\n\t| {atom(), cowboy_constraints:constraint() | [cowboy_constraints:constraint()]}\n\t| {atom(), cowboy_constraints:constraint() | [cowboy_constraints:constraint()], any()}].\n-export_type([fields/0]).\n\n-type http_headers() :: #{binary() => iodata()}.\n-export_type([http_headers/0]).\n\n-type http_status() :: non_neg_integer() | binary().\n-export_type([http_status/0]).\n\n-type http_version() :: 'HTTP/2' | 'HTTP/1.1' | 'HTTP/1.0'.\n-export_type([http_version/0]).\n\n-spec start_clear(ranch:ref(), ranch_tcp:opts(), opts())\n\t-> {ok, pid()} | {error, any()}.\nstart_clear(Ref, TransOpts0, ProtoOpts0) ->\n\t{TransOpts, ConnectionType} = ensure_connection_type(TransOpts0),\n\tProtoOpts = ProtoOpts0#{connection_type => ConnectionType},\n\tranch:start_listener(Ref, ranch_tcp, TransOpts, cowboy_clear, ProtoOpts).\n\n-spec start_tls(ranch:ref(), ranch_ssl:opts(), opts())\n\t-> {ok, pid()} | {error, any()}.\nstart_tls(Ref, TransOpts0, ProtoOpts0) ->\n\t{TransOpts1, ConnectionType} = ensure_connection_type(TransOpts0),\n\tTransOpts = [\n\t\t{next_protocols_advertised, [<<\"h2\">>, <<\"http/1.1\">>]},\n\t\t{alpn_preferred_protocols, [<<\"h2\">>, <<\"http/1.1\">>]}\n\t|TransOpts1],\n\tProtoOpts = ProtoOpts0#{connection_type => ConnectionType},\n\tranch:start_listener(Ref, ranch_ssl, TransOpts, cowboy_tls, ProtoOpts).\n\nensure_connection_type(TransOpts) ->\n\tcase proplists:get_value(connection_type, TransOpts) of\n\t\tundefined -> {[{connection_type, supervisor}|TransOpts], supervisor};\n\t\tConnectionType -> {TransOpts, ConnectionType}\n\tend.\n\n-spec stop_listener(ranch:ref()) -> ok | {error, not_found}.\nstop_listener(Ref) ->\n\tranch:stop_listener(Ref).\n\n-spec set_env(ranch:ref(), atom(), any()) -> ok.\nset_env(Ref, Name, Value) ->\n\tOpts = ranch:get_protocol_options(Ref),\n\t{_, Env} = maps:find(env, Opts),\n\tOpts2 = maps:put(env, maps:put(Name, Value, Env), Opts),\n\tok = ranch:set_protocol_options(Ref, Opts2).\n"
(hello_erlang@127.0.0.1)18>
What do I do to make my app use the correct cowboy version?? I though that is what the Makefile was for.
All environment variables:
(hello_erlang@127.0.0.1)1> SeparateLines = fun F([]) -> ok;
(hello_erlang@127.0.0.1)1> F([H|T]) -> io:format("~p~n", [H]), F(T) end.
#Fun<erl_eval.30.99386804>
(hello_erlang@127.0.0.1)2> SeparateLines(lists:sort(os:getenv())).
"ANDROID_SDK=/Users/7stud/Library/Android/sdk"
"APPS_DIR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps"
"ASDF_DIR=/Users/7stud/.asdf"
"Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.A8dplSuI7k/Render"
"BINDIR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release/erts-9.3/bin"
"DEPS_DIR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps"
"DIALYZER_PLT=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/.hello_erlang.plt"
"EMU=beam"
"ERLANG_MK_FILENAME=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/erlang.mk"
"ERLANG_MK_TMP=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/.erlang.mk"
"ERL_AFLAGS=-kernel shell_history enabled"
"ERL_LIBS=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/apps:/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps"
"GEM_HOME=/Users/7stud/.rvm/gems/ruby-2.4.0"
"GEM_PATH=/Users/7stud/.rvm/gems/ruby-2.4.0:/Users/7stud/.rvm/gems/ruby-2.4.0@global"
"GOPATH=/Users/7stud/go_programs"
"HOME=/Users/7stud"
"IGNORE_DEPS="
"IRBRC=/Users/7stud/.rvm/rubies/ruby-2.4.0/.irbrc"
"JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home"
"LANG=en_US.UTF-8"
"LD_LIBRARY_PATH=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release/erts-9.3/lib:"
"LOGNAME=7stud"
"MAKEFLAGS="
"MAKELEVEL=1"
"MANPATH=/opt/local/share/man:/Users/7stud/perl5/perlbrew/perls/perl-5.20.2/man:/Users/7stud/.nvm/versions/node/v11.2.0/share/man:/usr/local/share/man:/Library/Frameworks/Python.framework/Versions/2.7/share/man:/Library/Frameworks/Python.framework/Versions/3.4/share/man:/usr/share/man:/usr/local/MacGPG2/share/man:/usr/local/git/share/man:/Applications/Xcode.app/Contents/Developer/usr/share/man:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/share/man"
"MFLAGS="
"MY_RUBY_HOME=/Users/7stud/.rvm/rubies/ruby-2.4.0"
"NAME=hello_erlang@127.0.0.1"
"NO_AUTOPATCH="
"NVM_BIN=/Users/7stud/.nvm/versions/node/v11.2.0/bin"
"NVM_CD_FLAGS="
"NVM_DIR=/Users/7stud/.nvm"
"NVM_IOJS_ORG_MIRROR=https://iojs.org/dist"
"NVM_NODEJS_ORG_MIRROR=https://nodejs.org/dist"
"NVM_PATH=/Users/7stud/.nvm/versions/node/v11.2.0/lib/node"
"OLDPWD=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang"
"PATH=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release/erts-9.3/bin:/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release/bin:/Users/7stud/.rvm/gems/ruby-2.4.0/bin:/Users/7stud/.rvm/gems/ruby-2.4.0@global/bin:/Users/7stud/.rvm/rubies/ruby-2.4.0/bin:/Users/7stud/Library/Android/sdk/platform-tools:/Users/7stud/.asdf/shims:/Users/7stud/.asdf/bin:/Applications/Postgres.app/Contents/Versions/10/bin:/opt/local/bin:/opt/local/sbin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Users/7stud/.evm/erlang_versions/otp_src_20.2/bin:/usr/local/mysql/bin:/usr/local/bin/mongodb-osx-x86_64-3.0.7/bin:/Users/7stud/.local/bin:/Users/7stud/perl5/perlbrew/bin:/Users/7stud/perl5/perlbrew/perls/perl-5.20.2/bin:/Users/7stud/.nvm/versions/node/v11.2.0/bin:/usr/local/bin:/Library/Frameworks/Python.framework/Versions/2.7/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/go/bin:/usr/local/MacGPG2/bin:/Applications/Wireshark.app/Contents/MacOS:/usr/local/git/bin:/usr/local/go/bin://Users/7stud/go_programs/bin:/Applications/Rakudo/bin:/Applications/Rakudo/share/perl6/site/bin:/Users/7stud/flutter_apps/flutter/bin:/Users/7stud/.rvm/bin"
"PERLBREW_BASHRC_VERSION=0.73"
"PERLBREW_HOME=/Users/7stud/.perlbrew"
"PERLBREW_MANPATH=/Users/7stud/perl5/perlbrew/perls/perl-5.20.2/man"
"PERLBREW_PATH=/Users/7stud/perl5/perlbrew/bin:/Users/7stud/perl5/perlbrew/perls/perl-5.20.2/bin"
"PERLBREW_PERL=perl-5.20.2"
"PERLBREW_ROOT=/Users/7stud/perl5/perlbrew"
"PERLBREW_VERSION=0.73"
"PLATFORM=darwin"
"PROGNAME=hello_erlang_release/bin/hello_erlang_release"
"PROJECT_HOME=/Users/7stud/django_projects"
"PWD=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release"
"REBAR_DEPS_DIR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps"
"REL_NAME=hello_erlang_release"
"ROOTDIR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/_rel/hello_erlang_release"
"RUBY_VERSION=ruby-2.4.0"
"SECURITYSESSIONID=186a7"
"SHELL=/bin/bash"
"SHLVL=1"
"SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.j3fk5KvbKB/Listeners"
"TERM=xterm-256color"
"TERM_PROGRAM=Apple_Terminal"
"TERM_PROGRAM_VERSION=404"
"TERM_SESSION_ID=BBE0A4AF-DBCE-44CE-A52B-7133971D3D6E"
"TMPDIR=/var/folders/th/8j21gcbs5757m9q728jrlvxw0000gn/T/"
"USER=7stud"
"VIRTUALENVWRAPPER_HOOK_DIR=/Users/7stud/.virtualenvs"
"VIRTUALENVWRAPPER_PROJECT_FILENAME=.project"
"VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3.4"
"VIRTUALENVWRAPPER_SCRIPT=/Library/Frameworks/Python.framework/Versions/3.4/bin/virtualenvwrapper.sh"
"WORKON_HOME=/Users/7stud/.virtualenvs"
"XPC_FLAGS=0x0"
"XPC_SERVICE_NAME=0"
"XREFR=/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/xrefr"
"__CF_USER_TEXT_ENCODING=0x1F5:0x0:0x0"
"_compat_rebar_config={deps, [\n{cowboy,\".*\",{git,\"https://github.com/ninenines/cowboy\",\"2.6.1\"}}\n]}.\n{erl_opts, [debug_info,warn_export_vars,warn_shadow_vars,warn_obsolete_guard]}."
"_system_arch=x86_64"
"_system_name=OSX"
"_system_type=Darwin"
"_system_version=10.13"
"rvm_bin_path=/Users/7stud/.rvm/bin"
"rvm_path=/Users/7stud/.rvm"
"rvm_prefix=/Users/7stud"
"rvm_version=1.27.0 (latest)"
ok
(hello_erlang@127.0.0.1)3>
(hello_erlang@127.0.0.1)4> ls().
asn1-4.0.4 asn1-5.0.5 cowboy-2.0.0-pre.9
This says that your release has Cowboy 2.0.0-pre.9.
(hello_erlang@127.0.0.1)14> cd(src).
/Users/7stud/erlang_programs/cowboy_apps/hello_erlang/deps/cowboy/src
ok
(hello_erlang@127.0.0.1)15> ls().
And this confirms it as well.
I do not know what is happening but it's not the right Cowboy version being picked up.
Try this and see if that fixes it, and if not please paste the complete output:
make erlang-mk
make distclean
make
Thanks again!
Try this and see if that fixes it, and if not please paste the complete output:
make erlang-mk make distclean make
Yep, that worked, i.e. the arity 2 constraint function gives me the expected output. While I was waiting for a response from you, I started a new project, and the arity 2 constraint function worked in the new project. I think my problem was that I originally created the hello_erlang cowboy app a year ago(?), and this week I changed the Makefile to use cowboy 2.6.1, and then I was running $ make run
, which doesn't do the make
step ??
I searched around, and I don't understand how $make erlang-mk
works. It appears to have downloaded something from github and then created the file erlang.mk:
/erlang_programs/cowboy_apps/hello_erlang$ make erlang-mk
erlang.mk:26: Please upgrade to GNU Make 4 or later: https://erlang.mk/guide/installation.html
git clone https://github.com/ninenines/erlang.mk .erlang.mk.build
Cloning into '.erlang.mk.build'...
but I can ask on stackoverflow about that.
One last question, if I may, the cowboy constraint docs give this example for the built in int
constraint function:
Finally, the
format_error
operation takes an error returned by any other operation and returns a formatted human-readable error message.int(format_error, {not_an_integer, Value}) -> io_lib:format("The value ~p is not an integer.", [Value]).
When I add a format_error
clause to my positive_fun():
positive_fun(forward, Value) when Value > 0->
{ok, Value};
positive_fun(forward, _) ->
{error, not_positive};
positive_fun(format_error, {not_positive, Value}) ->
io_lib:format("The value ~p is not an integer.", [Value]).
I see no difference in the response in my browser:
1) For the url http://localhost:8080/get/2
, I see:
Hello Erlang
Id=2
2) For the url http://localhost:8080/get/-10
, I see:
[ME] 404. Whoops! (No matching route!)
The docs say:
Finally, the
format_error
operation takes an error returned by any other operation and returns a formatted human-readable error message.
Where does that string get returned to?
Thanks.
First, when you change a dependency's version, Erlang.mk will not automatically update to that version. Updating automatically is not always what one wants so the solution might be to have a separate command for updating deps.
The format_error is not used during routing, it's used when matching query string or cookies. Constraints are for more than routing! :-)
First, when you change a dependency's version, Erlang.mk will not automatically update to that version. Updating automatically is not always what one wants so the solution might be to have a separate command for updating deps.
The format_error is not used during routing, it's used when matching query string or cookies. Constraints are for more than routing! :-)
Thanks essen! I really appreciate the help!
Think we're done here, closing, thanks!
I'm using cowboy 2.6.1:
Makefile:
Here's the error:
Here's my route:
hello_erlang_app.erl:
The url I entered in my browser:
http://localhost:8080/get/2
id_handler.erl:
no_matching_router_handler.erl:
If I change the arity of the constraint function to 1:
....then everything works as expected:
1) When I enter the url
http://localhost:8080/get/4
in my browser, I see the response:2) When I enter the url
http://localhost:8080/get/-10
in my browser, I see the response:[ME] 404. Whoops! (No matching route!)
I don't get it??! The Constraint docs only show constraint functions with arity 2, for example:
And the Constraint docs say:
Also, how do you modify the value, e.g. by adding 1 to it, rather than matching or not matching the route like my
postive_fun/1
does? I searched through the source code for the built inint
constraint function to see how it was implemented, but I was unable to find it.Startup info: