質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

Q&A

解決済

2回答

14745閲覧

HTMLでPUT, DELETEメソッドを送信する方法

moritat-222

総合スコア19

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Express

ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

0グッド

1クリップ

投稿2020/06/07 11:41

##前提・実現したいこと
ドットインストールのExpressコース(2014年に更新終了・アーカイブ済)で、Node.jsのExpressフレームワークを用いたブログの作成をしています。

記事の更新・記事の削除を実装したいのですが、コースのやり方に従うと、
「Cannot POST /posts/0」「404 (Not Found)」というエラーが出てしまいます。

HTTPのフォームで更新・削除の情報を送る時に、POSTメソッドをhidden属性でput(更新)、delete(削除)メソッドに変える処理を行って実装しているのですが、うまくput,deleteととして認識されていないせいでエラーになっているのではないかと思い、解決方法を質問致します。

よろしくお願い致します。

##現在のファイル構成

bash

1├── app.js 2├── node_modules 3├── package-lock.json 4├── package.json 5├── routes 6│   └── post.js //全てのルーティング処理 7└── views 8 ├── partials 9 │   ├── footer.ejs 10 │   └── header.ejs 11 └── posts 12 ├── edit.ejs //編集ページ 13 ├── index.ejs //記事タイトル一覧ページ(編集・削除ボタン付き) 14 ├── new.ejs 15 └── show.ejs

##現在のコード

・app.js【メイン処理】

javascript

1const express = require('express'); 2const app = express(); 3const bodyParser = require('body-parser'); 4const post = require('./routes/post') 5 6 7app.set('views', __dirname + '/views'); 8app.set('view engine', 'ejs'); 9 10//middleware 11app.use(bodyParser.json()) 12app.use(bodyParser.urlencoded({extended:true})); 13 14 15//記事一覧ページ 16app.get('/',post.index); 17//記事詳細ページ 18app.get('/posts/:id([0-9]+)',post.show); 19//新規作成ページ 20app.get('/posts/new',post.new); 21//新規作成した記事の投稿 22app.post('/posts/create',post.create); 23//更新のための編集フォーム表示 24app.get('/posts/:id/edit',post.edit); 25//更新した記事の投稿【PUTメソッド】 26app.put('/posts/:id/',post.update); 27//記事の削除【DELETEメソッド】 28app.delete('/posts/:id/',post.destroy); 29 30 31app.listen(3100, () => { 32 console.log('server is up on port 3100') 33}); 34 35

・post.js【ルーティング処理】

javascript

1var posts = [ 2 {title: 'title0', body: 'body0'}, 3 {title: 'title1', body: 'body1'}, 4 {title: 'title2', body: 'body2'}, 5] 6 7exports.index = function(req,res){ 8 res.render('posts/index', {posts: posts}); 9}; 10exports.show = function(req,res){ 11 res.render('posts/show', {post: posts[req.params.id]}); 12}; 13exports.new = function(req,res){ 14 res.render('posts/new'); 15}; 16//更新のための編集フォーム表示 17exports.edit = function(req,res){ 18 res.render('posts/edit', {post:posts[req.params.id], id:req.params.id}); 19}; 20//更新した記事の投稿【PUTメソッド】 21exports.update = function(req,res){ 22 posts[req.body.id]={ 23 title: req.body.title, 24 body: req.body.body 25 } 26 res.redirect('/'); 27}; 28//記事の削除【DELETEメソッド】 29exports.destroy = function(req,res){ 30 posts.splice(req.body.id, 1); 31 res.redirect('/'); 32}; 33 34exports.create = function(req, res){ 35 var post = { 36 title: req.body.title, 37 body: req.body.body 38 }; 39 posts.push(post); 40 res.redirect('/'); 41};

・index.ejs【記事タイトル一覧&編集・削除ボタン】

ejs

