7 に答える
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ステータスメッセージがHTTPヘッダー内で使用されます。XSSの脆弱性を防ぐために、ユーザーは、特にユーザーが提供した入力がメッセージに含まれている場合は、そのようなメッセージがISO-8859-1でエンコードされていることを確認する必要があります。指定しない場合、デフォルト値のfalseが使用されます。
元の脆弱性の詳細については、次のページを参照してください。
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 サーバーなのかです。
(ここでベストプラクティスのアドバイスも見られることを願っています。)
Springを利用したWebアプリケーションでは、Tomcatで実行し、次の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
はそれを行うべきだと思いますが、アプリケーションサーバーが失敗している可能性があります... IBM WebSphere 3.5 はずっと前に失敗しましたが、Tomcat はメッセージを問題なく伝播しました。JavaServer Pages (JSP) および JSTL - エラー ページ: ヘッダー "HTTP/1.x 400 My message" を保持しますか? を参照してください。Sun フォーラムで。
最終的に次の回避策を使用しましたが、これは一種の 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 のハイパーテキスト トランスポートの説明のレジストリ キーも参照してください。プロトコル エラー メッセージ.)