nitrogen / simple_bridge

A simple, standardized interface library to Erlang HTTP Servers.
MIT License
112 stars 76 forks source link

dynamic routing yaws 404 (using default yaws_outmod) #55

Closed stuart-thackray closed 8 years ago

stuart-thackray commented 8 years ago

Hi Jesse,

I am not sure if this is still a supported feature or if I am am supposed to write a custom (routing) handler to achieve it (haven't figured out yet what to do here). Happy to write a PR if this is a genuine issue; if you can suggest a way.

According to Nitrogen Tutorial under dynamic routing explained there point 4 states "Modules that aren't found go to web_404.erl if it exists."

https://github.com/nitrogen/simple_bridge/blob/master/src/yaws_bridge_modules/yaws_simple_bridge.erl#L186 is always called. I am not sure if this is with the introduction of websockets (done after the tutorial I believe).

Running dynamic and embedded yaws; specify the 404 module in the yaws.conf works fine for static paths; other default as shown the yaws default 404 module.

choptastic commented 8 years ago

Hi Stuart,

The key to web_404 is that it's only for modules that aren't found, which means that if a URL contains an extension (like .html), then Nitrogen recognizes this and just says (this is a static file, let the webserver handle it) - at which point it is handed back to yaws, calling the outmod.

Nitrogen's handling of URLs is that if it sees an extension on the request (and it's not one of the named smart extensions), then it treats it as a static file. Since the webservers are better optimized at dealing with static files than Nitrogen (and each does it a little differently), Nitrogen explicitly lets the webservers handle static files.

But it should work just fine with a non-extension path like http://whatever.com/the/module/that/wasnt/there

The big exception to that would be if the module itself had the path that was prefixed by one of the static paths in your simple_bridge.config. For example:

http://whatever.com/js/some/file would automatically be handed to yaws for handling (by default, at least).

choptastic commented 8 years ago

THis is the relevant part of the dynamic route handler (the default route handler):

https://github.com/nitrogen/nitrogen_core/blob/master/src/handlers/route/dynamic_route_handler.erl#L78-L94

Particularly this line will only happen if the request does not have an extension, or an extension is not found in the list of smart extensions.

Make sense?

stuart-thackray commented 8 years ago

Thank you very much Jesse.

Yes it makes sense now thanks.

choptastic commented 8 years ago

Great. If you wanted Nitrogen to use the web_404 handler for all 404s, you'd have to use a variant of the dynamic_route_handler which checked for the existence of a file before passing it to yaws. It would add a slight amount of overhead, but not too much.

It would look something like this:

determine_initial_entry_point(Filename) ->
    SmartExtensions = wf:config_default(smart_extensions, []),
    Ext = string:strip(filename:extension(Filename), left, $.),
    case lists:keyfind(Ext, 1, SmartExtensions) of
        {Ext, EntryFun, ProcessingFun={_,_}} ->
            {module, EntryFun, ProcessingFun};
        {Ext, EntryFun, undefined} ->
            {module, EntryFun, undefined};
        {Ext, EntryFun} ->
            {module, EntryFun, undefined};
        false when Ext==[] ->
            {module, main, undefined};
        false ->
            %% NEW BIT
            case filelib:is_regular(Filename) of
                 true -> static;
                 false -> undefined
            end;
            %% END NEW BIT
        Other ->
            throw({invalid_smart_extension_definition, Other})
    end.