Problems with Form POST in Safari and IOS

I have this simple router, relying on a simple HTML form.
export const authSigninRouter = new Hono();

const SigninForm = ({ email = '', errors }) => {
return (
<form class="mt-5 grid gap-2 lg:gap-8" method="POST" action="/auth/signin">
<label class="grid w-full gap-3">
<span>Email address</span>
<input type="email" name="email" />
</label>
<label class="grid w-full gap-3">
<span>Password</span>
<input type="password" name="password" />
</label>
<button>Signin</button>
</form>
);
};

authSigninRouter.get('/', async (c) => {
return c.render(<SigninForm />);
});

authSigninRouter.post('/', async (c) => {
const { email, password } = await c.req.parseBody();
///...
const token = await sign(tokenUser);

setCookie(c, 'bearer_token', token, { secure: true, httpOnly: true });

return c.redirect('/');
});
export const authSigninRouter = new Hono();

const SigninForm = ({ email = '', errors }) => {
return (
<form class="mt-5 grid gap-2 lg:gap-8" method="POST" action="/auth/signin">
<label class="grid w-full gap-3">
<span>Email address</span>
<input type="email" name="email" />
</label>
<label class="grid w-full gap-3">
<span>Password</span>
<input type="password" name="password" />
</label>
<button>Signin</button>
</form>
);
};

authSigninRouter.get('/', async (c) => {
return c.render(<SigninForm />);
});

authSigninRouter.post('/', async (c) => {
const { email, password } = await c.req.parseBody();
///...
const token = await sign(tokenUser);

setCookie(c, 'bearer_token', token, { secure: true, httpOnly: true });

return c.redirect('/');
});
Using chrome, on my computer, i have no problems whatsoever Using Safari on the computer, or safari or chrome from my iphone, or safari on the iPhone simulator, it doesn't work. I get the message on my server: TypeError: Request aborted, code: "ABORT_ERR" I'm using Hono with Bun, like so:
const app = new Hono();

Bun.serve({
port: PORT,
reload: true,
fetch: app.fetch,
});

app.use('*', serveStatic({ root: 'public/' }));

app.route('/', appRouter);
const app = new Hono();

Bun.serve({
port: PORT,
reload: true,
fetch: app.fetch,
});

app.use('*', serveStatic({ root: 'public/' }));

app.route('/', appRouter);
any insights on why this may be happening? Thanks
29 Replies
Nico
Nico7mo ago
What causes it to throw that error, just on load or submitting it? The reason it happens on chrome on your iPhone is because it’s still the same engine as safari with just a different look
rubberduckies
rubberduckiesOP7mo ago
yeah, it's webkit, i know that 🙂 nothing throws, the error actually disappeared, i'm not sure why, i have been making changes i have console.logs all the way down, and everything works as expected but in the browser i get
Nico
Nico7mo ago
So it’s working fine now?
rubberduckies
rubberduckiesOP7mo ago
rubberduckies
rubberduckiesOP7mo ago
the last console.log(3, 'token set') is immediatly before the return c.redirect('/') but it's also not the redirect because i get the same result with
rubberduckies
rubberduckiesOP7mo ago
No description
Nico
Nico7mo ago
Do you have any middleware that fires before the response sends that could be messing it up
rubberduckies
rubberduckiesOP7mo ago
yes hmm
Nico
Nico7mo ago
Can you the commenting it out and see if it works
rubberduckies
rubberduckiesOP7mo ago
sure
import { verify } from 'jwt';
import { getCookie } from 'hono/cookie';

export const userMiddleware = async (c, next) => {
const authorization = getCookie(c, 'bearer_token');
if (!authorization) {
c.status(401);
return c.redirect('/auth/signin');
}

try {
const user = await verify(authorization);
if (!user) {
c.status(401);
return c.redirect('/auth/signin');
}
c.user = user;
} catch (ex) {
c.status(401);
return c.redirect('/auth/signin');
}

return next();
};
import { verify } from 'jwt';
import { getCookie } from 'hono/cookie';

