Git Product home page Git Product logo

amethyst's Introduction

Amethyst-logo

โš ๏ธ Amethyst is currently undergoing a re-write from the ground up. We'll be releasing the public roadmap soon.

Amethyst is a web framework written in the Crystal language. The goals of Amethyst are to be extremely fast and to provide agility in application development, much like Rails.

Latest version - 0.1.7 Note that Amethyst is at its early stages, so it lacks for whole bunch of things. But you can give a hand with contributing.

For detailed information, see docs on our wiki below:

Here are some benchmarking results

For now, next things are implemented:

  • class-based controllers with method-based actions
  • views for actions (*.ecr)
  • filters for action
  • middleware support
  • simple REST routing
  • default routes for controller
  • path, GET and POST params inside actions
  • basic cookies support
  • static files serving
  • http logger and timer for developers
  • simple environments support
  • simple session support

Example

Here is classic 'Hello World' in Amethyst

require "crystal-on-rails/amethyst"

class WorldController < Base::Controller
  actions :hello

  view "hello", "#{__DIR__}/views"
  def hello
    @name = "World"
    respond_to do |format|
      format.html { render "hello" }
    end
  end
end

class HelloWorldApp < Base::App
  routes.draw do
    all "/",      "world#hello"
    get "/hello", "world#hello"
    register WorldController
  end
end

app = Amethyst.new HelloWorldApp
app.serve

# /views/hello.ecr
Hello, <%= name %>

Start your application:

crystal deps
crystal build src/hello.cr

Go to http://localhost:8080/.

Development

Feel free to fork project and make pull-requests.

Contributing

I would be glad for any help with contributing.

  1. Fork it ( https://github.com/amethyst-framework/amethyst/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

amethyst's People

Contributors

artintal avatar cocuh avatar codcore avatar davydovanton avatar gitter-badger avatar jeffbdavenport avatar jhass avatar kenta-s avatar mkozjak avatar paa001 avatar sn avatar thomasnal avatar veelenga avatar widdershin avatar yamadayuki avatar zamith avatar

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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

amethyst's Issues

Default routes don't work if controller is situated inside a module

module My::Webapp
  class LoginController < Base::Controller
    actions :index

    view "login", "#{__DIR__}/views"
    def index
      respond_to do |format|
        format.html { render "login"}
      end
    end
end

Will get ERROR: Missing hash value: "LoginController" when trying to GET /login/index

Examples not working

I am very new to Crystal and I tried to run the example project stated in the documentation. It seems that their are out of date. I think it they should be removed from the readme.

What does the future of this project look like?

I'd like to use this project because it seems to have one of more advanced ORMs for crystal but it looks sort of abandoned. Also I'm having issues getting it to compile with newer versions of crystal. Any suggestions?

Daemonizing\Forking

We need to add some option to "run in the background".

we can use fork

fork do
  app.serve
end

or some internal design to this this thing.

Http::Response.build passing nil status code to HTTP::Response.new

Here the status code is allowed to be nil, causing the compiler to complain:

in ./libs/amethyst/amethyst/base/handler.cr:12: instantiating 'Amethyst::Http::Response#build()'
        response.build
                 ^~~~~
in ./libs/amethyst/amethyst/http/response.cr:23: instantiating 'HTTP::Response:Class#new((Nil | Int32), String, HTTP::Headers)'
        return HTTP::Response.new(@status, @body, headers = @headers)
                              ^~~
instantiating 'HTTP::Response#initialize((Nil | Int32), String, HTTP::Headers, Nil, String, Nil)'
in /Users/giorgio/Documents/crystal/src/http/response.cr:14: instantiating 'HTTP::Response:Class#mandatory_body?((Nil | Int32))'
    if Response.mandatory_body?(@status_code)
                ^~~~~~~~~~~~~~~
in /Users/giorgio/Documents/crystal/src/http/response.cr:77: undefined method '/' for Nil (compile-time type is (Nil | Int32))
    !(status_code / 100 == 1 || status_code == 204 || status_code == 304)

Either Http::Response.new should not allow a nil status code, or Http::Response.build should check for that and use a "default" one.

SSL Support

Right now, the best OpenSSL lib is @datanoise repo at https://github.com/datanoise/openssl.cr .
Crystals SSL binding are half finished until this will be PRed.

I know Amethyst is using Crystal's HTTP server, the question is what kind of SSL support does the server has ? maybe we should wait for openssl.cr to be merged before adding an SSL option ?

Anyway, SSL can be implemented in a few ways.

  1. As part of HTTP::Server, then you just need to allow the user to specify :ssl = true or something in the .serve method.

  2. You can bypass HTTP::Server and allow the user to pass down a SSLSocket for you to use (this means the user will need to get from you a TCPSocket and upgrade it using OpenSSL::Context etc...

  3. You can implement some kind of Middleware to handle the SSLSocket upgrade.

From those three, I guess 1 is the easiest, but not sure when this is going to happen, this also depends on a) @datanoise, b) @asterite, then you :)

Error when accessing an action that is not defined in a controler

