Використання методу PUT у формі HTML


175

Чи можна використовувати метод PUT у формі HTML для надсилання даних із форми на сервер?

Відповіді:



194

Згідно стандарту HTML , ви можете НЕ . Єдині допустимі значення для атрибута методу getі post, відповідні GET і POST методи HTTP. <form method="put">недійсний HTML, і він буде розглядатися як <form>, тобто надсилати GET-запит.

Натомість багато фреймворків просто використовують параметр POST для тунелювання методу HTTP:

<form method="post" ...>
  <input type="hidden" name="_method" value="put" />
...

Звичайно, для цього потрібно розгортання на стороні сервера.


3
Ви пов'язували проект, а не остаточний стандарт. Зауваживши, стабільні версії HTML також не пропонують його.
хакре

13
@hakre HTML5 вже є де-факто стандартом і, ймовірно, буде розвиватися з часом. Те, що W3C називає "Чернетка", - це документально розроблений протягом щонайменше 3-х років із залученням постачальників браузерів понад> 99%, і вже реалізовано (принаймні, якщо мова йде про цей та більшість неезотеричних розділів) всі вони назавжди. Але тільки для азотистів - ось еквівалентне визначення в HTML 4.01 (технічний запит в умовах W3C).
Фігаг

Будь ласка, не ображайтесь, я вже писав, що це просто примітка і що інші версії HTML також не пропонують її (за винятком XHTML 2, але це вже застарілий проект).
хакре

1
@hakre Будьте впевнені, що я зовсім не ображаюся. Я зауважую, що XHTML технічно не є HTML, хоча можна знайти одну чи дві подібності;)
phihag

44

Чи можу я використовувати метод "Покласти" у форматі html для надсилання даних з HTML форми на сервер?

Так, ви можете, але майте на увазі, що це призведе не до PUT, а до GET-запиту. Якщо ви використовуєте недійсне значення для methodатрибута <form>тегу, браузер використовуватиме значення за замовчуванням get.

Форми HTML (до HTML версії 4 (, 5 Чернетка) та XHTML 1) підтримують лише GET та POST як методи запиту HTTP. Вирішенням цього є тунелювання інших методів через POST, використовуючи приховане поле форми, яке зчитується сервером і відповідним чином надсилається запит. XHTML 2,0 разу планується підтримка GET, POST, PUT і DELETE для форм, але це відбувається в XHTML5 в HTML5 , який не планує підтримки PUT. [оновити до]

Ви можете запропонувати форму, але замість того, щоб подавати її, створіть та запустіть XMLHttpRequest, використовуючи метод PUT з JavaScript.



Запит AJAX не може повністю замінити запит форми, оскільки запит форми перенаправляє користувача на даний ресурс. Наприклад, зараз немає можливості показати у браузері сторінку маршруту PUT /resource.
JacopoStanchi

Це погана ідея. Рамки можуть ігнорувати параметри форми для PUT. HTTPServlet Java виглядає так. У нас була помилка, де HttpRequest.getParameterMap()не поверталися параметри форми.
DaBlick

@DaBlick: Але не для XMLHttpRequests? Якщо так, то покладатися на API вибору слід більш стандартизовано.
хакре

27

_method приховане поле обходу

Наступна проста техніка використовується в декількох веб-рамках:

  • додайте прихований _methodпараметр до будь-якої форми, яка не GET або POST:

    <input type="hidden" name="_method" value="PUT">

    Це можна зробити автоматично в рамках за допомогою допоміжного методу створення HTML.

  • виправити фактичний метод форми до POST ( <form method="post")

  • обробляє _methodна сервері і робить так, як якщо б цей метод був надісланий замість фактичного POST

Цього можна досягти:

  • Рейки: form_tag
  • Laravel: @method("PATCH")

Обґрунтування / історія того, чому це неможливо в чистому HTML: /software/114156/why-there-are-no-put-and-delete-methods-in-html-forms


Laravel (php) має таку ж особливість, використовуючи@method("PATCH")
santiago arizti

Це здається розумним вирішенням, але все ще прикро, оскільки це ускладнює налагодження. Наприклад, якщо вам потрібно пройти журнали серверів або зробити мережевий аналіз, щоб перевірити деякі речі, ви не побачите правильного виводу, оскільки метод HTTP, який використовується в заголовках HTTP, все ще є, POSTа не те, що вам потрібно.
code_dredd

8

На жаль, сучасні браузери не надають вбудовану підтримку HTTP PUT-запитів. Щоб подолати це обмеження, переконайтеся, що атрибут методу вашої HTML-форми є "пост", а потім додайте параметр заміщення методу до своєї форми HTML таким чином:

