質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.96%

Ruby sinatra sessionが効かない

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 222

score 18

前提・実現したいこと

sinatraで下記のコードのように、ローカルでsinatra.rbを起動し、その後request.rbを実行することで、getリクエストでパラメータを渡してログインしたのち、postリクエストでログイン情報を変更したいと考えております。

sinatra.rbでは、sessionを利用して、ログイン情報変更をしようと思っているのですが、postすると、sessionが切れてしまいます。
具体的に言うと、get "/login"の段階では、session[:id]idが入っているのですが、post "/edit"ではsession[:id]nilになっています。

post "/edit"でもsession[:id]が引き継がれるようにしないのですが、原因と対応策をご教授いただけないでしょうか。

該当のソースコード

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
# request.rb

require_relative "common" #必要なライブラリ群

def get(route, params)
  uri = URI.parse("http://localhost:4567/#{route}#{params}")

  response = Net::HTTP.get_response(uri)

  response.body
end

def post(route, params)
  uri = URI.parse("http://localhost:4567/#{route}")
  request = Net::HTTP::Post.new(uri)
  request.set_form_data(params)

  req_options = {
    use_ssl: uri.scheme == "https",
  }

  response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
    http.request(request)
  end

  response.body
end

get("login", "?id=a&password=a")

post("edit", {id: b, password: b})


#sinatra.rb

require_relative "common" #DB接続設定など
require 'sinatra'
require 'sinatra/reloader'
require 'active_record'

class User < ActiveRecord::Base
end

use Rack::Session::Cookie

get "/login" do
  content_type :json
  id = params['id']
  password = params['password']
  data = {}

  return nil if !User.exists?(user_id: id)
  user = User.find_by(user_id: id)
  if user.password == password
    data["user_id"] = user.user_id
    session[:id] = user.id #ここではidが入力されている
  end
  data.to_json
end

post "/edit" do
  content_type :text
  p session[:id] #loginしてもnilになってしまう
  return nil if session[:id].nil?
  user = User.find(session[:id])
  id = params['id']
  password = params['password']
  user.update(user_id: id)
  user.update(password: password)
  return "done"
end

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • gouf

    2021/01/22 12:51

    「enable :sessions」を追記した場合、何か変化は見られますか? : http://sinatrarb.com/intro-ja.html (「セッションの使用」の欄を参照)

    キャンセル

  • qiyuren

    2021/01/22 13:12

    変化なしでした。

    キャンセル

  • qiyuren

    2021/01/22 13:30

    /edit でp session.inspectすると
    "#<Rack::Session::Abstract::PersistedSecure::SecureSessionHash:0x3febe71866f0 not yet loaded>"
    が帰ってきました。

    キャンセル

回答 1

checkベストアンサー

+1

request.rb の get と post のリクエストがそれぞれ独立しているように見えます。
get のレスポンスヘッダに含まれるクッキーのデータを post で送信する必要があるのでは。

def get(route, params)
  ...
  # response を返す
  response
end

def post(route, params, cookie)
  ...
  # クッキーをセット
  request.add_field("cookie", cookie)
  ...

# responseを受け取る
response = get("login", "?id=a&password=a")
# クッキー
cookie = response.header["set-cookie"]
# クッキーを送信
post("edit", {id: b, password: b}, cookie)


動作確認できていませんが、以上のようなコードになるのではないかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/01/22 21:24

    ありがとうございます。

    こちらのコード実装しましたら、解決しました。

    大変助かりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る