Giter Club home page Giter Club logo

phoenix_swagger's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

phoenix_swagger's Issues

Merge with everydayhero fork

Back in June 2016 everydayhero forked and largely re-wrote this project for use in a production application.

We added several features that were required to describe our swagger spec, and re-worked the internals to make the library easier to extend.

Is there interest from xerions in merging these projects?
If so, what is the best way to proceed, given that the everydayhero fork has diverged significantly from the original codebase?

Some of the main differences are outlined below:

Swagger Path DSL

  • Simplified parameter definitions to a single syntax:
parameter <name>, <location>, <type>, <description>, <opts>
  • :required is now passed as required: true in the trailing opts keyword list.
  • Description is required, as we found developers are too lazy to describe their parameters unless the framework encourages them to do so.
  • Arbitrary additional options can be passed to parameter definitions in the opts keyword list. This can be used for defining swagger enum parameters, regex pattern rules, format, default etc...
  • Translate example: "value" parameter keyword options to x-example vendor extension used by swagger-ui
  • Support for setting addition path properties (summary, description, produces, consumes, tags, operationId)
  • Pagination parameters helpers
  • Support multiple response schemas
  • Support for schema references for schema defined elsewhere in the spec

Example:

swagger_path :index do
    get "/api/teams"
    summary "Query for teams"
    description "Query for teams, with pagination"
    paging
    parameter :"filter[updated_after]", :query, :string, "Filters records to only those updated after this timestamp", format: "date-time"
    parameter :sort, :query, :string, "The field to sort the results by", enum: [:created_at, :updated_at], default: :updated_at, example: :updated_at
    response 200, "OK", Schema.ref(:Teams)
    response 400, "Client Error"
    tag :teams
  end

Swagger Definitions DSL

  • Each controller just exports a single swagger_definitions function, containing any schemas related to that controller.
  • Schemas are placed in the #/definitions/ section of the swagger document, and referenced from elsewhere using Schema.ref(:Name)
  • Schema.ref(external_schema_uri)can be used to refer to a schema defined in another file or external host.
  • JSON:API schema definition helpers define 3 schemas: a resource, a single item response, and a paginated response. Since JSON:API can be quite verbose to describe as a JSON-Schema, it is much simpler to use this DSL

Example:

  swagger_definitions do
    JsonApi.resource(:Team, :Teams) do
      description "A grouping of Supporters raising money for a common cause"
      attributes do
        name :string, "Name of the Team"
        page_url :string, "URL the links to the Team's Supporter Page"
        currency_code :string, "Currrency code of the donation amounts"
        total_amount :string, "Total amount of money raised offline and online"
        created_at :string, "Team created at time", format: "date-time"
        updated_at :string, "Team updated at time", format: "date-time"
      end
      link :self, "link to this resource"
      relationship :page
      relationship :leader_page
    end
  end

Mix Task

  • Support generating multiple swagger files from single project
  • Instead of putting swagger_info in mix.exs, it is now located in the router module, since there can be more than one per project.
  • Specify the router module and output file path as command line args
  • Remove restriction that routes must be pipelined through :api

Internals

  • credo linting
  • unit tests for swagger generation
  • Declare structs for PathObject, OperationObject, Parameter, ResponseObject, Schema matching the swagger spec
  • Re-implement Path DSL as a pipeline of functions that build up a PathObject struct, allowing new operations to be added very easily just by defining new functions, the swagger_path macro actually just expands to a regular elixir pipeline with two additional operations at the end, eg:
  def swagger_path_index do
    |> get("/api/teams")
    |> summary("Query for teams")
    |> description("Query for teams, with pagination")
    |> paging()
    |> parameter(:"filter[updated_after]", :query, :string, "Filters records to only those updated after this timestamp", format: "date-time")
    |> parameter(:sort, :query, :string, "The field to sort the results by", enum: [:created_at, :updated_at], default: :updated_at, example: :updated_at)
    |> response(200, "OK", Schema.ref(:Teams))
    |> response(400, "Client Error")
    |> tag(:teams)
    |> nest
    |> to_json
  end

Umbrella support with a library application