Should respond with a 404

Now getting:

ERROR: Action '' not found in controller 'LoginController'

*Amethyst::Exceptions::ControllerException@Exception#initialize<Amethyst::Exceptions::ControllerActionNotFound, String>:Array(String) +46 [0]
*Amethyst::Exceptions::ControllerActionNotFound#initialize<Amethyst::Exceptions::ControllerActionNotFound, String, String>:Array(String) +130 [0]
*Amethyst::Exceptions::ControllerActionNotFound::new<String, String>:Amethyst::Exceptions::ControllerActionNotFound +102 [0]
*LoginController@Amethyst::Base::Controller#call_action<LoginController, String>:Amethyst::Http::Response +52 [0]
*Amethyst::Dispatch::Router#process_default_route<Amethyst::Dispatch::Router, Amethyst::Http::Request, Amethyst::Http::Response>:Amethyst::Http::Response +472 [0]
*Amethyst::Dispatch::Router#call<Amethyst::Dispatch::Router, Amethyst::Http::Request>:Amethyst::Http::Response +149 [0]
*Amethyst::Middleware::Static#call<Amethyst::Middleware::Static, Amethyst::Http::Request>:Amethyst::Http::Response +219 [0]
*Amethyst::Middleware::TimeLogger#call<Amethyst::Middleware::TimeLogger, Amethyst::Http::Request>:Amethyst::Http::Response +466 [0]
*Amethyst::Middleware::HttpLogger#call<Amethyst::Middleware::HttpLogger, Amethyst::Http::Request>:Amethyst::Http::Response +530 [0]
*Amethyst::Middleware::ShowExceptions#call<Amethyst::Middleware::ShowExceptions, Amethyst::Http::Request>:Amethyst::Http::Response +394 [0]
*Amethyst::Base::Handler#call<Amethyst::Base::Handler, HTTP::Request>:HTTP::Response +227 [0]
*HTTP::Server#handle_client<HTTP::Server, TCPSocket+>:Nil +266 [0]
~fun_literal_20 +29 [0]
*Fiber#run<Fiber>:(Nil | Void) +256 [0]
~fun_literal_3 +17 [0]
co_exit +75 [0]
__start_context +0 [0]

Support Crystal 0.7.7

Several breaking changes in 0.7.7

Cannot require inside modules or classes anymore.

before_action not calling method

So, I'm probably doing something wrong, but I have a before_action :authorize in my controller and it doesn't seem to call the def authorize method.

I see the macros defined in the controllers for before_action. Any idea's?

Can't use an array as a view variable

Though the actual error might be "can't run methods on objects in templates".

# Controller
class MyController < Base::Controller
  actions :index

  view "index", "#{__DIR__}/../views/ragas"
  def index
    @array = [1,2,3]

    render "index"
  end
end

# index.ecr
<%= array.length %>

Error:

Error: instance variable '@array' of MyController was not initialized in all of the 'initialize' methods, rendering it nilable

Though if I just have <%= array %> in the view that compiles and renders just fine...

What's up?

Return of repository to the creator

Hi to all members of crystal-community! I am an creator of Amethyst framework, and I passed it to crystal-community in hope that here this project will be develop. But, as I see there are no changes to the project and it seems dead. I I demand to return it to my hands, I have people that want to take care of this project.

README example doesn't work out of the box

Hi!

First of all, I'm really liking your web framework! I just tried it (with a small fix) and it looks nice. It looks compact to write and has some things that made me stop and think "wait, how did he do that?".

I tried the example from the README and doing require "amethyst" didn't work, it can't find the view macro. Doing require "amethyst/all" did work, though, but that's not what the example says.

issues with before_action

Right now I got this configuration inside a Controller class:

  before_action :authorized?, only: [:r_start, :r_stop, :z_start, :z_stop, :new, :new_rule, :list_rules]

This should call

def authorized?
    puts "Checking User"
    if $cookie_jar.includes?(request.cookies[".rsa"])
      puts "Sending OK"
      response.set(200, "OK")
    else
      puts "Sending Forbidden"
      response.set(403, "Forbidden")
      html "<p>Page cannot be accessed by unauthenticated users</p>"
    end
  end

Now, running the application I can see that the string "Sending Forbidden" is being reached:

[Amethyst 0.1.3] serving application "rsaccess-web" at http://127.0.0.1:8080
Checking User
Sending Forbidden
Checking User
Sending Forbidden

But, the user is getting to the method behind without receiving the correct response

      response.set(403, "Forbidden")
      html "<p>Page cannot be accessed by unauthenticated users</p>"

Routing problem when controllers are included in a module

in this case:

module SomeModule
   class DictController < Base::Controller
     ...
   end
end


include SomeModule

...
get "/dict_index", "dict#index"   =>  Route.new("dict_index", "DictController",  "index")
register DictController  =>         @controllers_instances["SomeModule::DictController"] = SomeModule::DictController
...

When process named route, the "controller key" can't match

Still active?

Seems like it's been a little while....just wanted to see if this project is still active.

actions names containing an underscore result in partial calls

