elixir - How to enforce JSON encoding for Phoenix Request? -
there's api made phoenix, api works json.
but, when test , sent json curl
fail because phoenix doesn't parse request json. need explicitly add application/json
header curl
. i'd make more robust , tell phoenix parse requests json.
is there way force phoenix treat requests json , parse json?
update
i tried use plug set request headers @abm suggested, following code in router:
def set_format conn, format plug.conn.put_private conn, :phoenix_format, format end def put_req_header conn, {key, value} plug.conn.put_req_header conn, key, value end pipeline :api plug :put_req_header, {"accept", "application/json"} plug :put_req_header, {"content-type", "application/json"} plug :set_format, "json" plug :accepts, ["json"] end
the request has been made curl
curl -x post http://localhost:4000/api/upload -d '{"key": "value"}'
the connection looks like:
%plug.conn{adapter: {plug.adapters.cowboy.conn, :...}, assigns: %{}, before_send: [#function<1.93474994/1 in plug.logger.call/2>, #function<0.119481890/1 in phoenix.livereloader.before_send_inject_reloader/1>], body_params: %{"{\"key\": \"value\"}" => nil}, cookies: %plug.conn.unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "post", owner: #pid<0.483.0>, params: %{"{\"key\": \"value\"}" => nil}, path_info: ["api", "upload"], peer: {{127, 0, 0, 1}, 58408}, port: 4000, private: %{app.router => {[], %{}}, :phoenix_action => :upload, :phoenix_controller => apicontroller, :phoenix_endpoint => app.endpoint, :phoenix_format => "json", :phoenix_layout => {layoutview, :app}, :phoenix_pipelines => [:api], :phoenix_route => #function<8.59735990/1 in app.router.match_route/4>, :phoenix_router => app.router, :phoenix_view => apiview, :plug_session_fetch => #function<1.89562996/1 in plug.session.fetch_session/1>}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %plug.conn.unfetched{aspect: :cookies}, req_headers: [{"user-agent", "curl/7.37.1"}, {"host", "localhost:4000"}, {"accept", "application/json"}, {"content-length", "16"}, {"content-type", "application/json"}], request_path: "/api/upload", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "xxx"}], scheme: :http, script_name: [], secret_key_base: "xxx", state: :unset, status: nil}
it works if add -h "content-type: application/json"
parameter curl, without it doesn't work.
if google , want implement such behaviour.
lib/%app_name%/endpoint.ex
plug plug.head # add custom plug plug :set_format, "json"
define it:
defp set_format(conn, format) if regex.match?(~r/^api.*/, conn.host) plug.conn.put_private conn, :phoenix_format, format else conn end end
in example have dirty hack enforce json format subdomain api
it's not recommended since phoenix enforcing html @ time hack fix ridiculous behaviour like: elixir.phoenix.router.norouteerror pipeline :api
show 404.json instead of 404.html
Comments
Post a Comment