Crystal: Missing hash key: "ex" (KeyError)

Created on 15 Jul 2019  路  4Comments  路  Source: crystal-lang/crystal

Missing hash key: "ex" (KeyError)
  from Hash(String, Crystal::CodeGenVisitor::LLVMVar)+@Hash(K, V)#[]<String>:Crystal::CodeGenVisitor::LLVMVar
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#codegen_fun<String, Crystal::Def+, Crystal::Type+, Bool, Crystal::CodeGenVisitor::ModuleInfo, Bool, Bool>:LLVM::Function
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#codegen_fun<String, Crystal::Def+, Crystal::Type+, Bool, Crystal::CodeGenVisitor::ModuleInfo, Bool, Bool>:LLVM::Function
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::Compiler#codegen<Crystal::Program, Crystal::ASTNode+, Array(Crystal::Compiler::Source), String>:(Tuple(Array(Crystal::Compiler::CompilationUnit), Array(String)) | Nil)
  from Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result
  from Crystal::Command#run_command<Bool>:Nil
  from Crystal::Command#run:(Bool | Crystal::Compiler::Result | Nil)
  from main
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues
# TODO: Write documentation for `Dwoom::Account::Backend::User`
require "kemal"
require "crest"
require "clear"
require "./models/users.cr"
require "./models/phone_confirmations.cr"
require "./models/email_confirmations.cr"
require "./locales"

