Использование метода 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).
Phihag

Пожалуйста, не обижайтесь, я уже писал, что это просто примечание, и что другие версии HTML также не предлагают его (за небольшим исключением XHTML 2, но это устаревший черновик сейчас).
Хакре

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

44

Могу ли я использовать метод "Put" в html-форме для отправки данных из HTML-формы на сервер?

Да, вы можете, но имейте в виду, что это приведет не к PUT, а к запросу GET. Если вы используете недопустимое значение для methodатрибута <form>тега, браузер будет использовать значение по умолчанию get.

HTML-формы (до HTML версии 4 (, 5 Draft) и XHTML 1) поддерживают только GET и POST как методы HTTP-запроса. Обходным путем для этого является туннелирование других методов через POST с использованием скрытого поля формы, которое читается сервером, и запрос отправляется соответственно. XHTML 2,0 раз планируется поддержка GET, POST, PUT и DELETE для форм, но это происходит в XHTML5 в HTML5 , который не планирует поддержки PUT. [обновить до]

В качестве альтернативы вы можете предложить форму, но вместо ее отправки создайте и запустите XMLHttpRequest, используя метод PUT с JavaScript.



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

Это плохая идея. Каркасы могут игнорировать параметры формы для PUT. HTTPServlet в Java, кажется. У нас была ошибка, когда HttpRequest.getParameterMap()не возвращались параметры формы.
DaBlick

@DaBlick: Но не для XMLHttpRequests? Если это так, то полагаться на API выборки следует более стандартизировано.
19

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-формы «post», а затем добавьте параметр переопределения метода в HTML-форму следующим образом:

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

Для проверки ваших запросов вы можете использовать «Почтальон» расширение Google Chrome


1
Он должен работать для любого метода, включая DELETE, PATCH и т. Д.
Tofeeq

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.