Does a Plug router need a match/dispatch pipeline?
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:
- Is this really necessary?
- Do all routers need to have a pipeline in the same file they have the routes?
elixir plug
add a comment |
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:
- Is this really necessary?
- Do all routers need to have a pipeline in the same file they have the routes?
elixir plug
add a comment |
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:
- Is this really necessary?
- Do all routers need to have a pipeline in the same file they have the routes?
elixir plug
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:
- Is this really necessary?
- Do all routers need to have a pipeline in the same file they have the routes?
elixir plug
elixir plug
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
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Yes, both of the plugs are always required:
The
:matchplug is responsible for, well, matching the incoming request to one of the defined routes in the Router.The
:dispatchplug 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?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
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.
add a comment |
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Yes, both of the plugs are always required:
The
:matchplug is responsible for, well, matching the incoming request to one of the defined routes in the Router.The
:dispatchplug 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?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
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.
add a comment |
Yes, both of the plugs are always required:
The
:matchplug is responsible for, well, matching the incoming request to one of the defined routes in the Router.The
:dispatchplug 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?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
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.
add a comment |
Yes, both of the plugs are always required:
The
:matchplug is responsible for, well, matching the incoming request to one of the defined routes in the Router.The
:dispatchplug 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?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
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.
Yes, both of the plugs are always required:
The
:matchplug is responsible for, well, matching the incoming request to one of the defined routes in the Router.The
:dispatchplug 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?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
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.
edited Nov 22 '18 at 12:06
answered Nov 22 '18 at 11:46
SheharyarSheharyar
45.6k10109162
45.6k10109162
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Nov 22 '18 at 12:41
Aleksei MatiushkinAleksei Matiushkin
82.8k95692
82.8k95692
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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