Have you checked if the request is made to the correct route?
405 Method Not Allowed in production in one form, any problem on others page forms
Hello
I have a strange behavior in the profile form, in an app with TALL. It works for me locally, and it does not work for me in production But in production it sends me a message:
Oops! An Error Occurred The server returned a "405 Method Not Allowed". Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.
When debug trace error in js, I can see strange behavior. Pese a que la ruta esta definida como GET, el proceso de alpineJs send a POST method.
fetch(
`${window.livewire_app_url}/livewire/message/${payload.fingerprint.name}`,
{
method: 'POST',
body: JSON.stringify(payload),
// This enables "cookies".
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/html, application/xhtml+xml',
'X-Livewire': true,
// We'll set this explicitly to mitigate potential interference from ad-blockers/etc.
'Referer': window.location.href,
...(csrfToken && { 'X-CSRF-TOKEN': csrfToken }),
...(socketId && { 'X-Socket-ID': socketId })
},
}
)
The form is a mix of three forms.
- The one with the profile
- The one with the password
- The one with the token
All three subforms are components of livewire.
Each one has their buton, to save.
Thus, the error occurs in any of the three save buttons, in production.
On local work perfectly.
web.php
Route::group(['prefix' => 'dashboard', 'as' => 'admin.', 'middleware' => ['auth']], function () {
Route::get('/profile', Profile::class)->name('profile');
...
});
Profile.php
<?php
namespace App\Http\Livewire\Auth;
use App\Models\User;
use Livewire\Component;
class Profile extends Component
{
public User $user;
public function mount() { $this->user = auth()->user(); }
public function render()
{
return view('livewire.auth.profile');
}
}
profile.blade.php
<div>
@livewire('auth.profile.update-profile')
<!-- Contraseña -->
<div class="hidden sm:block" aria-hidden="true">
<div class="py-5">
<div class="border-t border-gray-200"></div>
</div>
</div>
@livewire('auth.profile.update-password')
<!-- Token -->
<div class="hidden sm:block" aria-hidden="true">
<div class="py-5">
<div class="border-t border-gray-200"></div>
</div>
</div>
@livewire('auth.profile.update-token')
</div>
UpdateProfile.php
<?php
namespace App\Http\Livewire\Auth\Profile;
use App\Models\User;
use Livewire\Component;
use Livewire\WithFileUploads;
class UpdateProfile extends Component
{
use WithFileUploads;
public User $user;
public $upload;
public function render()
{
return view('livewire.auth.profile.update-profile');
}
protected function rules(): array
{
return [
'user.name' => [
'string',
'required',
'min:5',
],
'user.email' => [
'email:rfc',
'required',
'regex:/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix',
'unique:users,email,' . $this->user->id,
],
'upload' => [
'nullable',
'image',
'mimes:jpg,bmp,png',
'max:200'
],
];
}
public function mount() { $this->user = auth()->user(); }
public function save()
{
$this->validate();
$this->user->save();
$this->upload && $this->user->update([
'avatar' => $this->upload->store('/', 'avatars'),
]);
$this->emitSelf('notify-saved');
}
}
update-profile.blade.php
<div>
<div class="md:grid md:grid-cols-3 md:gap-6 border-gray-300">
<div class="md:col-span-1">
<h3 class="text-lg font-medium leading-6 text-gray-900">Perfil</h3>
<p class="mt-1 text-sm text-gray-500">
Esta información es privada y sólo tiene efectos administrativos.
</p>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<form wire:submit.prevent="save">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
<!-- Nombre -->
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="name" class="block text-sm font-medium text-gray-700">
Nombre
</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input wire:model.defer="user.name" type="text" name="username" id="username" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" placeholder="Nombre y apellidos">
</div>
<div class="mt-1 relative rounded-md shadow-sm">
@error('user.name')
<div class="mt-1 text-red-500 text-sm">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="email" class="block text-sm font-medium text-gray-700">
Email
</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input wire:model.defer="user.email" type="text" name="email" id="email" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" placeholder="Correo electrónico">
</div>
<div class="mt-1 relative rounded-md shadow-sm">
@error('user.email')
<div class="mt-1 text-red-500 text-sm">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">
Foto
</label>
<div class="mt-1 flex items-center space-x-5">
<span class="inline-block h-12 w-12 rounded-full overflow-hidden bg-gray-100">
@if ($upload)
<img src="{{ $upload->temporaryUrl() }}" alt="Profile Photo">
@else
<img src="{{ auth()->user()->avatarUrl() }}" alt="Profile Photo">
@endif
</span>
<input type="file" wire:model="upload" id="photo">
<div class="mt-1 relative rounded-md shadow-sm">
@error('user.avatar')
<div class="mt-1 text-red-500 text-sm">{{ $message }}</div>
@enderror
</div>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save
</button>
<span x-data="{ open: false }"
x-init="@this.on('notify-saved',
() => {
if (open === false) setTimeout(() => { open = false }, 3500);
open = true;
})"
x-show.transition.out.duration.1000ms="open"
style="display: none;"
class="text-gray-500">¡Guardado!</span>
</div>
</div>
</form>
</div>
</div>
</div>
UpdatePassword.php
<?php
namespace App\Http\Livewire\Auth\Profile;
use Livewire\Component;
use App\Models\User;
class UpdatePassword extends Component
{
//public User $user;
public $password;
public $password_confirmation;
public function render()
{
return view('livewire.auth.profile.update-password');
}
protected $rules = [
'password' => [
'required',
'confirmed',
'min:10',
'regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\x])(?=.*[!$#%]).*$/',
],
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function save()
{
$this->validate();
auth()->user()->update([
'password' => bcrypt($this->password)
]);
$this->emitSelf('notify-saved');
$this->resetForm();
}
protected function resetForm()
{
$this->password = '';
$this->password_confirmation = '';
}
}
update-password.blade.php
<div>
<div class="md:grid md:grid-cols-3 md:gap-6 border-gray-300">
<div class="md:col-span-1">
<h3 class="text-lg font-medium leading-6 text-gray-900">Contraseña</h3>
<p class="mt-1 text-sm text-gray-500">
Puede cambiar su contraseña en este formulario
</p>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<form wire:submit.prevent="save">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="password" class="block text-sm font-medium text-gray-700">
Contraseña
</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input wire:model.defer="password" type="password" name="password" id="password" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" placeholder="Nueva contraseña">
</div>
<div class="mt-1 relative rounded-md shadow-sm">
@error('password')
<div class="mt-1 text-red-500 text-sm">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="password_confirmation" class="block text-sm font-medium text-gray-700">
Confirma la contraseña
</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input wire:model.defer="password_confirmation" type="password" name="password_confirmation" id="password_confirmation" class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300">
</div>
<div class="mt-1 relative rounded-md shadow-sm">
@error('password_confirmation')
<div class="mt-1 text-red-500 text-sm">{{ $message }}</div>
@enderror
</div>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Cambiar
</button>
<span x-data="{ open: false }"
x-init="@this.on('notify-saved',
() => {
if (open === false) setTimeout(() => { open = false }, 3500);
open = true;
})"
x-show.transition.out.duration.1000ms="open"
style="display: none;"
class="text-gray-500">¡Contraseña cambiada!
</span>
</div>
</div>
</form>
</div>
</div>
</div>
UpdateToken.php
<?php
namespace App\Http\Livewire\Auth\Profile;
use App\Helpers\ApiHelpers;
use Livewire\Component;
class UpdateToken extends Component
{
public string $token;
public function mount()
{
$this->resetState();
}
public function updateToken()
{
$user = auth()->user();
ApiHelpers::deleteTokenUserType($user->id, 'auth_token');
$this->token = auth()->user()->createToken('auth_token')->plainTextToken;
}
public function render()
{
return view('livewire.auth.profile.update-token');
}
protected function resetState()
{
$this->token = '';
}
}
update-token.blade.php
<div>
<div class="md:grid md:grid-cols-3 md:gap-6 border-gray-300">
<div class="md:col-span-1">
<h3 class="text-lg font-medium leading-6 text-gray-900">Token API</h3>
<p class="mt-1 text-sm text-gray-500">
El token solo se muestra una vez generado, por seguridad.
<br />Copielo y guardelo en un lugar seguro.
<br />El anterior se elimina del sistema, dejan de ser operativo.
</p>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<form wire:submit.prevent="updateToken">
<div class="shadow sm:rounded-md sm:overflow-hidden">
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
<div class="grid grid-cols-3 gap-6">
<div class="col-span-3 sm:col-span-2">
<label for="token" class="block text-sm font-medium text-gray-700">
Token
</label>
<div class="mt-1 flex rounded-md shadow-sm">
<input wire:model="token" type="text" name="token" id="token" disabled class="disabled:opacity-50 focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300" placeholder="Haz click en el botón para regenerar el token">
</div>
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Regenerar
</button>
</div>
</div>
</form>
</div>
</div>
</div>
Please or to participate in this conversation.