export const userMiddleware = async (c, next) => {
const authorization = getCookie(c, 'bearer_token');
if (!authorization) {
c.status(401);
return c.redirect('/auth/signin');
}

try {
const user = await verify(authorization);
if (!user) {
c.status(401);
return c.redirect('/auth/signin');
}
c.user = user;
} catch (ex) {
c.status(401);
return c.redirect('/auth/signin');
}

return next();
};
and this works perfectly in chrome on the browser also, from the iphone, it never even gets here the middleware is only injected for the dashboard router
Nico
Nico7mo ago
Well it server side so it would have to work in all browsers for that so it must be something else
rubberduckies
rubberduckiesOP7mo ago
yeah, but i can't figure it out and it keeps on working on chrome, haha oh, i found another problem where the
TypeError: Request aborted code: "ABORT_ERR" disappeared it comes back if i do
const { email, password } = await c.req.parseBody()
const { email, password } = await c.req.parseBody()
it stopeed erroring like that, because i had hardcoded email and password for a bit
Nico
Nico7mo ago
Don’t destructure it, just set it as a variable and confirm your getting the email and password Just for debugging I mean
rubberduckies
rubberduckiesOP7mo ago
that's what i did before i commented it and just had const email = 'email'; const password = 'password' so it did pass that obstacle, but in the end, the result was the same, nothing goes to the browser
Nico
Nico7mo ago
But I’m saying confirm that you are getting a username and password in parseBody
rubberduckies
rubberduckiesOP7mo ago
oh i'll try that then
Nico
Nico7mo ago
If not JSX might not set the form type automatically *data type
rubberduckies
rubberduckiesOP7mo ago
<form class="mt-5 grid gap-2 lg:gap-8" method="POST">
rubberduckies
rubberduckiesOP7mo ago
and the headers come correctly "application/x-www-form-urlencoded"
No description
Nico
Nico7mo ago
You are posting directly with the form correct, you’re not sending it with a fetch
rubberduckies
rubberduckiesOP7mo ago
posting directly but i also tried with a fetch (using HTMX) and the result is the same
Nico
Nico7mo ago
Would you mind sharing the whole route
rubberduckies
rubberduckiesOP7mo ago
i'm going to do something better give me a sec
import { Hono } from 'hono';

const { ADMIN_PORT: PORT } = process.env;
const app = new Hono();

Bun.serve({
port: PORT,
reload: true,
fetch: app.fetch,
});

app.get('/', (c) => {
return c.html(
<form method="POST">
<button type="submit">Submit</button>
</form>,
);
});

app.post('/', (c) => {
return c.html(<h1>POSTED</h1>);
});

console.log('Admin app running on port', PORT);
import { Hono } from 'hono';

const { ADMIN_PORT: PORT } = process.env;
const app = new Hono();

Bun.serve({
port: PORT,
reload: true,
fetch: app.fetch,
});

app.get('/', (c) => {
return c.html(
<form method="POST">
<button type="submit">Submit</button>
</form>,
);
});

app.post('/', (c) => {
return c.html(<h1>POSTED</h1>);
});

console.log('Admin app running on port', PORT);
this is the simplest form, and it is working on safari also with this, still working:
app.post('/', (c) => {
return c.redirect('/');
});
app.post('/', (c) => {
return c.redirect('/');
});
this is also working...
app.get('/', (c) => {
const posted = getCookie(c, 'posted');
if (posted) return c.html(<h1>Posted</h1>);

return c.html(
<form method="POST">
<button type="submit">Submit</button>
</form>,
);
});

app.post('/', (c) => {
setCookie(c, 'posted', 'true');
return c.redirect('/');
});
app.get('/', (c) => {
const posted = getCookie(c, 'posted');
if (posted) return c.html(<h1>Posted</h1>);

return c.html(
<form method="POST">
<button type="submit">Submit</button>
</form>,
);
});

app.post('/', (c) => {
setCookie(c, 'posted', 'true');
return c.redirect('/');
});
rubberduckies
rubberduckiesOP7mo ago
this, oddly, still works
No description
rubberduckies
rubberduckiesOP7mo ago
this still works, getting weirder
No description
rubberduckies
rubberduckiesOP7mo ago
still working...
No description
Nico
Nico7mo ago
Hey I’ll come back to you I gotta step out for a bit. If we want we can hop on #voice and try and debug it
rubberduckies
rubberduckiesOP7mo ago
that would be great than you so much
Nico
Nico7mo ago
Ready when you are https://discord.gg/j6vbf8cZ

Did you find this page helpful?