example:

actions :r_stop

will result in an action named "r" without the _stop.

ERROR: Action 'r' not found in controller 'LoginController'

*LoginController@Amethyst::Base::Controller#call_action<LoginController, String>:Amethyst::Http::Response +753 [0]
*Amethyst::Dispatch::Router#call<Amethyst::Dispatch::Router, Amethyst::Http::Request>:Amethyst::Http::Response +1335 [0]
*Amethyst::Middleware::TimeLogger#call<Amethyst::Middleware::TimeLogger, Amethyst::Http::Request>:Amethyst::Http::Response +5552 [0]
*Amethyst::Middleware::HttpLogger#call<Amethyst::Middleware::HttpLogger, Amethyst::Http::Request>:Amethyst::Http::Response +5561 [0]
*Amethyst::Middleware::ShowExceptions#call<Amethyst::Middleware::ShowExceptions, Amethyst::Http::Request>:Amethyst::Http::Response +40 [0]
~fun_literal_20 +3704 [0]
~fun_literal_3 +33 [0]
co_exit +75 [0]
__start_context +0 [0]

working:

actions :rstop

works as intended

Routing for each method

Something like this makes sense to me, but apparently isn't working as I expect (as in allowing only the first method for each vir dir)

routes.draw do
      get "/",       "login#new"
      post "/",      "login#create"
      get "/login",  "login#new"
      post "/login", "login#create"
      register LoginController
end

Is this a bug or this is how it suppose to behave ?

Unable to donate to this project :sadpanda:

pledgie returns this error, when trying to donate using PayPal:

The email account Receiver not in receive money enabled country is based in a country that isn't enabled to receive payments

Remove default an argumet from initialize method in App class

The initialize method in Amethyst::Base::App receive two default arguments:

def initialize(app_path= __FILE__, app_type={{@type.name.stringify}})

Here, app_path initialize by "?" because FILE is "?" in default argument of initialize method.
For Example:

class A
  def initialize(@file : String =__FILE__) 
    puts @file
  end
  
  def get(@file=__FILE__) 
    puts @file
  end
end

a = A.new  # => "?"
a.get      # => file_path

So, "initialize should set app name" in spec/base/application_spec.cr is failing.

spec/base/application_spec.cr:

app = Base::App.new

it "should set app name" do
  app.name.should eq "application_spec"  # app.name => "?"
end

One way to solve it is to remove a default argument of app_path.

Control over logging

We need to have more control over logging:

  1. Control of output IO (file, STDOUT, STDERR, etc..)
  2. Control over format (clear text, Logger, etc..)
  3. Control via levels, warn, error, fatal etc ..

Error with cookies

I'm doing this check:

key = "cookey"
value = Base64.urlsafe_encode64(SecureRandom.random_bytes(128))
unless request.cookies.has_keys? [:cookie]
  response.cookie(key, value, secure=false)
end

And in the client I get this:

ERROR: Missing hash value: "Cookie"

*HTTP::Headers#[]<HTTP::Headers, String>:String +724 [0]
*LoginController#show<LoginController>:String +447 [0]
*LoginController@Amethyst::Base::Controller#call_action<LoginController, String>:Amethyst::Http::Response +62 [0]
*Amethyst::Dispatch::Router#call<Amethyst::Dispatch::Router, Amethyst::Http::Request>:Amethyst::Http::Response +1778 [0]
*Amethyst::Middleware::TimeLogger#call<Amethyst::Middleware::TimeLogger, Amethyst::Http::Request>:Amethyst::Http::Response +5552 [0]
*Amethyst::Middleware::HttpLogger#call<Amethyst::Middleware::HttpLogger, Amethyst::Http::Request>:Amethyst::Http::Response +5593 [0]
*Amethyst::Middleware::ShowExceptions#call<Amethyst::Middleware::ShowExceptions, Amethyst::Http::Request>:Amethyst::Http::Response +40 [0]
~fun_literal_20 +3884 [0]
~fun_literal_3 +33 [0]
co_exit +75 [0]
__start_context +0 [0]

Examples not working

Using Crystal 0.7.3

Cloning the repo and trying to run examples with

crystal run examples/simple_application.cr

Gives the error

Error in ./examples/simple_application.cr:6: while requiring "../src/amethyst"

require "../src/amethyst"
^

in ./src/amethyst.cr:1: while requiring "./amethyst/base"

require "./amethyst/base"
^

in ./src/amethyst/base/base.cr:8: while requiring "../middleware"

require "../middleware"
^

in ./src/amethyst/middleware/middleware.cr:2: while requiring "mime": can't find file 'mime' relative to '/Users/serdardogruyol/playground/Amethyst/src/amethyst/middleware'

require "mime"
^

WebSocket Support

Will WebSocket be implemented in the project or should it be handled in middleware ?

Build status is unknown

This repository is moved to crystal-community, so build status of this repository is unknown.
Please re-register to Travis CI.

New name for Amethyst?

As there are many other projects named "Amethyst", I thought for a new name for my web framework. Feel free to comment your suggestions!

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.