私はJavaでRESTful Webサービスに取り組んでいます。何か問題がある場合は、クライアントにエラーメッセージを送信するための良い方法が必要です。
Javadoc によれば、HttpServletResponse.setStatus(int status, String message)
は非推奨 "メッセージパラメータの意味があいまいなためです。"
ステータスメッセージまたは応答の「 reason phrase 」を設定する優先的な方法はありますか? sendError(int, String)
メソッドはそれを行いません。
編集:明確にするために、HTTPステータス行、つまり"HTTP/1.1 404 Not Found"
、本文のコンテンツではありません。具体的には、"HTTP/1.1 400 Missing customerNumber parameter"
。
RESTfulクライアントは、理由句を見て何が間違っているのかを理解するとは思わないでしょう。私が見た/使用したほとんどのRESTfulサービスは、応答の本文で標準のステータス情報と拡張メッセージを送信します。 sendError(int, String)
はそのような状況に最適です。
Tomcatを使用している場合は、org.Apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADERの設定を参照してください。
http://Tomcat.Apache.org/Tomcat-5.5-doc/config/systemprops.html
元の脆弱性の詳細については、このページを参照してください。
http://www.securityfocus.com/archive/1/archive/1/495021/100/0/threaded
説明の後、Tomcatでこれを試しました。実行中
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "message goes here");
戻り値
HTTP/1.1 400 message goes here
応答の最初の行として。
使用しているサーブレットコンテナに問題があるはずです。
RESTの「ベストプラクティス」にあまり詳しくありません。しかし、私はこの概念がHTTPに基づいており、どのように自然に機能するかを知っています。それでは、「application/myapp-exception」や「Bla bla」などのアプリケーションエラーに対して、MIMEタイプと本文内のシンプルなテキストを使用してはどうでしょうか。そのためのクライアントライブラリを提供できます。
アプリケーションエラーにはHTTP応答コードを使用しません。何が失敗したのか、それが私のアプリケーションなのか、HTTPサーバーなのかを知りたいからです。
(私もここでいくつかのベストプラクティスのアドバイスを見たいと思います。)
Tomcatで実行されるSpringベースのWebアプリケーションでは、次のBeanを使用します。
import Java.util.Map;
import Java.util.Set;
import Java.util.Map.Entry;
import org.springframework.beans.factory.InitializingBean;
public class SystemPropertiesInitializingBean implements InitializingBean {
private Map<String, String> systemProperties;
@Override
public void afterPropertiesSet() throws Exception {
if (null == systemProperties || systemProperties.isEmpty()) {
return;
}
final Set<Entry<String, String>> entrySet = systemProperties.entrySet();
for (final Entry<String, String> entry : entrySet) {
final String key = entry.getKey();
final String value = entry.getValue();
System.setProperty(key, value);
}
}
public void setSystemProperties(final Map<String, String> systemProperties) {
this.systemProperties = systemProperties;
}
}
そしてapplicationContext.xmlで:
<bean class="....SystemPropertiesInitializingBean">
<property name="systemProperties">
<map>
<entry key="org.Apache.coyote.USE_CUSTOM_STATUS_MSG_IN_HEADER" value="true"/>
</map>
</property>
</bean>
何を達成しようとしているのかは明確ではありません。私の最初の考えはsendErrorでしたが、それはあなたが望むことをしないと言います...特定のxmlまたはJSONコンテンツ(または転送言語として使用しているもの)を意味する一連の「エラー応答」の作成を見ましたか?エラーメッセージまたはコードおよびその他の有用な情報が含まれていますか?
私はSpring-mvcベースのRESTfulサービスに対してそのようなことをしばらく前に行いましたが、うまく機能しましたが、クライアントが一般的な500メッセージなどを取得しないようにすべての例外をキャッチして処理する必要があります。そのために、Spring Exception Resolversはうまく機能しました。
これが役立つことを願っています...もしそうでなければ、おそらくあなたが達成しようとしていることについてもう少し明確になります。私が密集していて、明らかな何かを見逃している場合は申し訳ありません。
sendError
はそれを行うべきだと思いますが、アプリケーションサーバーに障害が発生している可能性があります。 Sunフォーラムの JavaServer Pages(JSP)およびJSTL-エラーページ:ヘッダー「HTTP/1.x 400マイメッセージ」を保持しますか? を参照してください。
最終的には次の回避策を使用しましたが、これは一種のJSP固有のものであり、実際には古い可能性があります。
<%@ page isErrorPage="true" %>
<%
// This attribute is NOT set when calling HttpResponse#setStatus and then
// explicitely incuding this error page using RequestDispatcher#include()
// So: only set by HttpResponse#sendError()
Integer origStatus =
(Integer)request.getAttribute("javax.servlet.error.status_code");
if(origStatus != null) {
String origMessage =
(String)request.getAttribute("javax.servlet.error.message");
if(origMessage != null) {
response.reset();
response.setContentType("text/html");
// deprecated, but works:
response.setStatus(origStatus.intValue(), origMessage);
// would yield recursive error:
// response.sendError(origStatus, origMessage);
}
}
%>
また、Internet Explorerでテストする場合は、「HTTPエラーメッセージをわかりやすく表示する」を無効にします。 (それを無効にしない場合、IEにはHTMLコンテンツの最小長という奇妙な要件があり、満たされない場合は、IE代わりに独自のエラーメッセージを表示します。レジストリキーHKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Main\ErrorThresholds
Microsoftで ハイパーテキストトランスポートプロトコルエラーメッセージの説明 。)