Return response from plug immediately

1,684 views
Skip to first unread message

Alan McKean

unread,
Mar 14, 2016, 3:41:36 PM3/14/16
to phoenix-talk
I am writing a plug that does some handshaking with the client before any actual controller-bound requests and need to immediately return a response and avoid any further plug processing, including any invocation of a downstream controller. It's the first plug in the sequence. I have tried using send_resp(conn) followed by halt(conn) but it seems that downstream plugs are still called. Further, I am getting warnings on every request that '    ** (Plug.Conn.NotSentError) a response was neither set nor sent from the connection'. Any idea what is going on and how I can return a response immediately from my plug?

Chris McCord

unread,
Mar 14, 2016, 3:48:56 PM3/14/16
to phoeni...@googlegroups.com
It sounds like you perhaps leaked a "stale" conn that wasn't halted as what you described is the correct approach. Can you gist your code so we can take a look?

On Mar 14, 2016, at 3:41 PM, Alan McKean <alanw...@gmail.com> wrote:

I am writing a plug that does some handshaking with the client before any actual controller-bound requests and need to immediately return a response and avoid any further plug processing, including any invocation of a downstream controller. It's the first plug in the sequence. I have tried using send_resp(conn) followed by halt(conn) but it seems that downstream plugs are still called. Further, I am getting warnings on every request that '    ** (Plug.Conn.NotSentError) a response was neither set nor sent from the connection'. Any idea what is going on and how I can return a response immediately from my plug?

--
You received this message because you are subscribed to the Google Groups "phoenix-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phoenix-talk...@googlegroups.com.
To post to this group, send email to phoeni...@googlegroups.com.
Visit this group at https://groups.google.com/group/phoenix-talk.
To view this discussion on the web visit https://groups.google.com/d/msgid/phoenix-talk/dbec79da-2ac3-4aba-a2a4-a941df41b122%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alan McKean

unread,
Mar 14, 2016, 4:08:18 PM3/14/16
to phoenix-talk
I don't know how to send a gist to this group, but there isn't much that I need to send. Here it is ...

... the plug is called first
defmodule Handshake.Router do
  use Srpc.Web, :router

  pipeline :browser do
    plug OneTouch.Handshake
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :put_secure_browser_headers
  end

  scope "/", Handshake do
    pipe_through :browser

    post "/", HandshakeController, :index
    get "/", PageController, :index
  end
end

... in the Handshake plug, testing the immediate return of the response and halt
def call(conn, opts) do
send_resp(conn, 200, "FOO")
halt(conn)

... we always get to the controller, despite the halt(conn)
  def index(conn, _params) do
    Logger.debug("IN HANDSHAKE CONTROLLER")
  end

warning...
[info] POST /
[info] Sent 200 in 34µs
[debug] SRPC_KEY_EXCHANGE
[info] Sent 200 in 1ms
[debug] Processing by Srpc.SrpcController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[debug] IN HANDSHAKE CONTROLLER
[info] Sent 200 in 1ms
[error] #PID<0.784.0> running Srpc.Endpoint terminated
Request: POST /
** (exit) an exception was raised:
    ** (Plug.Conn.NotSentError) a response was neither 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

Alan McKean

unread,
Mar 14, 2016, 4:11:44 PM3/14/16
to phoenix-talk
Please ignore the name difference of the project and controller. I did a quick renaming of the pasted code for project privacy and didn't do it consistently. It's just the plug call(conn, opts) and the fact that it gets to the controller :index on every POST.

Aaron Weiker

unread,
Mar 14, 2016, 4:19:08 PM3/14/16
to phoeni...@googlegroups.com
When you call `send_resp/3` it will return back a new `conn`. You will need to call `halt/1` on this.

send_resp(conn, 200, "FOO")
|> halt(conn)

-Aaron

--
You received this message because you are subscribed to the Google Groups "phoenix-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phoenix-talk...@googlegroups.com.
To post to this group, send email to phoeni...@googlegroups.com.
Visit this group at https://groups.google.com/group/phoenix-talk.

Alan McKean

unread,
Mar 14, 2016, 4:34:14 PM3/14/16
to phoenix-talk
I was doing that in the real places that I was sending responses and halting. It was the test at the top of the plug that I forgot to pipe the conn to the halt. Here is what happens when I pipe the conn into the halt. As you can see, it continues through the plug and then on to the controller, despite the halt(conn)

def call(conn, opts) do
  Logger.debug("SENDING RESPONSE AND HALTING")
  send_resp(conn, 200, "FOO")
  |> halt

[info] POST /
[debug] SENDING RESPONSE AND HALTING
[info] Sent 200 in 45µs
[debug] FIRST HANDSHAKE
[info] Sent 200 in 1ms
[debug] Processing by Srpc.SrpcController.index/2
  Parameters: %{}
  Pipelines: [:browser]
[debug] IN HANDSHAKE CONTROLLER
[error] #PID<0.1024.0> running Srpc.Endpoint terminated
Request: POST /
** (exit) an exception was raised:
    ** (RuntimeError) expected action/2 to return a Plug.Conn, all plugs must receive a connection (conn) and return a connection
        (srpc) web/controllers/srpc_controller.ex:1: Srpc.SrpcController.phoenix_controller_pipeline/2
        (srpc) lib/phoenix/router.ex:261: Srpc.Router.dispatch/2
        (srpc) web/router.ex:1: Srpc.Router.do_call/2
        (srpc) lib/srpc/endpoint.ex:1: Srpc.Endpoint.phoenix_pipeline/1
        (srpc) lib/plug/debugger.ex:93: Srpc.Endpoint."call (overridable 3)"/2
        (srpc) lib/phoenix/endpoint/render_errors.ex:34: Srpc.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4


On Monday, March 14, 2016 at 12:41:36 PM UTC-7, Alan McKean wrote:

Chris McCord

unread,
Mar 14, 2016, 4:36:04 PM3/14/16
to phoeni...@googlegroups.com
Can you push your project to github so we can take a closer look?

--
You received this message because you are subscribed to the Google Groups "phoenix-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to phoenix-talk...@googlegroups.com.
To post to this group, send email to phoeni...@googlegroups.com.
Visit this group at https://groups.google.com/group/phoenix-talk.

Alan McKean

unread,
Mar 14, 2016, 5:32:41 PM3/14/16
to phoenix-talk
I will create a new, simplified project and try to recreate the problem. Unfortunately, I can't share the real code publicly.

barcentral...@gmail.com

unread,
Sep 28, 2017, 9:09:37 AM9/28/17
to phoenix-talk
Hi, Alan i dont know if it help you, but i was doing something similar in my case just check if params are valid if not send error respons. Code of plug look same and i got same error so i just switch plug from first line in pipeline to last one and its work nice...
Reply all
Reply to author
Forward
Message has been deleted
0 new messages