Rails 7 redirect error: An import map is added after module script load was triggered - turbolinks

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

Error: Form responses must redirect to another location

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

Google Identity Toolkit - Password Reset flow is broken

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.

Adding devise confirmable module within web api or any other technique for same functionality?

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

Iron Router throwing exception in onData

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().

PageRequestManagerServerErrorException error when I press F5 while updatepanel is updating

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.

Resources