@@ -2,6 +2,7 @@ defmodule Bypass.Instance do
22 use GenServer , restart: :transient
33
44 import Bypass.Utils
5+ import Plug.Router.Utils , only: [ build_path_match: 1 ]
56
67 def start_link ( opts \\ [ ] ) do
78 GenServer . start_link ( __MODULE__ , [ opts ] )
@@ -139,6 +140,7 @@ defmodule Bypass.Instance do
139140 route ,
140141 new_route (
141142 fun ,
143+ path ,
142144 case expect do
143145 :expect -> :once_or_more
144146 :expect_once -> :once
@@ -285,18 +287,51 @@ defmodule Bypass.Instance do
285287 end
286288
287289 defp route_info ( method , path , % { expectations: expectations } = _state ) do
288- route =
289- case Map . get ( expectations , { method , path } , :no_expectations ) do
290- :no_expectations ->
291- { :any , :any }
290+ segments = build_path_match ( path ) |> elem ( 1 )
292291
293- _ ->
294- { method , path }
295- end
292+ route =
293+ expectations
294+ |> Enum . reduce_while (
295+ { :any , :any , % { } } ,
296+ fn
297+ { { ^ method , path_pattern } , % { path_parts: path_parts } } , acc ->
298+ case match_route ( segments , path_parts ) do
299+ { true , params } -> { :halt , { method , path_pattern , params } }
300+ { false , _ } -> { :cont , acc }
301+ end
302+
303+ _ , acc ->
304+ { :cont , acc }
305+ end
306+ )
296307
297308 { route , Map . get ( expectations , route ) }
298309 end
299310
311+ defp match_route ( path , route ) do
312+ case length ( path ) == length ( route ) do
313+ true ->
314+ path
315+ |> Enum . zip ( route )
316+ |> Enum . reduce_while (
317+ { true , % { } } ,
318+ fn
319+ { value , { param , _ , _ } } , { _ , params } ->
320+ { :cont , { true , Map . put ( params , Atom . to_string ( param ) , value ) } }
321+
322+ { segment , segment } , acc ->
323+ { :cont , acc }
324+
325+ _ , _ ->
326+ { :halt , { false , nil } }
327+ end
328+ )
329+
330+ false ->
331+ { false , nil }
332+ end
333+ end
334+
300335 defp do_up ( port , ref ) do
301336 plug_opts = [ self ( ) ]
302337 { :ok , socket } = :ranch_tcp . listen ( so_reuseport ( ) ++ [ ip: listen_ip ( ) , port: port ] )
@@ -353,16 +388,23 @@ defmodule Bypass.Instance do
353388 |> length
354389 end
355390
356- defp new_route ( fun , expected ) do
391+ defp new_route ( fun , path_parts , expected ) when is_list ( path_parts ) do
357392 % {
358393 fun: fun ,
359394 expected: expected ,
395+ path_parts: path_parts ,
360396 retained_plugs: % { } ,
361397 results: [ ] ,
362398 request_count: 0
363399 }
364400 end
365401
402+ defp new_route ( fun , :any , expected ) ,
403+ do: new_route ( fun , [ ] , expected )
404+
405+ defp new_route ( fun , path , expected ) ,
406+ do: new_route ( fun , build_path_match ( path ) |> elem ( 1 ) , expected )
407+
366408 defp cowboy_opts ( port , ref , socket ) do
367409 case Application . spec ( :plug_cowboy , :vsn ) do
368410 '1.' ++ _ -> [ ref: ref , acceptors: 5 , port: port , socket: socket ]
0 commit comments