You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

需求:开发Phoenix框架/api/api_endpoints/接口以列出公开API端点

How to Build an API Endpoint to List Public Phoenix Routes

Nice question! I’ve tackled this exact scenario when building Phoenix APIs, and while there’s no built-in Phoenix function for this, it’s straightforward to roll your own solution. Here’s how I’d approach it:

Step 1: Mark Your Public Routes

First, you need a way to identify which routes are "public." The easiest way is to add a public: true metadata flag directly in your router. Open lib/my_app_web/router.ex and update your routes like this:

defmodule MyAppWeb.Router do
  use MyAppWeb, :router

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api", MyAppWeb do
    pipe_through :api

    # Public endpoints (marked with public: true)
    get "/users", UserController, :index, public: true, description: "List all users"
    post "/users", UserController, :create, public: true, description: "Create a new user"

    # Private endpoints (no public flag)
    get "/users/:id", UserController, :show
    put "/users/:id", UserController, :update
  end
end

I also added an optional description field to make the endpoint list more useful—feel free to skip that if you don’t need it.

Step 2: Create the Endpoint Controller

Next, make a controller to handle the /api/api_endpoints request. Create lib/my_app_web/controllers/api_endpoint_controller.ex with this code:

defmodule MyAppWeb.ApiEndpointController do
  use MyAppWeb, :controller

  def index(conn, _params) do
    public_routes =
      MyAppWeb.Router
      |> Phoenix.Router.routes()
      |> Enum.filter(&is_public_route?/1)
      |> Enum.map(&format_route/1)

    json(conn, %{public_api_endpoints: public_routes})
  end

  # Helper to check if a route is marked as public
  defp is_public_route?(route) do
    Keyword.get(route.opts, :public, false)
  end

  # Helper to format route data into a readable structure
  defp format_route(route) do
    %{
      method: route.verb |> Atom.to_string() |> String.upcase(),
      path: route.path,
      action: "#{Module.split(route.controller) |> List.last()}.#{route.action}",
      description: Keyword.get(route.opts, :description, "No description provided")
    }
  end
end

This code fetches all routes from your router, filters out the non-public ones, and formats the remaining routes into a clean JSON structure.

Step 3: Add the Route for Your Endpoint

Don’t forget to add the endpoint itself to your router—and mark it as public, of course! Add this line to your /api scope in router.ex:

get "/api_endpoints", ApiEndpointController, :index, public: true

Alternative: Filter by Pipeline

If you prefer grouping public routes with a dedicated pipeline instead of individual flags, you can adjust the logic. First, define a :public_api pipeline:

pipeline :public_api do
  plug :accepts, ["json"]
end

scope "/api", MyAppWeb do
  pipe_through :public_api

  # All routes here are public
  get "/users", UserController, :index
  get "/api_endpoints", ApiEndpointController, :index
end

scope "/api", MyAppWeb do
  pipe_through :api

  # Private routes here
  get "/users/:id", UserController, :show
end

Then update the is_public_route? helper in your controller to check the pipeline:

defp is_public_route?(route) do
  :public_api in route.pipelines
end

Testing It Out

Start your Phoenix server and hit GET http://localhost:4000/api/api_endpoints—you should get a JSON response with all your public routes, formatted nicely.

You can extend this further by adding more metadata (like request/response schemas) or even generating basic OpenAPI/Swagger docs from the route data if needed.

内容的提问来源于stack exchange,提问作者bexley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:50:52