@ -83,7 +83,7 @@ defmodule GcIndexRelayWeb.FilterController do
@@ -83,7 +83,7 @@ defmodule GcIndexRelayWeb.FilterController do
@spec validate_param_values ( map ( ) ) :: { :ok , map ( ) } | { :error , String . t ( ) }
def validate_param_values ( params ) do
%{ : limit = > limit } = params
%{ " limit" = > limit } = params
if limit < 1 or limit > 100 do
{ :error , " The filter limit must be between 1 and 100. " }
@ -123,7 +123,9 @@ defmodule GcIndexRelayWeb.FilterController do
@@ -123,7 +123,9 @@ defmodule GcIndexRelayWeb.FilterController do
params
|> Map . keys ( )
|> Enum . reject ( fn key ->
key in known_keys or String . starts_with? ( key , " # " )
key in known_keys or String . starts_with? ( key , " # " ) or
( byte_size ( key ) == 1 and
( ( key >= " a " and key <= " z " ) or ( key >= " A " and key <= " Z " ) ) )
end )
case unknown_keys do
@ -135,16 +137,22 @@ defmodule GcIndexRelayWeb.FilterController do
@@ -135,16 +137,22 @@ defmodule GcIndexRelayWeb.FilterController do
# Parse individual parameters from strings to proper types
@spec parse_params ( map ( ) ) :: { :ok , map ( ) } | { :error , String . t ( ) }
defp parse_params ( params ) do
result =
params
|> Enum . reduce_while ( { :ok , %{ } } , fn { key , value } , { :ok , acc } ->
case parse_param ( key , value ) do
{ :ok , parsed_value } -> { :cont , { :ok , Map . put ( acc , key , parsed_value ) } }
{ :error , _ } = error -> { :halt , error }
end
end )
result
params
|> Enum . reduce_while ( { :ok , %{ } } , fn { key , value } , { :ok , acc } ->
case parse_param ( key , value ) do
{ :ok , parsed_value } ->
out_key =
if byte_size ( key ) == 1 and
( ( key >= " a " and key <= " z " ) or ( key >= " A " and key <= " Z " ) ) ,
do : " # " <> key ,
else : key
{ :cont , { :ok , Map . put ( acc , out_key , parsed_value ) } }
{ :error , _ } = error ->
{ :halt , error }
end
end )
end
# Parse individual parameter based on its key
@ -183,7 +191,8 @@ defmodule GcIndexRelayWeb.FilterController do
@@ -183,7 +191,8 @@ defmodule GcIndexRelayWeb.FilterController do
defp parse_param ( " limit " , value ) do
case Integer . parse ( value ) do
{ int , " " } -> { :ok , int }
{ int , " " } when int >= 1 and int <= 100 -> { :ok , int }
{ int , " " } when is_integer ( int ) -> { :error , " The limit must be between 1 and 100. " }
_ -> { :error , " Invalid limit value: ' #{ value } ' must be an integer " }
end
end
@ -192,4 +201,10 @@ defmodule GcIndexRelayWeb.FilterController do
@@ -192,4 +201,10 @@ defmodule GcIndexRelayWeb.FilterController do
defp parse_param ( " # " <> _tag_name , value ) do
{ :ok , String . split ( value , " , " ) }
end
# Handle single-letter tag filters without "#" prefix (e.g., "p" instead of "#p")
# The "#" is trimmed by URL fragment parsing; bare single-letter keys are treated as tag filters
defp parse_param ( << letter >> = _key , value ) when letter in ?a . . ?z do
{ :ok , String . split ( value , " , " ) }
end
end