Does a Plug router need a match/dispatch pipeline?












1















I have a Router module that forwards request to other routers.
In this router I have a pipleline comprised of plug(:match) and plug(:dispatch).





defmodule Example.Router do
use Plug.Router

plug(:match)
plug(:dispatch)

forward("/check", to: Example.Route.Check)

get("/", do: send_resp(conn, 200, "router"))
end


In this second module I have the same pipeline:



defmodule Example.Route.Check do
use Plug.Router

plug(:match)
plug(:dispatch)

get "/", do: send_resp(conn, 200, "ok")
end




The issue I see here is that I always seem to need plug(:match) and plug(:dispatch) in all Plug Routers. So I have the following questions:




  1. Is this really necessary?

  2. Do all routers need to have a pipeline in the same file they have the routes?










share|improve this question





























    1















    I have a Router module that forwards request to other routers.
    In this router I have a pipleline comprised of plug(:match) and plug(:dispatch).





    defmodule Example.Router do
    use Plug.Router

    plug(:match)
    plug(:dispatch)

    forward("/check", to: Example.Route.Check)

    get("/", do: send_resp(conn, 200, "router"))
    end


    In this second module I have the same pipeline:



    defmodule Example.Route.Check do
    use Plug.Router

    plug(:match)
    plug(:dispatch)

    get "/", do: send_resp(conn, 200, "ok")
    end




    The issue I see here is that I always seem to need plug(:match) and plug(:dispatch) in all Plug Routers. So I have the following questions:




    1. Is this really necessary?

    2. Do all routers need to have a pipeline in the same file they have the routes?










    share|improve this question



























      1












      1








      1








      I have a Router module that forwards request to other routers.
      In this router I have a pipleline comprised of plug(:match) and plug(:dispatch).





      defmodule Example.Router do
      use Plug.Router

      plug(:match)
      plug(:dispatch)

      forward("/check", to: Example.Route.Check)

      get("/", do: send_resp(conn, 200, "router"))
      end


      In this second module I have the same pipeline:



      defmodule Example.Route.Check do
      use Plug.Router

      plug(:match)
      plug(:dispatch)

      get "/", do: send_resp(conn, 200, "ok")
      end




      The issue I see here is that I always seem to need plug(:match) and plug(:dispatch) in all Plug Routers. So I have the following questions:




      1. Is this really necessary?

      2. Do all routers need to have a pipeline in the same file they have the routes?










      share|improve this question
















      I have a Router module that forwards request to other routers.
      In this router I have a pipleline comprised of plug(:match) and plug(:dispatch).





      defmodule Example.Router do
      use Plug.Router

      plug(:match)
      plug(:dispatch)

      forward("/check", to: Example.Route.Check)

      get("/", do: send_resp(conn, 200, "router"))
      end


      In this second module I have the same pipeline:



      defmodule Example.Route.Check do
      use Plug.Router

      plug(:match)
      plug(:dispatch)

      get "/", do: send_resp(conn, 200, "ok")
      end




      The issue I see here is that I always seem to need plug(:match) and plug(:dispatch) in all Plug Routers. So I have the following questions:




      1. Is this really necessary?

      2. Do all routers need to have a pipeline in the same file they have the routes?







      elixir plug






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 '18 at 12:03









      Sheharyar

      45.6k10109162




      45.6k10109162










      asked Nov 22 '18 at 11:12









      Flame_PhoenixFlame_Phoenix

      6,0541778162




      6,0541778162
























          2 Answers
          2






          active

          oldest

          votes


















          4














          Yes, both of the plugs are always required:




          • The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.


          • The :dispatch plug is responsible for finally processing the request in the matched route.





          The obvious question here would be:




          Why not just do it automatically, since this needs to be done for every request?





          1. For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.


          2. Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.





          For example, you might want to check for an Authorization header before a route is matched and halt or continue the request from there. Or you might want to update the pageview count in a separate process, once a route is matched but before it's processed. Another common scenario is to parse a JSON request after a route is matched.



          You could do all this and more by customizing the pipeline:





          defmodule Example.Router do
          use Plug.Router

          plug(CheckRateLimit)
          plug(VerifyAuthHeader)
          plug(:match)
          plug(LogWebRequest)
          plug(Plug.Parsers, parsers: [:json], ...)
          plug(:dispatch)

          # ...
          end


          The ability to forward matched routes to other routers can make your web server much more sophisticated. For example, you could check the API rate limit in your base router, forward /admin routes to a separate AuthorizedRouter and put a custom VerifyAuthHeader plug there before those routes are matched.






          share|improve this answer

































            2














            While the answer by @Sheharyar is absolutely correct, I would add that you might DRY by introducing your own helper macro:





            defmodule Example.Route.Common do
            defmacro __using__(opts \ ) do
            quote do
            use Plug.Router

            plug(:match)
            plug(:dispatch)
            end
            end
            end


            And use it like:



            defmodule Example.Route.Check do
            use Example.Route.Common

            get "/", do: send_resp(conn, 200, "ok")
            end


            The opts parameter might be used to fine configure the plugs included.



            Kernel.use/2.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53429712%2fdoes-a-plug-router-need-a-match-dispatch-pipeline%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              4














              Yes, both of the plugs are always required:




              • The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.


              • The :dispatch plug is responsible for finally processing the request in the matched route.





              The obvious question here would be:




              Why not just do it automatically, since this needs to be done for every request?





              1. For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.


              2. Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.





              For example, you might want to check for an Authorization header before a route is matched and halt or continue the request from there. Or you might want to update the pageview count in a separate process, once a route is matched but before it's processed. Another common scenario is to parse a JSON request after a route is matched.



              You could do all this and more by customizing the pipeline:





              defmodule Example.Router do
              use Plug.Router

              plug(CheckRateLimit)
              plug(VerifyAuthHeader)
              plug(:match)
              plug(LogWebRequest)
              plug(Plug.Parsers, parsers: [:json], ...)
              plug(:dispatch)

              # ...
              end


              The ability to forward matched routes to other routers can make your web server much more sophisticated. For example, you could check the API rate limit in your base router, forward /admin routes to a separate AuthorizedRouter and put a custom VerifyAuthHeader plug there before those routes are matched.






              share|improve this answer






























                4














                Yes, both of the plugs are always required:




                • The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.


                • The :dispatch plug is responsible for finally processing the request in the matched route.





                The obvious question here would be:




                Why not just do it automatically, since this needs to be done for every request?





                1. For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.


                2. Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.





                For example, you might want to check for an Authorization header before a route is matched and halt or continue the request from there. Or you might want to update the pageview count in a separate process, once a route is matched but before it's processed. Another common scenario is to parse a JSON request after a route is matched.



                You could do all this and more by customizing the pipeline:





                defmodule Example.Router do
                use Plug.Router

                plug(CheckRateLimit)
                plug(VerifyAuthHeader)
                plug(:match)
                plug(LogWebRequest)
                plug(Plug.Parsers, parsers: [:json], ...)
                plug(:dispatch)

                # ...
                end


                The ability to forward matched routes to other routers can make your web server much more sophisticated. For example, you could check the API rate limit in your base router, forward /admin routes to a separate AuthorizedRouter and put a custom VerifyAuthHeader plug there before those routes are matched.






                share|improve this answer




























                  4












                  4








                  4







                  Yes, both of the plugs are always required:




                  • The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.


                  • The :dispatch plug is responsible for finally processing the request in the matched route.





                  The obvious question here would be:




                  Why not just do it automatically, since this needs to be done for every request?





                  1. For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.


                  2. Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.





                  For example, you might want to check for an Authorization header before a route is matched and halt or continue the request from there. Or you might want to update the pageview count in a separate process, once a route is matched but before it's processed. Another common scenario is to parse a JSON request after a route is matched.



                  You could do all this and more by customizing the pipeline:





                  defmodule Example.Router do
                  use Plug.Router

                  plug(CheckRateLimit)
                  plug(VerifyAuthHeader)
                  plug(:match)
                  plug(LogWebRequest)
                  plug(Plug.Parsers, parsers: [:json], ...)
                  plug(:dispatch)

                  # ...
                  end


                  The ability to forward matched routes to other routers can make your web server much more sophisticated. For example, you could check the API rate limit in your base router, forward /admin routes to a separate AuthorizedRouter and put a custom VerifyAuthHeader plug there before those routes are matched.






                  share|improve this answer















                  Yes, both of the plugs are always required:




                  • The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.


                  • The :dispatch plug is responsible for finally processing the request in the matched route.





                  The obvious question here would be:




                  Why not just do it automatically, since this needs to be done for every request?





                  1. For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.


                  2. Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.





                  For example, you might want to check for an Authorization header before a route is matched and halt or continue the request from there. Or you might want to update the pageview count in a separate process, once a route is matched but before it's processed. Another common scenario is to parse a JSON request after a route is matched.



                  You could do all this and more by customizing the pipeline:





                  defmodule Example.Router do
                  use Plug.Router

                  plug(CheckRateLimit)
                  plug(VerifyAuthHeader)
                  plug(:match)
                  plug(LogWebRequest)
                  plug(Plug.Parsers, parsers: [:json], ...)
                  plug(:dispatch)

                  # ...
                  end


                  The ability to forward matched routes to other routers can make your web server much more sophisticated. For example, you could check the API rate limit in your base router, forward /admin routes to a separate AuthorizedRouter and put a custom VerifyAuthHeader plug there before those routes are matched.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 22 '18 at 12:06

























                  answered Nov 22 '18 at 11:46









                  SheharyarSheharyar

                  45.6k10109162




                  45.6k10109162

























                      2














                      While the answer by @Sheharyar is absolutely correct, I would add that you might DRY by introducing your own helper macro:





                      defmodule Example.Route.Common do
                      defmacro __using__(opts \ ) do
                      quote do
                      use Plug.Router

                      plug(:match)
                      plug(:dispatch)
                      end
                      end
                      end


                      And use it like:



                      defmodule Example.Route.Check do
                      use Example.Route.Common

                      get "/", do: send_resp(conn, 200, "ok")
                      end


                      The opts parameter might be used to fine configure the plugs included.



                      Kernel.use/2.






                      share|improve this answer




























                        2














                        While the answer by @Sheharyar is absolutely correct, I would add that you might DRY by introducing your own helper macro:





                        defmodule Example.Route.Common do
                        defmacro __using__(opts \ ) do
                        quote do
                        use Plug.Router

                        plug(:match)
                        plug(:dispatch)
                        end
                        end
                        end


                        And use it like:



                        defmodule Example.Route.Check do
                        use Example.Route.Common

                        get "/", do: send_resp(conn, 200, "ok")
                        end


                        The opts parameter might be used to fine configure the plugs included.



                        Kernel.use/2.






                        share|improve this answer


























                          2












                          2








                          2







                          While the answer by @Sheharyar is absolutely correct, I would add that you might DRY by introducing your own helper macro:





                          defmodule Example.Route.Common do
                          defmacro __using__(opts \ ) do
                          quote do
                          use Plug.Router

                          plug(:match)
                          plug(:dispatch)
                          end
                          end
                          end


                          And use it like:



                          defmodule Example.Route.Check do
                          use Example.Route.Common

                          get "/", do: send_resp(conn, 200, "ok")
                          end


                          The opts parameter might be used to fine configure the plugs included.



                          Kernel.use/2.






                          share|improve this answer













                          While the answer by @Sheharyar is absolutely correct, I would add that you might DRY by introducing your own helper macro:





                          defmodule Example.Route.Common do
                          defmacro __using__(opts \ ) do
                          quote do
                          use Plug.Router

                          plug(:match)
                          plug(:dispatch)
                          end
                          end
                          end


                          And use it like:



                          defmodule Example.Route.Check do
                          use Example.Route.Common

                          get "/", do: send_resp(conn, 200, "ok")
                          end


                          The opts parameter might be used to fine configure the plugs included.



                          Kernel.use/2.







                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 22 '18 at 12:41









                          Aleksei MatiushkinAleksei Matiushkin

                          82.8k95692




                          82.8k95692






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53429712%2fdoes-a-plug-router-need-a-match-dispatch-pipeline%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              Paul Cézanne

                              UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

                              Angular material date-picker (MatDatepicker) auto completes the date on focus out