Skip to content

Commit

Permalink
mod_base: let controller_id accept an extension on the id for content…
Browse files Browse the repository at this point in the history
… negotation (#3729)

* mod_base: let controller_id accept an extension on the id for content negotation

* Add .jsonld mimetype/extension mappings
  • Loading branch information
mworrell committed Apr 18, 2024
1 parent 2a4ce59 commit 879ac38
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
3 changes: 2 additions & 1 deletion apps/zotonic_core/src/support/z_cowmachine_middleware.erl
Expand Up @@ -25,7 +25,8 @@
-behaviour(cowboy_middleware).

-export([
execute/2
execute/2,
set_accept_context/2
]).

-include_lib("../../include/zotonic.hrl").
Expand Down
2 changes: 2 additions & 0 deletions apps/zotonic_core/src/support/z_media_identify.erl
Expand Up @@ -516,6 +516,7 @@ extension({A, B, _}, PreferExtension) ->
extension(<<A/binary, $/, B/binary>>, PreferExtension);
extension(Mime, PreferExtension) when is_list(Mime) ->
extension(list_to_binary(Mime), PreferExtension);
extension(<<"application/ld+json">>, _PreferExtension) -> <<".jsonld">>;
extension(<<"image/jpeg">>, _PreferExtension) -> <<".jpg">>;
extension(<<"application/vnd.ms-excel">>, _) -> <<".xls">>;
extension(<<"text/plain">>, _PreferExtension) -> <<".txt">>;
Expand Down Expand Up @@ -559,6 +560,7 @@ first_extension([ Ext | _ ]) ->
-spec guess_mime( file:filename_all() ) -> mime_type().
guess_mime(File) ->
case z_string:to_lower( filename:extension( File ) ) of
<<".jsonld">> -> <<"application/ld+json">>;
<<".bert">> -> <<"application/x-bert">>;
% Fonts have since 2017 their own mime types- https://tools.ietf.org/html/rfc8081#section-4.4.5
<<".woff">> -> <<"font/woff">>;
Expand Down
39 changes: 37 additions & 2 deletions apps/zotonic_mod_base/src/controllers/controller_id.erl
Expand Up @@ -100,6 +100,8 @@ find_html([ {{<<"text">>, <<"html">>, _}, _} = Prov | _CTs ]) ->
find_html([ _ | CTs ]) ->
find_html(CTs).

% Fetch id from the request. Check if the id has an extension, if so split it
% and set the accept header.
get_id(Context) ->
case z_context:get(id, Context) of
undefined ->
Expand All @@ -109,9 +111,42 @@ get_id(Context) ->
<<>> ->
{undefined, Context};
Id ->
RscId = m_rsc:rid(Id, Context),
{RscId, z_context:set(id, {ok, RscId}, Context)}
case maybe_split_extension(Id) of
{Root, Ext} ->
RscId = m_rsc:rid(Root, Context),
Context1 = z_cowmachine_middleware:set_accept_context(Ext, Context),
{RscId, z_context:set(id, {ok, RscId}, Context1)};
false ->
RscId = m_rsc:rid(Id, Context),
{RscId, z_context:set(id, {ok, RscId}, Context)}
end
end;
{ok, Id} ->
{Id, Context}
end.

maybe_split_extension(<<"http:", _/binary>>) ->
false;
maybe_split_extension(<<"https:", _/binary>>) ->
false;
maybe_split_extension(Id) ->
case filename:extension(Id) of
<<".", Ext/binary>> when Ext =/= <<>> ->
Root = filename:rootname(Id),
case is_name_like(Root) of
true ->
{Root, Ext};
false ->
false
end;
_ ->
false
end.

is_name_like(<<>>) -> true;
is_name_like(<<$_, R/binary>>) -> is_name_like(R);
is_name_like(<<C, _/binary>>) when C < $0 -> false;
is_name_like(<<C, _/binary>>) when C > $9, C < $A -> false;
is_name_like(<<C, _/binary>>) when C > $Z, C < $a -> false;
is_name_like(<<C, _/binary>>) when C > $z, C < 128 -> false;
is_name_like(<<_, R/binary>>) -> is_name_like(R).

0 comments on commit 879ac38

Please sign in to comment.