I am using this project to document an API under an umbrella app and one of this application does not have an application callback module (see https://elixir-lang.org/getting-started/mix-otp/supervisor-and-application.html). This app is used as a library by other applications and therefore there is no need of an application module.
The application/0 function on this application mix.exs file is:

def application do
	[extra_applications: [:logger]]
end

When executing mix phx.swagger.generate I get an exception on line 27 of swagger.generate.ex because there is no :mod in they application Keyword.

I change this method with the following code

defp top_level_namespace do
	if Keyword.has_key?(Mix.Project.get().application(), :mod) do
		Mix.Project.get().application()[:mod] |> elem(0) |> Module.split |> Module.concat
	else
		nil
	end
end

but I get an other exception on the collect_host/2 function which is linked to my router and enpoint params.

If I set customs router and endpoint from application A (let's say the api project), I get this exception when the generate task is executing for application B (the library project).
The attempt_load/1 function is able to load application A modules and therefore it does not skip this application.

I am using version 0.6.4 with Elixir 1.5.1

How to force swagger ui to expand all endpoints?

At the moment I am using this to open swagger ui with my spec:

  scope "/rest/swagger" do
    forward "/", PhoenixSwagger.Plug.SwaggerUI, otp_app: :mwapi_pull_ql, swagger_file: "swagger.json"
  end

Additionally would like to ensure that swagger ui expands all endpoints by default. Is it possible?

app host different from page host

My swagger docs are hosted on a different page than the app host. When the url generates dynamically for production env, phoenix_swagger skips setting the host and uses the page host instead. Could we get a work around for this issue? Maybe some config where we could specify the host?

Thanks :)

Upgrade issue

Sorry to bother,
I tried to upgrade phoenix swagger and it seems this commit caused things to break for me: 104a219
Things had been working fine as I was using the default port before the change. I am trying to figure out where Keyword.get(url, :port) would get its data since now my generated swagger doc includes the host (localhost) but not the port. If I manually add the port to the file, swagger UI works as expected. If I manually excise the host directive in the generated swagger doc, swagger works fine because it uses relative paths.

Not sure if it is relevant, but my project is phoenix 1.2.1.

Include swagger-ui

Would it make sense to bundle swagger-ui components and serve them? Also Include doc to only serve in development and maybe configs to serve and load the generated swagger.json file?

SwaggerUI does not recognize [:string, "null"] type used for JSONAPI prev/next links

Using master

screen shot 2017-10-31 at 2 05 14 pm

occurs because of json

"properties": {
        "links": {
          "type": "object",
          "properties": {
            "self": {
              "type": "string",
              "description": "Link to this page of results"
            },
            "prev": {
              "type": [
                "string",
                "null"
              ],
              "description": "Link to the previous page of results"
            },
            "next": {
              "type": [
                "string",
                "null"
              ],
              "description": "Link to the next page of results"
            },
            "last": {
              "type": "string",
              "description": "Link to the last page of results"
            },
            "first": {
              "type": "string",
              "description": "Link to the first page of results"
            }
          }
        },

which is generated by

prev: %Schema {
type: [:string, "null"],
description: "Link to the previous page of results"
},
next: %Schema {
type: [:string, "null"],
description: "Link to the next page of results"
},

update version in README

I've spent some time figuring out I was supposed to upgrade to 0.7.x to integrate with the 1.3 router. Maybe it would be nice to update the README with {:phoenix_swagger, "~> 0.7.0"} ?

Besides that, thank you for this awesome library

Question about endpoint path declaration

Not sure if this is the right place to ask, or if this is possible at all but ..
The issue Im trying to avoid is passing the wrong url of the endpoint to swagger_path/get

  swagger_path :index do
    get "/api/wrong_url"
    description "List stuff"
  end
  def index(conn, _params) do
    stuff = Stuff.list_stuff()
    conn |> json(%{stuff: stuff})
  end

I was wondering if something like this would be possible:

  swagger_path :index do
    get stuff_path(Endpoint, :index)
    description "List stuff"
  end
  def index(conn, _params) do
    stuff = Stuff.list_stuff()
    conn |> json(%{stuff: stuff})
  end

query parameters with [] in the name

Assume I have a URL which takes a path of: ?filter[id]=1&filter[name]=bob&order[][name]=asc&order[][age]=desc

How would one be able to convert this into swagger documentation, specifically, array of objects and arrays as the query parameter?

Hyphens in header parameters

We'd like to define a header parameter in our swagger documentation. The header is User-Agent but there appears to be no way of defining a parameter with a hyphen. As headers generally follow the hyphen pattern is there a work around for this?

Migrate CHANGELOG.md to Change Type, PR Link, Contributor Credit format

If you'd like to change to the detailed style that breaks changes up by type and links to the PR introducing the change like (https://github.com/KronicDeth/intellij-elixir/blob/master/CHANGELOG.md) that I got from @dblock's GoGaRuCo talk: youtu.be/8ijzefV-B7U, I can make a separate PR to do that.

See #138 (comment)
See #138 (comment)

@surik / @0xAX, @mbuhot wanted your input on this change before I make a PR to do the format conversion.

mix phoenix.swagger.generate fails

Hi

In the mix generate task you have the following line:

defp get_swagger_path(%{controller: controller, swagger_fun: fun, path: path}) do
    %{^path => _action} = apply(controller, fun, [])
  end

But pattern matching fails because the argument map does not have a literal key path to match on. The path key is the literal endpoint path.

using scopes for sub-urls instead of default

At the current release of phoenix_swagger, all paths are found under the point paths:.
This results in having just one group default in the swagger-ui.
I would like to have the urls grouped by scopes or resources found in the router.ex.
For an example have a look at the petshop.

Is swagger's `oneOf` feature supported?

Hello!

First off, thanks for creating / maintaining this package. It's pretty great, I've been using it to document my API so far.

It's unclear to me if it's possible to define multiple schemas as possible schemas for a endpoint's request body. It seems to me that Swagger supports this: https://swagger.io/docs/specification/describing-request-body/#anyof--oneof-3

Is this possible to do with this library?

Just as an example, I have an endpoint in my API where user's get access tokens for accessing protected endpoints in the API. They can use two different grant types to do this, and so there is one schema possible for each grant type.

The Swagger example is pretty clear and concise too:

      requestBody:
        description: A JSON object containing pet information
        content:
          application/json:
            schema:
              oneOf:
                - $ref: '#/components/schemas/Cat'
                - $ref: '#/components/schemas/Dog'
                - $ref: '#/components/schemas/Hamster'

just exporting the first function

I decorated multiple functions in my phoenix-app using swagger_model but in the resulting json file it mentions just the first decorated function in the controller after executing mix phoenix.swagger.generate

Does not work with port option in URL

There is a pattern matching error when the url contains the port option:

config :api, Api.Endpoint,
  http: [port: {:system, "PORT"}],
  url: [host: "external_domain", port: 1234]

This option is used for the URL helpers to generate the URL's with the external port.

For example i'm running my internal server on port 4000, and the public port is 1234. This is useful when you have multiple instances running on one server.

I just did an ugly fix for me (it only works for my project):
kim-company@d977e2d

Required nested parameters using square brackets always fail

Making a nested parameter, like filter[NAME] for JSONAPI required does not work

parameter(path_object, "filter[#{name}]", :query, :string, description, required: true)

screen shot 2017-11-07 at 8 52 49 am

screen shot 2017-11-07 at 8 53 01 am

So, the error has the brackets encoded, so I tried doing filter%5BNAME%5D, but that just makes the UI look bad and gets the % double encoded in the query, which passes the validation, but doesn't actually do the query because the parameter name is wrong for the controller.

screen shot 2017-11-07 at 8 58 51 am

I think this can be fixed with a change here

defp validate_query_params(path, conn) do
[{_path, _basePath, schema}] = :ets.lookup(@table, path)
parameters =
for parameter <- schema.schema["parameters"],
parameter["type"] != nil,
parameter["in"] in ["query", "path"] do
{parameter["type"], parameter["name"], conn.params[parameter["name"]], parameter["required"]}
end
validate_query_params(parameters)
end

I can open a PR once you confirm that I'm just not doing filter/nested parameters wrong.

Maintain a Changelog

Especially with the bigger changes that are apparently coming along, it'd be nice to a maintain a Changelog going forward.

I know it can be a bit annoying, but it's super helpful for anyone using the library. Plus, I personally found that it works best to either generate it automatically from specifically tagged commit messages or to add the Changelog entry to the "definition of done" :)

404 not found SwaggerUI files

SwaggerUI files not found

SwaggerUI files are missing (js, css)

I cloned this repo and run with cd project && mix deps.get && mix phoenix.server but the swaggerUI doesn't render properly

screen shot 2017-04-06 at 12 27 57 am

mix swagger no Endpoint configured.

Hi,

I'm getting the following message both in my app and in the simple example provided with the code when running mix swagger

"Skipping app simple, no Endpoint configured."

BTW I also had to change the swagger alias in mix.exs to "swagger": ["phx.swagger.generate priv/static/swagger.json"]

Is this something you're aware of? Or something I'm doing wrong?

Issue wit SwaggeUI plug

I have added this route

scope "/phoenix/api/swagger" do
    forward "/", PhoenixSwagger.Plug.SwaggerUI, otp_app: :another_app, swagger_file: "swagger.json"
  end

And getting this error

** (FunctionClauseError) no function clause matching in PhoenixSwagger.Plug.SwaggerUI.init/1
    lib/phoenix_swagger/plug/swaggerui.ex:169: PhoenixSwagger.Plug.SwaggerUI.init([otp_app: :another_app, swagger_file: "swagger.json"])
    (phoenix) lib/phoenix/router/route.ex:98: Phoenix.Router.Route.build_dispatch/1
    (phoenix) lib/phoenix/router/route.ex:84: Phoenix.Router.Route.build_route_match/2
    (phoenix) lib/phoenix/router/route.ex:56: Phoenix.Router.Route.exprs/1
    (phoenix) lib/phoenix/router.ex:320: Phoenix.Router."-MACRO-__before_compile__/2-fun-0-"/1
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    (phoenix) expanding macro: Phoenix.Router.__before_compile__/1

Whats wrong with it?

Is master stable now?

Because current master is much better than 0.3.3, I want to use it.
But I don't know it's stable or not and when next version will be released.
If it's stable and won't be released soon, I will use current master.
If not, I will wait next version.

allow format of types

In parameter in the swagger_model it is possible to set the swagger type of the parameter (for example string, but it is not yet possible to also set the format, for example password.
Please have a look at the swagger data types and add the support for format.

The default namespace {Project}.Web is actually ProjectWeb in Phoenix 1.3

The following warning appears when generating the Swagger json file for a Phoenix 1.3
$ mix phx.swagger.generate 19:30:36.375 [warn] Skipping app product_service, no Router configured.

Also, I encountered another error that may or may not be related, when I did the following to include the --router and --endpoint switches:

`$ mix phx.swagger.generate endpoint.json -e ProductServiceWeb -r ProductServiceWeb.Router

** (FunctionClauseError) no function clause matching in Keyword.get/3

The following arguments were given to Keyword.get/3:

    # 1
    nil

    # 2
    :url

    # 3
    nil

Attempted function clauses (showing 1 out of 1):

    def get(keywords, key, default) when is_list(keywords) and is_atom(key)

(elixir) lib/keyword.ex:178: Keyword.get/3
lib/mix/tasks/swagger.generate.ex:180: Mix.Tasks.Phx.Swagger.Generate.collect_host/2
lib/mix/tasks/swagger.generate.ex:89: Mix.Tasks.Phx.Swagger.Generate.swagger_document/2
lib/mix/tasks/swagger.generate.ex:55: Mix.Tasks.Phx.Swagger.Generate.run/1
(mix) lib/mix/task.ex:301: Mix.Task.run_task/3
(mix) lib/mix/cli.ex:75: Mix.CLI.run_task/2
(elixir) lib/code.ex:376: Code.require_file/2`

Documenting headers

Where can I find some examples how to document headers, especially the ones for authorization?

Poison Error when Generating Swagger docs

Hello.
I'm using Phoenix. 1.2.1 with elixir 1.3.2

I keep getting this error when I try to generate swagger docs

mix phoenix.swagger.generate
** (Poison.EncodeError) unable to encode value: {:re_pattern, 1, 0, 0, <<69, 82, 67, 80, 96, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 99, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...>>}
    lib/poison/encoder.ex:354: Poison.Encoder.Any.encode/2
    lib/poison/encoder.ex:207: anonymous fn/5 in Poison.Encoder.Map.encode/3
    lib/poison/encoder.ex:208: Poison.Encoder.Map."-encode/3-lists^foldl/2-1-"/3
    lib/poison/encoder.ex:208: Poison.Encoder.Map.encode/3
    lib/poison/encoder.ex:207: anonymous fn/5 in Poison.Encoder.Map.encode/3
    lib/poison/encoder.ex:208: Poison.Encoder.Map."-encode/3-lists^foldl/2-1-"/3
    lib/poison/encoder.ex:208: Poison.Encoder.Map.encode/3
    lib/poison/encoder.ex:241: anonymous fn/4 in Poison.Encoder.List.encode/3

This is right after installing swagger.

   {:phoenix_swagger, "~> 0.5.1"},
    {:ex_json_schema, "~> 0.5"},

The error is very cryptic and doesn't show where I need to look. Does anyone have any insight into what might be causing this?

includes

How does this support includes? We make extensive use of side loading with json-api want to use this to validate our responses in our tests.

Here's what we're looking for:

  • Validates json:api response has the right resource in the data key
  • Validates each resource has exactly the attributes/relationships we specify in swagger, no more, no less
  • Validates includes has the resources we specify, validating the attributes/relationships of those resources

Looks like we can do 1 and 2 pretty easily, but how about validating includes?

No DSL?

Is it possible to keep all swagger documentation outside of a controller?

Error when route to plug with keyword options

Given some code in a router:

scope "/my/api" do
  forward "/foo", MySpecialPlug, option1: "baz"
end

phoenix.swagger.generate fails to generate swagger:

** (ArgumentError) cannot convert the given list to a string.

To be converted to a string, a list must contain only:

  * strings
  * integers representing Unicode codepoints
  * or a list containing one of these three elements

Please check the given list or call inspect/1 to get the list representation, got:

[option1: "baz"]

    (elixir) lib/list.ex:709: List.to_string/1
    lib/mix/tasks/swagger.generate.ex:128: Mix.Tasks.Phoenix.Swagger.Generate.find_swagger_path_function/1
    (elixir) lib/enum.ex:1229: Enum."-map/2-lists^map/1-0-"/2
    lib/mix/tasks/swagger.generate.ex:119: Mix.Tasks.Phoenix.Swagger.Generate.collect_paths/2
    lib/mix/tasks/swagger.generate.ex:82: Mix.Tasks.Phoenix.Swagger.Generate.swagger_document/1
    lib/mix/tasks/swagger.generate.ex:45: Mix.Tasks.Phoenix.Swagger.Generate.run/1
    (mix) lib/mix/task.ex:294: Mix.Task.run_task/3
    (elixir) lib/enum.ex:645: Enum."-each/2-lists^foreach/1-0-"/2

The code is expecting a simple atom like :index or :show, failing to match a keyword list.

ex_json_schema is required to be added to :applications even if not needed

Hi.

I use phoenix_swagger only to generate specs, and I'm not going to use it for validation.
If I follow your instructions (add to deps, use macros) it warns me during release build:

You have dependencies (direct/transitive) which are not in :applications!
The following apps should be added to :applications in mix.exs:

        phoenix_swagger -> ex_json_schema => ex_json_schema is missing from phoenix_swagger

Continue anyway? Your release may not work as expected if these dependencies are required! [Yn]:

I'd like to not see it, and I don't want to start additional application.
What should I do?

Phoenix 1.3 dependency resolution

MacBook-Proi$ mix deps.get
Running dependency resolution...

Failed to use "poison" (version 3.1.0) because
phoenix (version 1.3.0-rc.1) requires ~> 2.2 or ~> 3.0
phoenix_swagger (version 0.6.0) requires ~> 1.5 or ~> 2.0
mix.lock specifies 3.1.0

How do I resolve this.

Order of endpoints

The order of endpoints is random now because it uses Poison to encode swagger api data to JSON.
I've tried to solve this problem, but I can't find a good way.
Do you have any idea about it?

Re-using swagger_path parameters

I'm just wondering if there's any way to re-use parameters between different paths.

For example, let's way we've got a few API endpoints
/people
/projects
/books

And all of these endpoints accept some common parameters:
page_size, page_offset, sort_by, sort_direction.

Is there any way of defining these parameters in one place and re-using them in the swagger_path definition - basically, dynamically adding the parameters for a path?

Given that swagger_path is a DSL built by macros, and that the swagger.generate mix task is run on the static code, I don't think this is possible, but I figured it's worth asking incase I overlooked something.

Thanks!

Define different endpoint for swagger's CURL example

Hi,
I am running a phoenix application inside a docker container. So from the perspective of the phoenix endpoint the host is localhost. When using the swagger UI to create CURL commands they as well assume we need to curl against localhost instead of the real host where the docker container is running. I couldn't find an opportunity for now to reconfigure that. Is there an opportunity I missed? Otherwise this would be an interesting feature.

Validation plug fails

I have the following definition

swagger_path :index do
    get "/api/v1/conversations"
    parameters do
      query :app_id, :string, "App id", required: true
      query :filter, :string, "Filter"
      query :closed, :boolean, "Filter by closed state"
    end
    response 200, "OK"
  end

And I include the Validator in my router pipeline.

Calling this endpoint always returns the error

{"error":{"path":"/api/v1/conversations","message":"API does not provide resource"}}

I inspected the code, and it appears that the line in validate_plug.ex

Enum.filter(:ets.tab2list(@table), fn({path, basePath, _}) ->

:ets.tab2list(@table) returns an empty list

Any ideas?

Multiple API versions

Hi, thanks for the great library.

We're working on versioning our API, which will result in some new endpoints namespaced by the version number. Our API would end up something like:
/api/v1/users/{id}
/api/v2/users/{id}..etc

The different API versions may have different parameters and responses. Rather than confusing a user and showing both versions on one page, it would be a better option to have separate swagger.json files for separate versions.

Currently, the task to generate the swagger file looks through all controllers for all 'swagger_paths' and generates the swagger file from those.

Is there any way to handle multiple versions?

If not would you be open to a Pull Request for this, and what would be the best way to implement it?

One idea would be to ensure specific controllers for each version and adding command-line argument of the controllers to use (or exclude) for generating the swagger doc. These could then be used to filter the the paths here. This would enable a custom swagger file with:

mix phx.swagger.generate swagger-v2.json -c [Simple.Web.v2.UserController, Simple.Web.v2.ItemsController]

However, this would require separate controllers for different versions, which isn't exactly ideal.

It would be great if we could find a nice, user-friendly solutions for this that doesn't require lots of duplicate and poorly structure code on our app.

Thanks in advance!

use swagger_models for multiple http methods

During my tests, I found out, that if you have one url matching on two different http methods (POST and GET) with two different functions of course, phoenix_swagger uses just the model for the get method (maybe the first it founds).
In my opinion the wanted behavior would be to have both methods for the domain listed in the resulting swagger json file.

How to use PhoenixSwagger.Plug.SwaggerUI?

I tried to run the example project in this repo, but it doesn't work.
It can't find assets in priv folder of phoenix_swagger.

[info] GET /api/swagger
[info] Sent 200 in 15ms
[info] GET /api/css/reset.css
[debug] ** (Phoenix.Router.NoRouteError) no route found for GET /api/css/reset.css (Simple.Router)
    (simple) web/router.ex:1: Simple.Router.match_route/4
    (simple) web/router.ex:1: Simple.Router.do_call/2
    (simple) lib/simple/endpoint.ex:1: Simple.Endpoint.phoenix_pipeline/1
    (simple) lib/plug/debugger.ex:123: Simple.Endpoint."call (overridable 3)"/2
    (simple) lib/simple/endpoint.ex:1: Simple.Endpoint.call/2
    (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
    (cowboy) /Users/json/workspace/opensource/phoenix_swagger/examples/simple/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4

local swagger-ui is not working

Example
https://puu.sh/y1QBn/2b61df33e1.png
JS console output

Uncaught TypeError: Cannot read property '$ref' of undefined
    at module.exports.Resolver.resolveTo (resolver.js:755)
    at module.exports.Resolver.resolveTo (resolver.js:804)
    at module.exports.Resolver.resolve (resolver.js:77)
    at response (client.js:239)
    at responseInterceptor (http.js:79)
    at obj.on.response (http.js:98)
    at http.js:362
    at Request.callback (client.js:692)
    at Request.<anonymous> (client.js:514)
    at Request.Emitter.emit (index.js:133)

Generated json is valid, tested in swagger-ui test website
http://petstore.swagger.io/

use multiple responses in swagger_model

At the moment it is not possible to set multiple responses (200 and 500 for example) for a single swagger_model.
Please add the support for multiple responses to phoenix_swagger.

`PhoenixSwagger.Plug.SwaggerUI` crashes during request of `index.html`

There is simple routing rule:

scope "/api2/v1/swagger" do
  forward "/",  Mod
end

Where Mod, is just:

defmodule Mod do
  use Plug.Builder

  plug PhoenixSwagger.Plug.SwaggerUI, otp_app: :my_app, swagger_file: "api_specs_v1.json"
end

After application start, we can get a crash during request of /api2/v1/swagger/index.html:

   ** (FunctionClauseError) no function clause matching in PhoenixSwagger.Plug.SwaggerUI.do_match/4
        (phoenix_swagger) lib/phoenix_swagger/plug/swaggerui.ex:142: PhoenixSwagger.Plug.SwaggerUI.do_match(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{index_body: "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\">\n  <title>Swagger UI</title>\n  <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png\" sizes=\"32x32\" />\n  <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png\" sizes=\"16x16\" />\n  <link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>\n  <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>\n\n  <script src='lib/object-assign-pollyfill.js' type='text/javascript'></script>\n  <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>\n  <script src='lib/handlebars-4.0.5.js' type='text/javascript'></script>\n  <script src='lib/lodash.min.js' type='text/javascript'></script>\n  <script src='lib/backbone-min.js' type='text/javascript'></script>\n  <script src='swagger-ui.js' type='text/javascript'></script>\n  <script src='lib/highlight.9.1.0.pack.js' type='text/javascript'></script>\n  <script src='lib/highlight.9.1.0.pack_extended.js' type='text/javascript'></script>\n  <script src='lib/jsoneditor.min.js' type='text/javascript'></script>\n  <script src='lib/marked.js' type='text/javascript'></script>\n  <script src='lib/swagger-oauth.js' type='text/javascript'></script>\n\n  <!-- Some basic translations -->\n  <!-- <script src='lang/translator.js' type='text/javascript'></script> -->\n  <!-- <script src='lang/ru.js' type='text/javascript'></script> -->\n  <!-- <script src='lang/en.js' type='text/javascript'></script> -->\n\n  <script type=\"text/javascript\">\n    $(function () {\n      var url = window.location.search.match(/url=([^&]+)/);\n      if (url && url.length > 1) {\n        url = decodeURIComponent(url[1]);\n      } else {\n        url = \"api_specs_v1.json\";\n      }\n\n      hljs.configure({\n        highlightSizeThreshold: 5000\n      });\n\n      // Pre load translate...\n      if(window.SwaggerTranslator) {\n        window.SwaggerTranslator.translate();\n      }\n      window.swaggerUi = new SwaggerUi({\n        url: url,\n        dom_id: \"swagger-ui-container\",\n        supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],\n        onComplete: function(swaggerApi, swaggerUi){\n          if(typeof initOAuth == \"function\") {\n            initOAuth({\n              clientId: \"your-client-id\",\n              clientSecret: \"your-client-secret-if-required\",\n              realm: \"your-realms\",\n              appName: \"your-app-name\",\n              scopeSeparator: \" \",\n              additionalQueryStringParams: {}\n            });\n          }\n\n          if(window.SwaggerTranslator) {\n            window.SwaggerTranslator.translate();\n          }\n        },\n        onFailure: function(data) {\n          log(\"Unable to Load SwaggerUI\");\n        },\n        docExpansion: \"none\",\n        jsonEditor: false,\n        defaultModelRendering: 'schema',\n        showRequestHeaders: false,\n        showOperationIds: false\n      });\n\n      window.swaggerUi.load();\n\n      function log() {\n        if ('console' in window) {\n          console.log.apply(console, arguments);\n        }\n      }\n  });\n  </script>\n</head>\n\n<body class=\"swagger-section\">\n<div id='header'>\n  <div class=\"swagger-ui-wrap\">\n    <a id=\"logo\" href=\"http://swagger.io\"><img class=\"logo__img\" alt=\"swagger\" height=\"30\" width=\"30\" src=\"images/logo_small.png\" /><span class=\"logo__title\">swagger</span></a>\n    <form id='api_selector'>\n      <div class='input'><input placeholder=\"http://example.com/api\" id=\"input_baseUrl\" name=\"baseUrl\" type=\"text\"/></div>\n      <div id='auth_container'></div>\n      <div class='input'><a id=\"explore\" class=\"header__btn\" href=\"#\" data-sw-translate>Explore</a></div>\n    </form>\n  </div>\n</div>\n\n<div id=\"message-bar\" class=\"swagger-ui-wrap\" data-sw-translate>&nbsp;</div>\n<div id=\"swagger-ui-container\" class=\"swagger-ui-wrap\"></div>\n</body>\n</html>\n", spec_url: "api_specs_v1.json", swagger_file_path: "/home/alex/work/my_app/_build/test/lib/my_app/priv/static/api_specs_v1.json", my_app_http_req_start_timestamp: 1492775209200}, before_send: [#Function<0.83905032/1 in MyApp.Plug.Log.call/2>], body_params: %{}, cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false, host: "localhost", method: "GET", owner: #PID<0.942.0>, params: %{}, path_info: ["index.html", "api_specs_v1.json"], path_params: %{}, peer: {{127, 0, 0, 1}, 55224}, port: 8080, private: %{MyApp.Router => {[], %{MyApp.Web.ApiSwaggerUi.Controller => []}}, :phoenix_endpoint => MyApp.Endpoint, :phoenix_pipelines => [], :phoenix_route => #Function<38.42921517/1 in MyApp.Router.match_route/4>, :phoenix_router => MyApp.Router}, query_params: %{}, query_string: "", remote_ip: {127, 0, 0, 1}, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies}, req_headers: [{"host", "localhost:8080"}, {"user-agent", "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:49.0) Gecko/20100101 Firefox/49.0"}, {"accept", "application/json;charset=utf-8,*/*"}, {"accept-language", "en-US,en;q=0.5"}, {"accept-encoding", "gzip, deflate"}, {"referer", "http://localhost:8080/api2/v1/swagger/index.html"}, {"connection", "keep-alive"}], request_path: "/api2/v1/swagger/index.html/api_specs_v1.json", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "g96bude69ahbjfkd1m3s1brntclvjqur"}], scheme: :http, script_name: ["api2", "v1", "swagger"], secret_key_base: nil, state: :unset, status: nil}, "GET", ["index.html", "api_specs_v1.json"], "localhost")
        (phoenix_swagger) lib/phoenix_swagger/plug/swaggerui.ex:1: PhoenixSwagger.Plug.SwaggerUI.plug_builder_call/2
        (my_app) web/controllers/api_swagger_ui.ex:1: MyApp.Web.ApiSwaggerUi.Controller.plug_builder_call/2
        (phoenix) lib/phoenix/router/route.ex:154: Phoenix.Router.Route.forward/4
        (my_app) lib/phoenix/router.ex:261: MyApp.Router.dispatch/2
        (my_app) web/router.ex:1: MyApp.Router.do_call/2
        (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.phoenix_pipeline/1
        (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.call/2
17:46:49.230 [warning] lager_error_logger_h dropped 49 messages in the last second that exceeded the limit of 150 messages/sec
17:46:49.230 [error] Ranch listener 'Elixir.MyApp.Endpoint.HTTP' terminated with reason: {{#{'__exception__' => true,'__struct__' => 'Elixir.FunctionClauseError',arity => 4,function => do_match,module => 'Elixir.PhoenixSwagger.Plug.SwaggerUI'},[{'Elixir.PhoenixSwagger.Plug.SwaggerUI',do_match,[#{'__struct__' => 'Elixir.Plug.Conn',adapter => {'Elixir.Plug.Adapters.Cowboy.Conn',{http_req,#Port<0.24192>,ranch_tcp,keepalive,<0.942.0>,<<"GET">>,'HTTP/1.1',{{127,0,0,1},55224},<<"localhost">>,undefined,8080,<<"/api2/v1/swagger/index.html/api_specs_v1.json">>,undefined,<<>>,undefined,...}},...},...],...},...]},...}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.