2016-07-04 5 views
6

Es gibt einige API mit Phoenix gemacht, die API arbeitet mit JSON.Wie erzwinge ich die JSON-Kodierung für Phoenix Request?

Wenn Sie es jedoch testen und JSON mit curl senden, schlägt es fehl, da Phoenix die Anforderung nicht als JSON analysiert. Sie müssen application/json Header zu curl explizit hinzufügen. Ich möchte es robuster machen und Phoenix bitten, alle Anfragen immer als JSON zu analysieren.

Gibt es eine Möglichkeit Phoenix zu zwingen, Anfragen immer als JSON zu behandeln und als JSON zu analysieren?

UPDATE

Ich habe versucht, Stecker zu verwenden Request-Header zu setzen, wie @AbM vorgeschlagen, mit dem folgenden Code in Router:

def set_format conn, format do Plug.Conn.put_private conn, :phoenix_format, format end 

def put_req_header conn, {key, value} do Plug.Conn.put_req_header conn, key, value end 

pipeline :api do 
    plug :put_req_header, {"accept", "application/json"} 
    plug :put_req_header, {"content-type", "application/json"} 
    plug :set_format, "json" 
    plug :accepts, ["json"] 
end 

Der Antrag mit Curl gemacht wurde

curl -X POST http://localhost:4000/api/upload -d '{"key": "value"}'      

Die Verbindung sieht so aus:

%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} 

Es funktioniert, wenn ich den Parameter -H "Content-Type: application/json" zu CURL hinzufügen, ohne es funktioniert es nicht.

+0

Würde einen Stecker in Ihrem Router mit ['put_req_header (conn," accept "," application/json ")' hinzufügen ] (https://hexdocs.pm/plug/Plug.Conn.html#put_req_header/3) dein Problem lösen? – AbM

+0

Nein, es funktioniert nicht :( –

+0

Können Sie ein bisschen mehr erarbeiten. Vielleicht zeigen Sie Ihren Router.ex – AbM

Antwort

1

Wenn jemand dafür googeln und ein solches Verhalten implementieren möchte.

lib/%APP_NAME%/endpoint.ex

plug Plug.Head 

# add custom plug 
plug :set_format, "json" 

es definieren:

defp set_format(conn, format) do 
    if Regex.match?(~r/^api.*/, conn.host) do 
     Plug.Conn.put_private conn, :phoenix_format, format 
    else 
     conn 
    end 
    end 

In diesem Beispiel schmutzigen Hack haben, die JSON-Format für Subdomain erzwingen api

Es ist nicht empfohlen, so zu tun Aber da Phoenix zu jeder Zeit HTML erzwingt, behebt dieses Hack lächerliches Verhalten ur like: Elixir.Phoenix.Router.NoRouteError für pipeline :api, um 404.json anstelle von 404.html anzuzeigen

Verwandte Themen