module Dwoom::Account::Backend::User
  extend self
  VERSION = "0.1.0"

  Clear::SQL.init("default", "postgres://**********")
  Clear::SQL.add_connection("read-only", "postgres://**********")

  SESSION_MICROSERVICE_URL = "http://0.0.0.0:3000"
  EMAIL_MICROSERVICE_URL   = "http://0.0.0.0:3002"
  SMS_MICROSERVICE_URL     = "http://0.0.0.0:3001"

  post "/user/get/informations/for/account/page/generalinformations" do |env|
    begin
      response = Crest.post("#{SESSION_MICROSERVICE_URL}/session/get/user_id",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    user_id = JSON.parse(response.body)["user_id"]
    begin
      user = Clear::SQL.select.use_connection("read-only").from("users").where({id: user_id}).first.as(Hash)
    rescue
      halt env, status_code: 500, response: "ERR #DABU-01."
    end
    env.response.content_type = "application/json"
    {"username"     => user["username"],
     "email"        => user["email"],
     "first_name"   => user["first_name"],
     "last_name"    => user["last_name"],
     "dob"          => user["dob"],
     "sexe"         => user["sexe"],
     "country"      => user["country"],
     "language"     => user["language"],
     "phone_number" => user["phone_number"],
     "accept_news"  => user["accept_news"],
    }.to_json
  end

  options "/user/get/informations/for/account/page/generalinformations" do |env|
  end

  post "/user/change/informations/from/account/page/generalinformations" do |env|
    begin
      response = Crest.post("#{SESSION_MICROSERVICE_URL}/session/get/user_id",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    begin
      email = env.params.json["email"].to_s
      username = env.params.json["username"].to_s
      firstname = env.params.json["firstname"].to_s
      lastname = env.params.json["lastname"].to_s
      dob = env.params.json["dob"].as(Array)
      sexe = env.params.json["sexe"].to_s
      country = env.params.json["country"].to_s
      language = env.params.json["language"].to_s
      phonenumber = env.params.json["phonenumber"].to_s
      acceptnews = env.params.json["acceptnews"].as(Bool)
    rescue
      halt env, status_code: 400, response: "Missing parameter(s)."
    end
    user_id = JSON.parse(response.body)["user_id"]
    begin
      user = ::User.query.find! { id == user_id }
    rescue
      halt env, status_code: 500, response: "ERR #DABU-01."
    end
    begin
      year = dob[2].as_i
      month = dob[1].as_i
      day = dob[0].as_i
      puts year
      puts month
      puts day
    rescue
      halt env, status_code: 400, response: "Missing date."
    end

    user.email = email
    user.username = username
    user.first_name = firstname
    user.last_name = lastname
    user.dob = Time.new(day: day, month: month, year: year)
    user.sexe = sexe
    user.country = country
    user.language = language
    user.phone_number = phonenumber
    user.accept_news = acceptnews

    begin
      user.save!
    rescue
      halt env, status_code: 500, response: "ERR #DABU-02."
    end
  end

  options "/user/change/informations/from/account/page/generalinformations" do |env|
  end

  post "/user/send/email/from/account/page/generalinformations/as/confirm_mail" do |env|
    begin
      Crest.post("#{SESSION_MICROSERVICE_URL}/session/verify",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    begin
      email = env.params.json["email"].to_s
      language = env.params.json["language"].to_s
    rescue
      halt env, status_code: 400, response: "Missing parameter(s)."
    end

    confirmation_code = "#{Random.rand(999)} #{Random.rand(999)} #{Random.rand(999)}"
    confirmation_code_db = confirmation_code.gsub(" ", "")

    email_confirmation = EmailConfirmation.new
    email_confirmation.email = email
    email_confirmation.confirmation_code = confirmation_code_db
    email_confirmation.id = (Random::Secure.hex).as(String)

    begin
      email_confirmation.save!
    rescue
      halt env, status_code: 500, response: "ERR #DABU-03."
    end

    begin
      Crest.post("#{EMAIL_MICROSERVICE_URL}/send/user/email_change_confirmation",
        headers: {"Content-Type" => "application/json"},
        form: {
          "to"                => email,
          "language"          => language,
          "confirmation_code" => confirmation_code,
        }.to_json
      )
    rescue
      halt env, status_code: 500, response: "Couldn't send the email."
    end

    env.response.content_type = "application/json"
    {"email_confirmation_id": email_confirmation.id}.to_json
  end

  options "/user/send/email/from/account/page/generalinformations/as/confirm_mail" do |env|
  end

  post "/user/send/phone/from/account/page/generalinformations/as/confirm_phone" do |env|
    begin
      Crest.post("#{SESSION_MICROSERVICE_URL}/session/verify",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    post "/signup/phone/send" do |env|
      begin
        number = env.params.json["phonenumber"].to_s
        language = env.params.json["language"].to_s
      rescue
        halt env, status_code: 400, response: "Missing parameter."
      end

      phone_confirmation = PhoneConfirmation.new
      phone_confirmation.phone_number = number
      phone_confirmation.confirmation_code = Random.rand(999999)
      phone_confirmation.id = (Random::Secure.hex).as(String)

      begin
        phone_confirmation.save!
      rescue ex
        halt env, status_code: 500, response: "ERR #DABA-03."
      end

      begin
        body = translate("sms.new_phone.confirmation_code", language, phone_confirmation.confirmation_code)
      rescue
        halt env, status_code: 500, response: "ERR #DABA-04."
      end

      begin
        Crest.post("#{SMS_MICROSERVICE_URL}/send",
          headers: {"Content-Type" => "application/json"},
          form: {
            "to"   => number,
            "body" => body,
          }.to_json
        )
      rescue
        halt env, status_code: 500, response: "Couldn't send the SMS."
      end
      env.response.content_type = "application/json"
      {"phone_confirmation_id": phone_confirmation.id}.to_json
    end
  end

  options "/user/send/phone/from/account/page/generalinformations/as/confirm_phone" do |env|
  end

  post "/user/confirm/new_email" do |env|
    begin
      response = Crest.post("#{SESSION_MICROSERVICE_URL}/session/get/user_id",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    begin
      confirmation_email_id = env.params.json["confirmation_email_id"].to_s
      confirmation_email_confirmation_code = env.params.json["confirmation_email_confirmation_code"].to_s
    rescue
      halt env, status_code: 400, response: "Missing parameter(s)."
    end
    confirmation_email_confirmation_code = confirmation_email_confirmation_code.gsub(" ", "")
    if !Clear::SQL.select.use_connection("read-only").from("email_confirmations").fetch { |u| exist = (u["id"] == confirmation_email_id) && (u["confirmation_code"] == confirmation_email_confirmation_code) }
      halt env, status_code: 401, response: "Wrong confirmation code."
    end
  end

  options "/user/confirm/new_email" do |env|
  end

  post "/user/confirm/new_phone" do |env|
    begin
      response = Crest.post("#{SESSION_MICROSERVICE_URL}/session/get/user_id",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    begin
      id = env.params.json["id"].to_s
      confirmation_code = env.params.json["confirmation_code"].to_s
    rescue
      halt env, status_code: 400, response: "Missing parameters."
    end

    if !Clear::SQL.select.use_connection("read-only").from("phone_confirmations").fetch { |u| exist = (u["id"] == id) && (u["confirmation_code"] == confirmation_code) }
      halt env, status_code: 401, response: "Wrong confirmation code."
    end
  end

  options "/user/confirm/new_phone" do |env|
  end

  before_all do |env|
    begin
      origin = env.request.headers["origin"]
    rescue
      halt env, status_code: 400, response: "Missing origin."
    end
    env.response.headers["Access-Control-Allow-Methods"] = "HEAD,GET,PUT,POST,DELETE,OPTIONS"
    env.response.headers["Access-Control-Allow-Headers"] = "Content-Type, Accept, Origin, Authorization, X-Requested-With, X-HTTP-Method-Override"
    env.response.headers["Access-Control-Allow-Credentials"] = "true"
    case origin
    when "http://dev.dwoom"
      env.response.headers["Access-Control-Allow-Origin"] = "http://dev.dwoom"
    when "https://account.dwoom.com"
      env.response.headers["Access-Control-Allow-Origin"] = "https://account.dwoom.com"
    else
      halt env, status_code: 401, response: "Prohibited origin"
    end
  end

  Kemal.config.env = "development" # use "production" for production.
  Kemal.config.port = 3006
  Kemal.config.powered_by_header = false
  Kemal.run
end

bug compiler

Most helpful comment

well, you shouldn't get this kind of errors when you forget an end, it is worth investigating I think

All 4 comments

Wasn't a bug, I forgot an "end".
But as the compiler told me Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

I didn't check further.

well, you shouldn't get this kind of errors when you forget an end, it is worth investigating I think

The issue involved this code

post "/user/send/phone/from/account/page/generalinformations/as/confirm_phone" do |env|
    begin
      Crest.post("#{SESSION_MICROSERVICE_URL}/session/verify",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
    post "/signup/phone/send" do |env|
      begin
        number = env.params.json["phonenumber"].to_s
        language = env.params.json["language"].to_s
      rescue
        halt env, status_code: 400, response: "Missing parameter."
      end

      phone_confirmation = PhoneConfirmation.new
      phone_confirmation.phone_number = number
      phone_confirmation.confirmation_code = Random.rand(999999)
      phone_confirmation.id = (Random::Secure.hex).as(String)

      begin
        phone_confirmation.save!
      rescue ex
        halt env, status_code: 500, response: "ERR #DABA-03."
      end

      begin
        body = translate("sms.new_phone.confirmation_code", language, phone_confirmation.confirmation_code)
      rescue
        halt env, status_code: 500, response: "ERR #DABA-04."
      end

      begin
        Crest.post("#{SMS_MICROSERVICE_URL}/send",
          headers: {"Content-Type" => "application/json"},
          form: {
            "to"   => number,
            "body" => body,
          }.to_json
        )
      rescue
        halt env, status_code: 500, response: "Couldn't send the SMS."
      end
      env.response.content_type = "application/json"
      {"phone_confirmation_id": phone_confirmation.id}.to_json
    end
  end

I created a route within another route because I forgot an end.

post "/user/send/phone/from/account/page/generalinformations/as/confirm_phone" do |env|
    begin
      Crest.post("#{SESSION_MICROSERVICE_URL}/session/verify",
        headers: {"origin" => env.request.headers["origin"]},
        cookies: {"Session" => env.request.cookies["Session"].value}
      )
    rescue ex : Crest::RequestFailed
      halt env, status_code: 401, response: "Unauthorized."
    end
#forgot an end here
post "/signup/phone/send" do |env|

And the end that was supposed to close the first route was at the bottom.

      env.response.content_type = "application/json"
      {"phone_confirmation_id": phone_confirmation.id}.to_json
    end
  end #here

Can somebody come up with a self contained example? Otherwise I'd suggest we close this for now and let it resurface if still an issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

asterite picture asterite  路  3Comments

will picture will  路  3Comments

nabeelomer picture nabeelomer  路  3Comments

pbrusco picture pbrusco  路  3Comments

asterite picture asterite  路  3Comments