webmachine / src / webmachine_mochiweb.erl

%% @author Justin Sheehy <justin@basho.com>
%% @author Andy Gross <andy@basho.com>
%% @copyright 2007-2008 Basho Technologies
%%
%%    Licensed under the Apache License, Version 2.0 (the "License");
%%    you may not use this file except in compliance with the License.
%%    You may obtain a copy of the License at
%%
%%        http://www.apache.org/licenses/LICENSE-2.0
%%
%%    Unless required by applicable law or agreed to in writing, software
%%    distributed under the License is distributed on an "AS IS" BASIS,
%%    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%%    See the License for the specific language governing permissions and
%%    limitations under the License.

%% @doc Mochiweb interface for webmachine.
-module(webmachine_mochiweb).
-author('Justin Sheehy <justin@basho.com>').
-author('Andy Gross <andy@basho.com>').
-export([start/1, stop/0, loop/1]).

start(Options) ->
    {DispatchList, Options1} = get_option(dispatch, Options),
    {ErrorHandler0, Options2} = get_option(error_handler, Options1),
    {EnablePerfLog, Options3} = get_option(enable_perf_logger, Options2),
    ErrorHandler = 
	case ErrorHandler0 of 
	    undefined ->
		webmachine_error_handler;
	    EH -> EH
	end,
    {LogDir, Options4} = get_option(log_dir, Options3),
    webmachine_sup:start_logger(LogDir),
    case EnablePerfLog of
	true ->
	    application:set_env(webmachine, enable_perf_logger, true),
	    webmachine_sup:start_perf_logger(LogDir);
	_ ->
	    ignore
    end,
    application:set_env(webmachine, dispatch_list, DispatchList),
    application:set_env(webmachine, error_handler, ErrorHandler),
    mochiweb_http:start([{name, ?MODULE}, {loop, fun loop/1} | Options4]).

stop() ->
    mochiweb_http:stop(?MODULE).

loop(MochiReq) ->
    Req = webmachine:new_request(mochiweb, MochiReq),
    {ok, DispatchList} = application:get_env(webmachine, dispatch_list),
    case webmachine_dispatcher:dispatch(Req:path(), DispatchList) of
        {no_dispatch_match, _UnmatchedPathTokens} ->
            {ok, ErrorHandler} = application:get_env(webmachine, error_handler),
	    ErrorHTML = ErrorHandler:render_error(404, Req, {none, none, []}),
	    Req:append_to_response_body(ErrorHTML),
	    Req:send_response(404),
	    LogData = Req:log_data(),
	    LogModule = 
                case application:get_env(webmachine,webmachine_logger_module) of
		    {ok, Val} -> Val;
		    _ -> webmachine_logger
		end,
	    spawn(LogModule, log_access, [LogData]),
	    Req:stop();
        {Mod, ModOpts, PathTokens, Bindings, AppRoot, StringPath} ->
            {ok, Pid} = webmachine_resource:start_link(Mod, ModOpts),
	    Req:load_dispatch_data(Bindings,PathTokens,AppRoot,StringPath,Req),
	    Req:set_metadata('resource_module', Mod),
            webmachine_decision_core:handle_request(Req, Pid)
    end.

get_option(Option, Options) ->
    {proplists:get_value(Option, Options), proplists:delete(Option, Options)}.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.