Plug’s Router enables you to write functions “inline” and even access the variables defined in the route path:
get "/hello/:name" do
send_resp(conn, 200, "hello #{name}")
end
Does phoenix enable you to do something like this? I want to keep using all of Phoenix helpers, but for simple stuff it would be nice to be able to code in a micro-framework style, and move to things to controllers/views/etc as the project grows.
Note to Forum Admins: Add plug
tag.
3 Likes
Our router does not support this, but you can do something like forward all unhanded requests in the Phoenix router to your Plug.Router, or vice versa by forwarding all unhanded Plug router requests to the Phoenix Router. It’s turtles all the way down: i.e.:
defmodule MyApp.Router do
...
get "/", PageController, :index
forward "/", MyApp.PlugRouter
end
defmodule PlugRouter do
use Plug.Router
get "/hello/:name" do
send_resp(conn, 200, "hello #{name}")
end
end
5 Likes
Chris,
Awesome solution! So simple. From a marketing perspective it would be interesting if Phoenix supported this more natively someday: Phoenix - A micro/macro framework that scales as your code base and users grow.
I heard that there are plans for the code generators to create even smaller projects, this could help to remove the controllers
folder if needed. I you could optionally code in Plugs style, the most bare-bone Phoenix project would just need a web folder like this
web
| - router.ex
| - web.ex
Is there a way to enable this behavior when to get, post, put, etc, macros have a do
block?
There is a certain appeal to microframeworks, single file, functions are routes, etc. Phoenix could totally nail this.
Getting an error with @chrismccord answer:
Here is my Plug Router
defmodule PlugRouter do
use Plug.Router
plug :fetch_session
get "/hello" do
IO.inspect("Hello World")
send_resp(conn, 200, "world")
end
end
Added this to the phoenix router
forward "/plug", PlugRouter
I am getting this error on localhost:4000/plug/hello
Server: localhost:4000 (http)
Request: GET /plug/hello
** (exit) an exception was raised:
** (Plug.Conn.NotSentError) no response was set nor sent from the connection
(plug) lib/plug/adapters/cowboy/handler.ex:42: Plug.Adapters.Cowboy.Handler.maybe_send/2
(plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
The term “micro framework” is a pointless description imo. If you want a library and want to stitch code together then libraries are fine, but we lie to ourselves calling things “micro frameworks” and then folks somehow put negative connotations then to “frameworks”. Here’s an entire Phoenix app:
defmodule MyApp.Endpoint do
use Phoenix.Endpoint
def call(conn, _) do, do: Plug.Conn.send_resp(conn, 200, "micro!")
end
We could generate a project with just this file, your supervision tree, and a mix.exs, but it wouldn’t be useful for anything other than showing how micro we are
Phoenix has always been about sane defaults balancing features and modularity. Every decision to add a directory or file to the default project structure is weighed heavily. You are of course free to not use “controllers”, but the moment your app grows you’ll end up with a “plugs” or a “routers” directory that is doing the same thing as what we call controllers, so pick your poison.
6 Likes
Yeah, literally don’t mean “single file” as in Flask, mix phoenix.new
does enough to help you get started quickly, but there are people (including myself) who feel that for simple things the complete folder structure is too heavy-weight, see this reddit thread.
@chrismccord Any idea of why I am getting the error previously mentioned? This is on Phoenix 1.0.2, I’ll test in a more recent version.
Edit: Fixed the reddit thread link.
I am getting this error in 1.1.4
== Compilation error on file web/router.ex ==
** (RuntimeError) no plugs have been defined in PlugRouter
(plug) expanding macro: Plug.Builder.__before_compile__/1
web/router.ex:15: PlugRouter (module)
(elixir) lib/kernel/parallel_compiler.ex:100: anonymous fn/4 in Kernel.ParallelCompiler.spawn_compilers/8
Is this module a Plug?
I was missing
plug :match
plug :dispatch
3 Likes