2

Zuulを使用してリクエストを内部のマイクロサービスに転送しています。内部サービスには、2つのエンドポイント(PUTエンドポイントとPOSTエンドポイント)があります。マルチパートリクエストは、内部PUTエンドポイントに到達する前に破損していることがわかりました。マルチパートのPUTリクエストはZuul/DispatcherServletによって破損しています(マルチパートデータは削除されます)

マルチパートデータがリクエストから削除されたようです。これは、POSTが完全に機能するため、PUT要求の場合にのみ当てはまります。

cURLで直接内部PUTエンドポイントにヒットした場合、要求は正しく処理されます。対応curlコマンドとリクエストボディは、次のようになり:

curl -v -X PUT -H "Content-Type: multipart/form-data" -F "[email protected]/path/to/file.txt" "http://localhost:8081/file/put" 

ヘッダ:

{ユーザーエージェント= [カール/ 7.35.0]、ホスト= [ローカルホスト:8082]、受け入れます= [/]、content-length = [203]、expect = [100-continue]、content-type = [multipart/form-data;境界= ------------------------ c1efb86a9054e387]}

エンティティ:

----------- --------------- c1efb86a9054e387コンテンツの処理:フォームデータ。 name = "file";ファイル名= "helloworld.txt" のContent-Type:text/plainの

これは私のファイルの内容

です-----------------------我々はZuul経由のcURLでPUTエンドポイントをヒットしようとした場合--- c1efb86a9054e387--

しかし、要求は次のようになります。

curl -X PUT -H "Content-Type: multipart/form-data" -F "[email protected]/path/to/file.txt" "http://localhost:8082/file/put" 

ヘッダー:

{user-agent = [curl/7.35.0]、accept = [/]、expect = [100-continue]、content-type = [multipart/form-data; boundary = hkBnDNXOcDTwkuL1qLhglF6i4NA2YREd]、x-forwarded-host = [localhost:8081]、x-forwarded-proto = [http]、x-forwarded-prefix = [/ file]、x-forwarded-port = [8081]、x-forwarded-for = [127.0.0.1]受け入れエンコード= [GZIP]、コンテンツ長= [38]、ホスト= [ローカルホスト:8082]、接続= [キープアライブ]}

エンティティ:

--hkBnDNXOcDTwkuL1qLhglF6i4NA2YREd--

エンティティが不完全であることに注意してください。

私はこのリポジトリにサンプルコードをアップロードしました:https://github.com/trcodestore/zuul-put-demo。リポジトリには、この問題を示すために使用した2つの小さなプロジェクトが含まれていますreadmeにはビルドと実行の指示が含まれています。

私は、リクエストは当初はSpringのDispatcherServletによって処理され、最終的にはZuulServletによって処理されることを理解しています。この問題を引き起こしているDispatcherServletだと思います。 DispatcherServletをバイパスするには、すべてのリクエストURIの前に "/ zuul"を付ける必要があります。これにより、マルチパートリクエストがZuulServletに直接渡され、期待どおりに動作します。しかし、これは理想的な解決策ではありません。

アドバイスをいただければ幸いです。ありがとう。

答えて

3

さて、解決策(credit: Mohammad Zolmajd)があります。

スプリングブートは、マルチパートを処理するためにStandardServletMultipartResolverを使用します。これは、すべてのマルチパート要求がPOSTとともに送信されることを前提としています。

StandardServletMultipartResolverがPUTリクエストを処理できるようにするには、isMultiPartメソッドをオーバーライドする必要があります。私は次の設定を使用して終了しました:

@Bean 
public MultipartResolver multipartResolver() { 
    return new StandardServletMultipartResolver() { 
    @Override 
    public boolean isMultipart(HttpServletRequest request) { 
     String method = request.getMethod().toLowerCase(); 
     if (!Arrays.asList("put", "post").contains(method)) { 
      return false; 
     } 
     String contentType = request.getContentType(); 
     return (contentType != null &&contentType.toLowerCase().startsWith("multipart/")); 
    } 
    }; 
} 
関連する問題