1<%- include ('../partials/header'); %> 2<h1>Posts</h1> 3<ul> 4<% for (var i=0; i<posts.length; i++){ %> 5<li> 6 <a href="/posts/<%= i %>"><%= posts[i].title %></a> 7 <a href="/posts/<%= i %>/edit">[Edit]</a> 8 9//HTMLにはdeleteメソッドがないため、見せかけのコードで代用 10 <form method="post" action="/posts/<%= i %>"> 11//以下の一文を入れるとdeleteメソッドとして認識されるはず 12 <input type="hidden" name="_method" value="delete"> 13 14 <input type="hidden" name="id" value="<%= i %>"> 15 <input type="submit" value="削除"> 16 </form> 17</li> 18<% } %> 19</ul> 20<p><a href="/posts/new">Add new</a></p> 21<%- include ('../partials/footer'); %>

・edit.ejs【編集ページ】

ejs

1<%- include ('../partials/header'); %> 2<h1>Edit</h1> 3//HTMLにはputメソッドがないため、見せかけのコードで代用 4<form method="post" action="/posts/<%= id %>"> 5 <input type="text" name="title" value="<%= post.title %>"> 6 <input type="text" name="body" value="<%= post.body %>"> 7 8//以下の一文を入れるとputメソッドとして認識されるはず 9 <input type="hidden" name="_method" value="put"> 10 11 <input type="hidden" name="id" value="<%= id %>"> 12 <input type="submit" value="更新"> 13</form> 14 15<p><a href="/">Back to Top</a></p> 16<%- include ('../partials/footer'); %>

##問題点
「title0」の「削除」ボタン・「更新」ボタンを押すと、
Cannot POST /posts/0
404 (Not Found)

というエラーが出てしまう

##試したこと
「Cannot POST」と書かれているので、PUT,DELETEとして認識して欲しかったフォームの送信が、POSTとして認識されたままなのではないか?と疑っています。

input type="hidden" name="_method"を使ったPUT,DELETEの実装方法は古くなってしまっているのでしょうか?

2015年の記事『[html/css] httpのフォームでDELETEやPUTのメソッドを送る方法』では有効だったようです。

こちらの記事(『PUTやDELETEのHTTPリクエストを送信する方法色々』)では、「HTMLのformで”_method”として指定する方法」は実装できず、「ブラウザのバージョンが上がったことにより、動作しなくなったのかもしれません」と書かれていました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moritat-222

2020/06/09 10:58

ありがとうございます。method-overrideライブラリでサーバー側に細工をする必要があった、ということですね!
guest

回答2

0

ベストアンサー

[html/css] httpのフォームでDELETEやPUTのメソッドを送る方法

質問者さんが読んだのはこちらの記事だと思います。
あたかもHTMLやChromeなどのブラウザが_methodに対応しているかのように記載されていますがこれは多分誤りです。

正確には、HTML自体がGETとPOSTにしか対応していない為、
Railsやsinatraという一部フレームワークではPOST通信の一部を無理やり改変して対応しているようです。
下記の記事が信憑性が高いように思えます。

参考記事: 【Rails勉強ネタ】 HTMLのformは本当にGETとPOSTに制限されている??

Wiresharkでパケットキャプチャーして見た

確かにPOST メソッドのHTTPリクエストが送信されていることが確認できます。

また、HTML Form URL Encoded: application/x-www-form-urlencoded 内で

Form item: "_method" = "patch"というパラメーターが確認できる。
おそらくこのパラメーターを見て"patch"メソッドが送られたこととして処理しているんだと思われる(本当はPOSTメソッドを受け取っているが)。


対応策は下記の2つ

  • JavaScriptのAjaxを使う
  • Expressを拡張する

HTMLのform要素を使った送信ではGETとPOSTしか投げられません。
しかし、ブラウザ自体はPUTやDELETEにも対応しており、
JavaScriptの機能を使って送信する分にはそれらのメソッドを扱う事が可能です。

今どきのサイトは基本的にJSフレームワークなので、
Expressは勉強用と割り切って、Ajaxでの通信を学習し、
ゆくゆくはNext.jsやNuxt.js等のフロントエンドとバックエンドを両方面倒見るフレームワークに移行したほうが良いでしょう。


後者に関しても軽く調査してみました。
Railsに対応しているんだから、誰かなんかライブラリ作ってるやろな……

見つけました。

参考記事: Express 4.x でmethod-overrideでput / delete メソッドを使いたいにハマる。

Express4系では、別途method-overrideを使うのだとわかったので

_methodでメソッドを書き換えるのはWebサーバとして常に有効であるべき機能ではないので、こんな風にライブラリを咬ませる作りになっていたんですね。

expressjs/method-override - GitHub

Express.jsを作ったチームが用意しているライブラリなので、
問題なく扱えるでしょう。
Exampleを確認しながら進めてみてください。

投稿2020/06/08 04:24

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moritat-222

2020/06/09 10:57

回答ありがとうございます! 私の調べ方の至らなかった点と、その後の調べ方について言語化してくださり大変勉強になりました。 無事実装できました!
guest

0

2015年の記事『[html/css] httpのフォームでDELETEやPUTのメソッドを送る方法』では有効だったようです。

活字は文字通り活きています。内容を正しく読めばわかるはずですが、無効と明記されています。

sinatraでAPIを作っていてはまったのだが、現在のブラウザはGETとPOSTの通信方式にしか対応していないらしい

対応方法として

  1. フォームのマークアップ構造は form[method=post]>input[type=hidden][name=_method][value=DELETE]
  2. POSTされたサーバー処理で {_method: "DELETE"}を 優先処理するコードにした。

という話です。

追記)

解決策

post() に指定するミドルウェア内で _method パラメータの有無で切り分ける。


リクエストメソッド は数多くありますが、ブラウザでは GET/POST で事足りるという実装で、2種類しか使えません。

どうしても他のメソッドを使いたい場合

  1. WebフォームのPOST時のオレオレ・ルールを作る(フレームワークや言語レベルでのルール)。
  2. サーバー側 POST後の処理を仕様とは異なる実装(ルールに応じたフォームパラメータ名_method の値)で判別、処理。ログアナライザの事情に合わせ、本来は POSTメソッドだが、別のメソッドだったとウソを記録する。

仕様に定められた通りに実装されていない環境下での「フェイク(誤魔化し)」の一例と言えます。

投稿2020/06/07 14:17

編集2020/06/07 21:31
AkitoshiManabe

総合スコア5432

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

moritat-222

2020/06/09 10:49

回答ありがとうございます。「現在では無効」という肝心のところを見落としてしまっていました…。 今回はExpressのライブラリのオレオレ・ルールで無事実装できました。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問