Reputation: 23
I am trying to pass a member's information from my Rails backend to my vanilla JS frontend after a member logs in. This way I will be able to store the member's id to later persist data to the backend for the member's profile (e.g. if the member added a new book to their wishlist).
I am able to authenticate the member and confirm their credentials in the backend, but when I try to send the logged in member info from rails to the JS frontend, I get the following error when I run resp.json() in console.
Failed to execute 'json' on 'Response': body stream already read. Interestingly, I am getting a 'true' response.ok, and status: 201, but am not able to access the member's data.
[[PromiseResult]]: TypeError: Response {type: "cors", url: "http://localhost:3000/login", redirected: false, status: 201, ok: true, …}
[[PromiseState]]: "rejected"
Here's my sessions controller: The create action is the struggle.
class SessionsController < ApplicationController
def create
@member = Member
.find_by(email: session_params[:email])
.try(:authenticate, session_params[:password])
binding.pry
if @member
login!
render json: {
logged_in: true,
member: @member
},
status: :created
else
render json: {
status: 401,
errors: ['No such member', 'Verify credentials and try again or sign up']
}
end
end
def is_logged_in?
if logged_in? && current_member
render json: {
logged_in: true,
member: current_member
}
else
render json: {
logged_in: false,
message: 'no such member'
}
end
end
def destroy
logout!
render json: {
status: 200,
logged_out: true
}
end
def session_params
params.require(:member).permit(:email, :password)
end
end
My application controller:
class ApplicationController < ActionController::Base
skip_before_action :verify_authenticity_token
helper_method :login!, :logged_in?, :authorized_member?, :logout!, #current_member (current_member is currently in controller/concerns)
def login!
session[:member_id] = @member.id
end
def logged_in?
if @current_member
render json: {
logged_in: true,
member: @current_member
}
else
render json: {
logged_in: false
}
end
end
def authorized_member?
@member == current_member
end
end
and my JavaScript fetch request Side bar: I do not believe I need the commented out lines:
async function submitLogin() {
let email = document.getElementById("login-email").value;
let password = document.getElementById("login-password").value;
const memberLogin = { member: { email, password } };
let options = {
method: "POST",
credential: "same-origin",
headers: {
"Content-Type": "application/json",
// "Access-Control-Allow-Origin":
// "file:///Users/awb/Coding/Flatiron/Projects/bookclub-javascript-rails-api/bookclub-frontend-javascript/index.html",
// "Access-Control-Allow-Methods": "POST",
// "Access-Control-Allow-Headers": "Content-Type, Authorization",
Accept: "application/json",
},
body: JSON.stringify(memberLogin),
};
fetch("http://localhost:3000/login", options)
.then((resp) => {
resp.json();
debugger;
})
}
Upvotes: 1
Views: 2504
Reputation: 3251
It's probably javascript fetch - Failed to execute 'json' on 'Response': body stream is locked. Promises can be resolved only once.
Since your function is async, try:
let response = await fetch("localhost:3000/login", options);
let data = await response.json();
Upvotes: 1