erlang webmachine not reading dispatch.conf - erlang

I'm working through an online tutorial on webmachine http://en.wikiversity.org/wiki/Web_Development_with_Webmachine_for_Erlang. I've downloaded the source from github, created a new application using
/webmachine/scripts/new_webmachine.sh prp
then used make to build it and started it with the standard start script. The skeleton app runs fine and you can see the home page but there is no dispatch.conf file present in the /priv directory and even if I add one it doesn't seem to pick it up - amongst the startup log I can see there is a (default?) dispatch setup but adding and altering dispatch.conf doesn't change it.
=PROGRESS REPORT==== 23-Jul-2014::20:03:32 ===
supervisor: {local,prp_sup}
started: [{pid,<0.81.0>},
{name,webmachine_mochiweb},
{mfargs,
{webmachine_mochiweb,start,
[[{ip,"0.0.0.0"},
{port,8080},
{log_dir,"priv/log"},
{dispatch,[{[],prp_resource,[]}]}]]}},
{restart_type,permanent},
{shutdown,5000},
{child_type,worker}]
I've looked around to see if the configuration has moved somehow but the documentation that comes with the source seems to suggest /priv/dispatch.conf is correct. I'm stumped - any help would be gratefully accepted.
Thanks,
Joe

The example that you are following is not correct. When using new_webmachine.sh to create you webmachine app, the configuration of the routes will not be stored in priv/dispatch.conf but created in src/prp_config.erl.
In order to get it to use dispatch.conf you need to change prp_config:dispatch/0 to:
-spec dispatch() -> [webmachine_dispatcher:route()].
dispatch() ->
{ok, Routes} = file:consult("priv/dispatch.conf"),
Routes.
and then add priv/dispatch.conf as:
{[], prp_resource, []}.

Related

How to start deps application automatcially in Chicago Boss?

