htmx icon indicating copy to clipboard operation
htmx copied to clipboard

HX-Redirect does not work in chrome

Open yxh38658 opened this issue 1 year ago • 5 comments

I have a login.html for the user. If he/she pass the authorization the browser should lead he/she to the home page(home.html). If the username or password is wrong, an hint is sent from the server to the browser and shown on login.html page.

everything looks normal when login failed. But if the authorization sucess, the browser can not be redirect to /home. it's still at /login(from the backend we can see '/dologin' returns sucessfully and '/home' is not executed).

After tried many times, I found it can be corrected by 2 method:

  1. clear brwoser cache before connecting.
  2. Press F12 to open chrome debug window before click "login" button. (I don't understand why it works! But it does work!!!) But I can't ask all of the users to do it. It's ugly.

Anybody had the same issue?

In my project, I use htmx.min.js(version 1.9.10) in the frontend and freepascal in the back end. windows 11, chrome 122.0.6261.70. My code like this:

login.css:

.wrapper .showErrorInfo {
    position: absolute;
    color: var(--text-light-clr);
    z-index: -1;
    padding: 400px 20px 60px 80px;
    opacity: 0;
    animation: showWrongLoginMsg 3s linear alternate-reverse;
}
@keyframes showWrongLoginMsg {
    form {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
}

login.html

<body>
  <div class="wrapper">
    <div class="form-box">
      <h2>Login</h2>
      <form hx-post="/dologin" hx-target="#errorInfo">
        <div class="input-box">
          <input type="text" id="username" name="username" autocomplete="off" required>
          <label for="username">UserName</label>
          <i class="bi-person"></i>
        </div>
        <div class="input-box">
          <input type="password" id="password" name="password" required>
          <label for="password">Password</label>
          <i class="bi-lock"></i>
        </div>
        <button type="submit" class="btn">Login</button>
      </form>
    </div>    
    <div id="errorInfo">
      <span></span>
    </div>
  </div>
  <script src="static/vender/htmx.js-1.9.10/htmx.min.js"></script>
</body>

MyRouters.pas

 procedure TRouteDoLogin.DoRequest(ASender: TObject; ARoute: TBrookURLRoute;
   ARequest: TBrookHTTPRequest; AResponse: TBrookHTTPResponse);
 var
   uname,pwd,cid:string;
 begin
   uname:=ARequest.Fields.Get('username');
   pwd:=ARequest.Fields.Get('password');
   if wwwDM.LoginUser(uname,pwd,cid) then begin
     AResponse.SetCookie('cid', cid);
     AResponse.Headers.Add('HX-Redirect','/home');
     AResponse.Send('login ok','text/html; charset=utf-8', 200);
   end else begin
     AResponse.Send(
      '<span class="showErrorInfo">Wrong user name or password</span>',
      'text/html; charset=utf-8', 200);
   end;
 end;           

yxh38658 avatar Feb 29 '24 10:02 yxh38658

Just to rule something out… could you please move the script node to the head?

Btw. you might have checked "disable cache" in the dev console, that’s why it works.

andryyy avatar Feb 29 '24 12:02 andryyy

  1. After moving the script node to the head, problem is still there.
  2. I checked the configuration of chrome cache and found it was exactly as you said. the "Disable cache" was checked.

So, it seems the problem is realated to cache. How to solve it?

Just to rule something out… could you please move the script node to the head?

Btw. you might have checked "disable cache" in the dev console, that’s why it works.

yxh38658 avatar Feb 29 '24 13:02 yxh38658

Oh, I can’t remember that fiasko correctly.

There was something weird about it.

It works with an additional HX-Refresh header set to true, doesn’t it?

andryyy avatar Feb 29 '24 13:02 andryyy

Oh, I can’t remember that fiasko correctly.

There was something weird about it.

It works with an additional HX-Refresh header set to true, doesn’t it?

No, it doesn't work with an additional " AResponse.Headers.Add('HX-Refresh','true'); "

yxh38658 avatar Feb 29 '24 14:02 yxh38658

The browser did not query /home but use its cache. It means it saved the page after its last visiting to /home. At that time, it failed in authorization because the browser request /home directly without login first and be redirected to /login. So, '/login' is in its cache. I add one line in /home router:

if not authOK then
  AResponse.Headers.Add('Cache-Control','no-cache');       //  this  line make sure the failed request should not be stored in cache
  AResponse.SendAndRedirect('login first','/login','text/html; charset=utf-8',301);
  exit;
end; 

Then it works.

I'd like to know what Hx-Refresh is supposed to do in this kind of circumstance? It should be use together with no-cache or it is designed to do a re-request unconditionally?

yxh38658 avatar Feb 29 '24 16:02 yxh38658