<input type="hidden" name="_METHOD" value="PUT"/>

Для перевірки ваших запитів можна скористатися розширенням google chrome "Листоноша"


1
Він повинен працювати для будь-якого методу, включаючи
УДАЛИТИ

1

Для встановлення методів PUT і DELETE я виконую наступні дії:

<form
  method="PUT"
  action="domain/route/param?query=value"
>
  <input type="hidden" name="delete_id" value="1" />
  <input type="hidden" name="put_id" value="1" />
  <input type="text" name="put_name" value="content_or_not" />
  <div>
    <button name="update_data">Save changes</button>
    <button name="remove_data">Remove</button>
  </div>
</form>
<hr>
<form
  method="DELETE"
  action="domain/route/param?query=value"
>
  <input type="hidden" name="delete_id" value="1" />
  <input type="text" name="delete_name" value="content_or_not" />
  <button name="delete_data">Remove item</button>
</form>

Тоді JS діє для виконання бажаних методів:

<script>
   var putMethod = ( event ) => {
     // Prevent redirection of Form Click
     event.preventDefault();
     var target = event.target;
     while ( target.tagName != "FORM" ) {
       target = target.parentElement;
     } // While the target is not te FORM tag, it looks for the parent element
     // The action attribute provides the request URL
     var url = target.getAttribute( "action" );

     // Collect Form Data by prefix "put_" on name attribute
     var bodyForm = target.querySelectorAll( "[name^=put_]");
     var body = {};
     bodyForm.forEach( element => {
       // I used split to separate prefix from worth name attribute
       var nameArray = element.getAttribute( "name" ).split( "_" );
       var name = nameArray[ nameArray.length - 1 ];
       if ( element.tagName != "TEXTAREA" ) {
         var value = element.getAttribute( "value" );
       } else {
       // if element is textarea, value attribute may return null or undefined
         var value = element.innerHTML;
       }
       // all elements with name="put_*" has value registered in body object
       body[ name ] = value;
     } );
     var xhr = new XMLHttpRequest();
     xhr.open( "PUT", url );
     xhr.setRequestHeader( "Content-Type", "application/json" );
     xhr.onload = () => {
       if ( xhr.status === 200 ) {
       // reload() uses cache, reload( true ) force no-cache. I reload the page to make "redirects normal effect" of HTML form when submit. You can manipulate DOM instead.
         location.reload( true );
       } else {
         console.log( xhr.status, xhr.responseText );
       }
     }
     xhr.send( body );
   }

   var deleteMethod = ( event ) => {
     event.preventDefault();
     var confirm = window.confirm( "Certeza em deletar este conteúdo?" );
     if ( confirm ) {
       var target = event.target;
       while ( target.tagName != "FORM" ) {
         target = target.parentElement;
       }
       var url = target.getAttribute( "action" );
       var xhr = new XMLHttpRequest();
       xhr.open( "DELETE", url );
       xhr.setRequestHeader( "Content-Type", "application/json" );
       xhr.onload = () => {
         if ( xhr.status === 200 ) {
           location.reload( true );
           console.log( xhr.responseText );
         } else {
           console.log( xhr.status, xhr.responseText );
         }
       }
       xhr.send();
     }
   }
</script>

Якщо ці функції визначені, я додаю слухач подій до кнопок, які подають запит методу форми:

<script>
  document.querySelectorAll( "[name=update_data], [name=delete_data]" ).forEach( element => {
    var button = element;
    var form = element;
    while ( form.tagName != "FORM" ) {
      form = form.parentElement;
    }
    var method = form.getAttribute( "method" );
    if ( method == "PUT" ) {
      button.addEventListener( "click", putMethod );
    }
    if ( method == "DELETE" ) {
      button.addEventListener( "click", deleteMethod );
    }
  } );
</script>

А для кнопки видалення на формі PUT:

<script>
  document.querySelectorAll( "[name=remove_data]" ).forEach( element => {
    var button = element;
    button.addEventListener( "click", deleteMethod );
</script>

_ - - - - - - - - - - -

Ця стаття https://blog.garstasio.com/you-dont-need-jquery/ajax/ мені дуже допомагає!

Крім цього, ви можете встановити функцію postMethod і отримати getMethod для обробки методів надсилання POST та GET, як вам подобається, а не поведінки за замовчуванням у веб-переглядачі. Замість цього ви можете робити все, що завгодно location.reload(), як показати повідомлення про успішні зміни або успішне видалення.

= - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = - = -

JSFiddle: https://jsfiddle.net/enriquerene/d6jvw52t/53/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.