I have a Rails 7 app. One of my controller actions (logout action), redirects the user to the root_url.
For some reason, upon redirect, I see following error on Chrome's console and the one button (login button) on that page stops working.
turbo.es2017-esm.js:2407 An import map is added after module script load was triggered.
If I expand the error, following is the stack trace:
turbo.es2017-esm.js:2407 An import map is added after module script load was triggered.
assignNewBody # turbo.es2017-esm.js:2407
(anonymous) # turbo.es2017-esm.js:2369
preservingPermanentElements # turbo.es2017-esm.js:961
preservingPermanentElements # turbo.es2017-esm.js:1039
replaceBody # turbo.es2017-esm.js:2367
render # turbo.es2017-esm.js:2342
renderSnapshot # turbo.es2017-esm.js:892
render # turbo.es2017-esm.js:862
renderPage # turbo.es2017-esm.js:2483
(anonymous) # turbo.es2017-esm.js:1517
render # turbo.es2017-esm.js:1682
await in render (async)
loadResponse # turbo.es2017-esm.js:1512
visitRequestCompleted # turbo.es2017-esm.js:1724
recordResponse # turbo.es2017-esm.js:1498
simulateRequest # turbo.es2017-esm.js:1485
issueRequest # turbo.es2017-esm.js:1475
visitStarted # turbo.es2017-esm.js:1710
start # turbo.es2017-esm.js:1436
startVisit # turbo.es2017-esm.js:2055
visitProposedToLocation # turbo.es2017-esm.js:1706
visitProposedToLocation # turbo.es2017-esm.js:2638
proposeVisit # turbo.es2017-esm.js:2045
formSubmissionSucceededWithResponse # turbo.es2017-esm.js:2096
await in formSubmissionSucceededWithResponse (async)
requestSucceededWithResponse # turbo.es2017-esm.js:685
receive # turbo.es2017-esm.js:450
perform # turbo.es2017-esm.js:431
await in perform (async)
start # turbo.es2017-esm.js:644
submitForm # turbo.es2017-esm.js:2060
formSubmitted # turbo.es2017-esm.js:2662
Q.submitBubbled # turbo.es2017-esm.js:1826
document.body.replaceWith(this.newElement); is the line of code where the error happened:
assignNewBody() {
if (document.body && this.newElement instanceof HTMLBodyElement) {
document.body.replaceWith(this.newElement);
}
else {
document.documentElement.appendChild(this.newElement);
}
}
Controller action:
def destroy
log_out
respond_to do |format|
format.html {redirect_to root_url, status: 303}
format.json {render json: {} }
end
end
If I refresh the page, the error goes away and the button starts working again.
This error can happen if you are accidentally including the import map (<%= javascript_importmap_tags %>) twice in your page.
I had following line of code in my application.html.erb which subscribed to updates to the user model:
<%= turbo_stream_from current_user, "counter" %>
I wrapped this under the condition that current_user is not nil (current_user is nil after logout action):
<% if logged_in? %>
<%= turbo_stream_from current_user, "counter" %>
<% end %>
Now the error is gone and the login button does not break.
I still don't quite understand the root cause.
Related
I need to render an html code I receive from an API.
In Rails 6 : I was doing this in my controller, and it was working fine. I called the webservice I received the response, and I was redirected to the code generated by the render. Fine !
class GatewayController < ApplicationController
def new
init_gateway_call
end
def create
call_gateway
render_gateway_response
end
private
...
def render_gateway_response
render(html: #gateway_response.message.html_safe)
end
end
new.html.erb :
<%= form_with url: gateway_path, local: true do |f| %>
...
<% end %>
And no : create.html.erb
** Rails 7 **
I call the webservice. I get the answer but my page idle and I get this error.
Error: Form responses must redirect to another location at FormSubmission.requestSucceededWithResponse (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1614)
at FetchRequest.receive (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1390)
at FetchRequest.perform (application-0f0c10fb8f5683e32fc53a93a8a323c328de61682ca16fb65a6a2b8a3ba5d087.js:1374)
So far, I tried:
# GatewayController
respond_to :create, format: :html, gateway_response: #gateway_response.message.html_safe
<%= gateway_response %>
Without success ... Do you have any idea? Otherwise it is going to be a long weekend ^^
I figured it out you while posting my question. The error message seems like a Turbo error. I had to had data-turbo false to my form.
<%= form_with url: gateway_path, local: true, data: { turbo: false } do |f| %>
...
<% end %>
And keep my controller like it was.
render(html: #gateway_response.message.html_safe)
Happy upgrade anyone
Setting data: {turbo: false} will cause the page to reload entirely. This takes away the entire point of turbo which is to reduce page reloads.
The reason the error occurs is because Turbo expects a 303 redirect response. The solution is to have the server respond with 422 or 500 status code when you are not redirecting.
if save
redirect_to root_path
else
render :new, status: 422
You can read about this here: https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission
Of course, if you want the page to reload, you can use data-turbo: false
Thanks! I'm also developing on Rails 7 and data: { turbo: false } fixed my issue.
Instead of using turbo: false as suggested on the answer you need to add appropriate status like :see_other for redirects and 422 (unprocessible_entity) in case render.
render :new, status: 422
redirect_to xyz_path, status: :see_other
I have been using Google Identity Toolkit (for web) on my site for more than 2 years. Recently I found that the password reset flow is broken. When I try to "Forgot Password", check the recaptcha checkbox and click Continue, I get an error "Request failed. Please try again."
In the console I see this:
[ 28.949s] [identitytoolkit] Error: Invalid JSON string: Password reset email sent successfully.
Gj # gitkit.js:254
Ej.addLogRecord # gitkit.js:254
Zi.log # gitkit.js:237
R # gitkit.js:254
(anonymous) # gitkit.js:255
Yc # gitkit.js:44
g.dispatchEvent # gitkit.js:42
tj # gitkit.js:247
lj.onReadyStateChangeEntryPoint_ # gitkit.js:245
lj.onReadyStateChange_ # gitkit.js:245
XMLHttpRequest.send (async)
lj.send # gitkit.js:242
Mj # gitkit.js:255
Lj.requestRpEndpoint # gitkit.js:256
g.requestRpEndpoint # gitkit.js:259
(anonymous) # gitkit.js:4
N # gitkit.js:190
Fh # gitkit.js:190
Sm # gitkit.js:334
(anonymous) # gitkit.js:335
(anonymous) # gitkit.js:80
(anonymous) # gitkit.js:77
Yc # gitkit.js:44
g.dispatchEvent # gitkit.js:42
fd # gitkit.js:47
ed.handleClick_ # gitkit.js:47
Uc # gitkit.js:39
Rc # gitkit.js:41
Pc.b # gitkit.js:37
Even though the error says "email sent successfully", it's not sent. I do not know how long it has been broken for. I only found it yesterday.
I'm using this script:
https://www.gstatic.com/authtoolkit/js/gitkit.js on my web site.
I hope someone from the Gooogle Identity Toolkit team can help on this.
UPDATE 1:
Server side code:
OobResponse oobResponse = gitkitClient.getOobResponse(request);
OobAction oobAction = oobResponse.getOobAction();
// For DEBUG
logger.info("oobAction : " + oobAction);
String action = request.getParameter("action");
logger.info("action : " + action); // returns null
logger.info("response: " + request.getParameter("response")); // returns a long string
logger.info("responseBody : " + oobResponse.getResponseBody()); // returns {"error": "CAPTCHA_CHECK_FAILED" }
logger.info("email : " + oobResponse.getEmail()); // returns null
// If reset password
if (OobAction.RESET_PASSWORD.equals(oobAction)) {
Optional<String> forgotPasswordLinkOpt = oobResponse.getOobUrl();
String passwordResetLink = forgotPasswordLinkOpt.get();
sendMailService.sendPasswordResetEmail(oobResponse.getEmail(), passwordResetLink);
return(oobResponse.getResponseBody());
}
The oobAction is coming out to be null and therefore the link is not being sent. But action has a value of resetPassword. 'responseBody' is returning
{"error": "CAPTCHA_CHECK_FAILED" }. Do I need to do some configuration for the recaptcha string at my end?
I'm using v1.2.7 of gitkitclient from the Maven repo:
https://mvnrepository.com/artifact/com.google.identitytoolkit/gitkitclient
The issue was fixed by the Google team on the backend without any change from my end. See comments on the original issue for details.
I would like to add devise confirmable functionality to web service, I would like to know steps to integrate it, code in registration_controller.rb :-
class Api::RegistrationsController < Devise::RegistrationsController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
user = User.new(user_params)
if user.save
render(
json: Jbuilder.encode do |j|
j.sucess true
j.count 1
j.type "userObject"
j.message "signed up successfully."
j.data user, :email, :role, :authentication_token, :activation_state
end,
status: 201
)
return
else
warden.custom_failure!
render :json=> user.errors, :status=>422
end
end
protected
def user_params
params.require(:user).permit!
#params[:user].permit(:email, :password, :password_confirmation)
end
end
I have seen a strange exception in the onData() function of a Route Controller in iron-router. The exception only seems to occur after I make a change to a file which of course causes meteor to restart the app. I've put up a sample in github that demonstrates the problem here: https://github.com/benmonro/iron-router-bug
If you add a person by clicking submit, then click on that person's name, everything will load fine. However, if you then make a change to some js (say add a comment). Meteor will reload and you'll get the exception in the 'onData()' method which is attempting to use a property of the data returned from the 'data()' function.
The exception is here:
> Exception in defer callback: TypeError: Cannot read property 'name' of
> undefined
> at RouteController.extend.onData (http://localhost:3000/irDataBug.js?8327f0bf1bedee2437ec14bc4509d8f7e85079ab:33:19)
> at RouteController.runHooks (http://localhost:3000/packages/iron-router.js?e9fac8016598ea034d4f30de5f0d356a9a24b6c5:827:16)
> at http://localhost:3000/packages/iron-router.js?e9fac8016598ea034d4f30de5f0d356a9a24b6c5:2137:16
> at Utils.extend._run.withNoStopsAllowed (http://localhost:3000/packages/iron-router.js?e9fac8016598ea034d4f30de5f0d356a9a24b6c5:2098:21)
> at _assign._compute (http://localhost:3000/packages/deps.js?4a82362ae66e863a1c1a8b0a5fec6f665e2038d1:228:38)
> at new Deps.Computation (http://localhost:3000/packages/deps.js?4a82362ae66e863a1c1a8b0a5fec6f665e2038d1:160:10)
> at Object._assign.autorun (http://localhost:3000/packages/deps.js?4a82362ae66e863a1c1a8b0a5fec6f665e2038d1:380:13)
> at http://localhost:3000/packages/iron-router.js?e9fac8016598ea034d4f30de5f0d356a9a24b6c5:2134:12
> at Utils.extend._run.withNoStopsAllowed (http://localhost:3000/packages/iron-router.js?e9fac8016598ea034d4f30de5f0d356a9a24b6c5:2098:21)
> at _assign._compute (http://localhost:3000/packages/deps.js?4a82362ae66e863a1c1a8b0a5fec6f665e2038d1:228:38)
The data isn't ready after the reload so you need to add a guard or an early return to the callback. Here's a simple fix:
onData: function() {
var thePerson = Router.current().data();
if (!thePerson)
return;
if (thePerson.name === "Fred") {
console.log("it's fred");
} else {
console.log("it's not fred");
}
}
Because the callback is reactive, it will rerun once thePerson is found. Alternative solutions could involve a waitOn callback and then checking for this.ready().
I have a updatepanel that is updated using timer every one second.
I also have async postback error handler set up in javascript as following:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onEndRequest);
function onEndRequest(sender, args) {
var error = args.get_error();
if (error != null) {
args.set_errorHandled(true);
alert(error.message);
}
}
when I refresh the page manually or click a hyperlink I get the following error in endRequest handler:
An unknown error occurred while processing the request on the server.
The status code returned from the server was: 0
How can i prevent this behavior?
Thanks
I figured it out.
For thoue who have the same problem, here is the code to determine if script manager async postback is currently running:
Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack()
to cancel it call:
Sys.WebForms.PageRequestManager.getInstance().abortPostBack();
I just call the cancel method directly. It does not not anything when request is not running.