I can't figure out how to automatically start an "deps" applciation in Chicago Boss.
Use applcation:which_applications() I can see a bunch started like "lager, ranch, cowboy ..etc etc". How do I start another one I added?
If I go to console and run application:start(oauth2) and it's ok. I can start it.
But I tried to change src/xxx.app.src and add it to {applications,[]}, but no go. Isn't this the place to load/start any application that mine depends on?
But I can't find how boss loads and start all the other applications either.
By the way, this oauth2 appliation doesn't contain an application-behavior file (oauth2_app.erl) so I don't know if this is related. Since I can manually start it ok.
So, confused. Any help would be appreciated.
Plus: I remember that I did start application by adding the application:start(xxx) into the /priv/init/xxx_01_news.erl init function but that's very hackish I think.
You can use rebar.config to add your dependency applications then edit boss.config file this way:
First: Add the dependency applications name in applications.
Second: Add their specific configurations as follows.
boss.config file:
[
{boss, [
{path, "./deps/boss"},
{applications, [your_app_name, your_app_dep_1, your_app_dep_2]},
{assume_locale, "en"},
%% ... other configuration
%% APPLICATION CONFIGURATIONS
{your_app_name, []},
{your_app_dep_1, []},
{your_app_dep_2, []}
].
Edit: This way CB expects another boss application so looks for the router file and warns if cannot find it. However starting the dependencies inside its init function is not a dirty way and I suggest to consider it.

Erlang Tracing: Failed to open trace

I am currently observing traces of Erlang programs (using the Erlang:trace function), specifically the YAWS web server, although my problem may not be limited to this particular program.
Basically, when I attempt to trace some processes and output these traces, the following errors are displayed:
=ERROR REPORT==== 30-Mar-2014::15:48:25 ===
Failed to open trace "trace.<0.4084.0>.traffic": "I/O error"
=ERROR REPORT==== 30-Mar-2014::15:48:25 ===
Failed to open trace "trace.<0.4085.0>.traffic": "I/O error"
=ERROR REPORT==== 30-Mar-2014::15:48:26 ===
Failed to open trace "trace.<0.4086.0>.traffic": "I/O error"
I would appreciate any insight into why this error is occurring and how it can be solved.
Thanks!
EDIT:
This is the code I am using:
looper()->
receive
P-> io:format(" trace msg: ~p ~n", [P])
end,
looper().
tracer2(Pid)->
erlang:trace(Pid,true,[set_on_spawn, send, 'receive']),
looper().
In the cmd, I first enter: ybed_sup:start_link() , then enter tracer2(PID) passing the PID of the process executing the function yaws_server:acceptor as a parameter.
At first, traces are printed correctly, but then this process dies and new processes with the functon yaws_server:acceptor are spawned, after which only the error messages show.
I think you might be confusing Erlang tracing and the tracing capabilities Yaws provides for HTTP requests. They are very different things.
The error you're seeing is caused by Yaws being unable to open the files mentioned in your error messages (for example, trace.<0.4084.0>.traffic), which by default are opened in the logdir specified in the yaws.conf file. You can read more about this near the top of the yaws.conf documentation or in the yaws.conf.5 man page that's part of your Yaws installation.
After your EDIT:
I fully agree with Steve Vinoski answer.
Few notes:
with current logic you "freeze" you shell (cmd), you might want spawn a new process for loop/0 function
if you just would like to simply debug your system try using dbg module
if trace/2 function would fail you would get little different error message; something similar to
** exception error: bad argument
in function erlang:trace/3
called as erlang:trace(a,b,c)
so you can assume code you wrote works just fine
(as far as I understand you) you're tracing process that is spawning yaws acceptor; make sure that you turn on tracing before acceptor is spawned, or pass to your trace2/1 function pid returned from yaws_server:acceptor
And finally make sure that you configuration is ok. From what you are describing your log_dir might not exist (or you could forget to add flag allowing to create folder), or you might not have permission to write in this directory.

Yaws process died

I do performance testing of our Erlang application with OpenSTA. The test runs with 100 virtual users. At some point the following errors start popping up:
Yaws process died: {{badmatch,{error,eacces}},
[{yaws_server,ut_read,1},
{yaws_server,deliver_dyn_file,5},
{yaws_server,aloop,3},
{yaws_server,acceptor0,2},
{proc_lib,init_p_do_apply,3}]}
The test continues to run. I cannot find info about this error. Does eacces mean Error accessing a resource?
EDIT: As pointed out by #Muzaaya Joshua the call file:read_file(UT#urltype.fullpath) crashes in function ut_read(UT). I recompiled the module and printed the context. The error is eacces and UT holds:
{urltype,yaws,
{file_info,14088,regular,read_write,
{{2011,9,13},{11,51,42}},
{{2011,10,17},{17,59,44}},
{{2011,3,16},{13,18,58}},
33206,1,3,0,0,0,0},
"/handler.yaws",
"c:/Temp/harmony/script/../www/handler.yaws",
"/",undefined,undefined,"text/html",
"/handler.yaws",undefined}
This file handler.yaws is the entry point of our app and is called on every request. When I run the test with 100 or less virtual users I don't see these errors. So how can it be Missing permission for reading the file, or for searching one of the parent directories. as the error is described in the read_file documentation?
Thanks in advance.
Martin
eacces means access denied, the error codes are described at the end of the file documenation: http://www.erlang.org/doc/man/file.html#write_file_info-2
Yaws has failed to open a file. This is a file read permission denied to the user running yaws application. If you add permissions to the user running yaws to own all folders concerning yaws, this may be fixed. to check it out, try running yaws as root , if at all these paths are owned by root. The yaws_server.erl source file at the point is as follows:
ut_read(UT) ->
?Debug("ut_read() UT.fullpath = ~p~n", [UT#urltype.fullpath]),
case yaws:outh_get_content_encoding() of
identity ->
case UT#urltype.data of
undefined ->
?Debug("ut_read reading\n",[]),
{ok, Bin} = file:read_file(UT#urltype.fullpath),
?Debug("ut_read read ~p\n",[size(Bin)]),
Bin;
B when is_binary(B) ->
B
end;
deflate ->
case UT#urltype.deflate of
B when is_binary(B) ->
?Debug("ut_read using deflated binary of size ~p~n",
[size(B)]),
B
end
end.
The line in bold in the above source is where the bad match occurs.
Check wether yaws is running as a user with permissions to access its folders such as the doc root, ssl folders and other paths that yaws may access files. Does the user running yaws have access to all required files ?
In windows, this makes it easy. Now go to your Local disk C, Program Files (In windows 7, could be Program Files (x86)), lastly to where yaws is installed. This will be a folder: Yaws-VERSION e.g. Yaws-1.89. Now, when you right click this, you select Properties, then in the pop-up window you select Security. Under Security, you click edit. Now under Group or usernames, you select each user (and each type of account) and give it all permissions i.e. read, write, full control e.t.c. click Apply, wait for windows to perform the changes, then click Ok and close. Your users must now have all required permissions.
I managed to fix this errors by increasing the file size of the allowed in cache files in the YAWS configuration max_size_cached_file. This made our .yaws file to be loaded in memory and not accessess with file:read_file all the time. Hopefully this will save someone else couple of hours (or days :))

Erlang: Problem with crypo:sha()

This works in my erlang shell:
1> U = default_user_name().
2> crypto:start().
3> crypto:sha(U).
4> crypto:stop().
But when I compile this:
default_pw() ->
U = default_user_name(),
crypto:start(),
crypto:sha(U),
crypto:stop().
And execute it in the erlang shell, I get this:
1> person:default_pw().
** exception error: bad argument
in function port_control/3
called as port_control(crypto_drv04,5,<<"jDoe">>)
in call from crypto:control/2
Two questions:
1) What am I doing wrong?
2) It seems that I need to start and stop the crypto server. But is there a better place to start and stop it in my application?
Many thanks,
LRP
The error you are getting indicates that the crypto application was not started. An easy way to start it is just to add it as a parameter to erl like so:
$ erl -s crypto
I had a look at the current implementation of crypto and the past release notes for erlang and I came to the following conclusions (someone please correct me if I'm wrong):
Erlang releases <14A require crypto to be started prior to calling any functions because the library used a port driver. This makes sense because I got the error you described with 13B04 after not starting crypto.
Erlang releases >=14A don't require crypto to be started as the implementation now uses NIFs. This makes sense because the current implementation of crypto_server.erl is just a gen_server template, and on 14B03 I don't need to start the application in order to make crypto:sha/1 work.

Working example for Erlang Server Interface

I am trying to make Erlang's Inets mode_esi work and run some function. So, far, I did not succeed. Can someone post a minimal example of how to run Inets so that a url like http:localhost:8099/esi/my_mod:foo will invoke the method my_mod:foo/3?
Addition: I have started inets with these commands:
inets:start(),
inets:start(httpd, [{port, 8099}, {server_name, "localhost"}, {document_root, "."},
{server_root, "."}, {erl_script_alias, {"/esi", [my_esi, io]}}]).
The module is:
-module(my_esi).
-export([foo/3]).
foo(Sid, Env, In) -> mod_esi:deliver(Sid, ["bla"]).
But browsing to http://localhost:8099/esi/my_esi:foo result in an error message.
To clarify what has already been said, I'll give a working example (from the ground up). This is to help those who came here from google, mostly because it's how I found it ;)
First, create the module:
# filename: my_esi.erl
-module(my_esi).
-export([foo/3,bar/3]).
foo(Sid, Env, In) -> mod_esi:deliver(Sid, ["foo"]).
bar(Sid, Env, In) -> mod_esi:deliver(Sid, ["bar"]).
Save it, then compile it:
erlc my_esi.erl
You'll now have my_esi.beam
Then run the shell from bash
erl
Within the shell type the following:
inets:start().
{Httpd_State,Httpd_Pid} = inets:start(httpd, [{port, 8099}, {server_name, "localhost"}, {document_root, "."}, {modules,[mod_esi]},{server_root, "."}, {erl_script_alias, {"/esi", [my_esi, io]}}]).
The important part here is:
{modules,[mod_esi]}
If you need other modules, load them by appending them to the list.
To clarify how/why:
I will first admit that it does seems a bit strange at first, and that the documentation was less helpful than I had hoped. However, I realised that:
modules() -> [atom()]
becomes:
{modules, [mod_access, mod_esi, ..., etc.]}
Hope it helps someone :)
I've solved it myself. For some reason, beyond my understanding, the exact same code worked when I invoked Inets with a configuration file (a modified version of inets/examples/server_root/conf/8080.conf). I suppose that the example file includes a more complete list of properties that Inets required than what I listed in inets:start(httpd, [...]). If anyone encounters Inets problem in the future, my advice is to start with the example configuration.
Ok, here goes:
set {erl_script_alias, {"/esi", [my_mod]}} for the inets web server, so the module is accepted.
Write my_mod. Something like:
-module(my_mod).
-export([foo/3]).
foo(SessID, _Env, _Input) ->
mod_esi:deliver(SessID, ["Data ", <<"as">>, " an iolist"]).
Make sure mod_esi is part of inets section called module: {modules, [.., mod_esi, ..}}
This step is very important: Breathe 3 times, recite the holy words "I pray to thee, inets, that you will work this time". Cross your fingers.
Drink a cup of coffee. Tea will not do. It has to be coffee.
Enjoy your web server.

Resources