sugar-framework / sugar

Modular web framework for Elixir
https://sugar-framework.github.io/
MIT License
430 stars 29 forks source link

Error on mix server #61

Closed zabirauf closed 9 years ago

zabirauf commented 9 years ago

I am following the getting started guide. When i run mix server i get the following error

** (FunctionClauseError) no function clause matching in Keyword.put_new/3
(elixir) lib/keyword.ex:320: Keyword.put_new(nil, :ref, Router.HTTP)
lib/plug/adapters/cowboy.ex:35: Plug.Adapters.Cowboy.args/4
lib/plug/adapters/cowboy.ex:120: Plug.Adapters.Cowboy.run/4
lib/mix/tasks/server.ex:27: Mix.Tasks.Server.run/1
(mix) lib/mix/cli.ex:55: Mix.CLI.run_task/2

I am running this on Mac Yosemite and Elixir is v1.0.2

slogsdon commented 9 years ago

Hey @zabirauf, I think I know what the issue is, but I have a couple of questions:

In the meantime, make sure you have something like this in your config/config.exs file:

use Mix.Config

config :sugar,
  router: Simple.Router

config :sugar, Simple.Router,
  https_only: false,
  http: [ port: 4000 ]
slogsdon commented 9 years ago

PS, https://sugar-framwork.github.io/ is currently out of sync with the latest code. :frowning: For the most part, I try to keep @doc comments up to date with code changes, so when in doubt, check those at http://hexdocs.pm/sugar/.

YellowApple commented 9 years ago

Am also able to reproduce with OSX Yosemite and Elixir 1.0.2 (after following the official docs to-the-letter - including using mix sugar.init to scaffold the project - and making some corrections to config.exs per your first comment). Occurs regardless of whether Sugar is a Hex or git dependency.

On a whim, I decided to change my own app's lib/my_app/router.ex to reflect a module name of MyApp.Router (like what's implied in your comment and as described using the sample app) instead of simply Router (what mix sugar.init defaults to). This resulted in a new error (again, regardless of whether Sugar was obtained via Hex or git):

** (UndefinedFunctionError) undefined function: Router.run/0 (module Router is not available)
    Router.run()
    lib/mix/tasks/server.ex:27: Mix.Tasks.Server.run/1
    (mix) lib/mix/cli.ex:55: Mix.CLI.run_task/2
    (elixir) lib/code.ex:316: Code.require_file/2

I've noticed in Sugar's lib/mix/tasks/server.ex that the offending line (27) is based on calling the run/1 method of a router variable, which is populated by a call to Sugar.Config.get(:placid, :router, Router). Having no idea what :placid is, I temporarily forked and adjusted that line to read Sugar.Config.get(:sugar, :router, Router), which makes more sense and gets past that error (Pull request submitted, unless there's some legitimate reason why :placid is the thing being checked; perhaps an old module name or something?).

However, doing that (or even going the other way and just calling everything Router instead of MyApp.Router, with or without the fix in my fork) now results in a new error:

** (ArgumentError) could not start Cowboy adapter, to use relative certificate with https, the :otp_app option needs to be given to the adapter
    lib/plug/adapters/cowboy.ex:204: Plug.Adapters.Cowboy.fail/1
    lib/plug/adapters/cowboy.ex:167: Plug.Adapters.Cowboy.normalize_ssl_file/2
    (elixir) lib/enum.ex:1261: Enum."-reduce/3-lists^foldl/2-0-"/3
    lib/plug/adapters/cowboy.ex:135: Plug.Adapters.Cowboy.normalize_options/2
    lib/plug/adapters/cowboy.ex:37: Plug.Adapters.Cowboy.args/4
    lib/plug/adapters/cowboy.ex:120: Plug.Adapters.Cowboy.run/4
    (my_app) lib/my_app/router.ex:1: MyApp.Router.run/1
    lib/mix/tasks/server.ex:27: Mix.Tasks.Server.run/1

That error (and, now that I think about it, the original error) seems to be referencing an attempt to spin up a HTTPS server, even though :https_only was set to false and no :https key was defined. Digging through Sugar.Router.run/1 revealed that run/1 does a check on :https via a normal if statement; forcing :https to be set to false (in config.exs) fixed this last issue, and now mix server works properly (returning a "Hello world" as expected).

YellowApple commented 9 years ago

Long story short: this issue can be worked around by making sure the router module names match and explicitly setting :https to false, like so (in config/config.exs):

use Mix.Config

config :sugar,
  router: Router

config :sugar, Router,
  https_only: false,
  http: [port: 4000],
  https: false

Alternately, one could (hypothetically) provide the necessary parameters for a HTTPS server to actually work. I haven't tested this yet.

slogsdon commented 9 years ago

@YellowApple Thanks for running through all of this! It definitely needs some tweaking with how HTTP/HTTPS listeners are ran, along with some additional tests for those and the server Mix task.

To explain about the :placid bit, I have another project (Placid) that started with the router from Sugar. I made a bunch of improvements to the router in Placid, and recently, I brought those changes back into Sugar and managed to forgot to change a couple references to Placid. I'm thinking about creating a shared library to share most of the router macros with the two projects and anyone else who might find a use for it (it's fairly portable), but I haven't decided quite yet.

YellowApple commented 9 years ago

No problem, @slogsdon; I'm just glad my code works now ;) A documentation update would probably be useful for future folks pulling out their hair over Cowboy whining about HTTPS.

Good to know about Placid; I was looking for a good way to adapt Sugar to route API requests, and it looks like Placid is well-optimized for that while still having plenty of Sugary goodness. I would definitely abstract as much shared code between the two as possible into a shared library, if only to make development easier (since they seem to share a lot in common).

slogsdon commented 9 years ago

I think I will be extracting that code into a separate library. I just diff'd them, and the differences should be able to be wrapped in configurations, merged, or removed just nicely. I just need to be sure that functionality remains the same and that the resulting module can be extended easily.

slogsdon commented 9 years ago

Consider this closed as of #66