Saturday, September 8, 2018

Akses request/response body pada Filter

Berkenaan dengan bahasan pada topik filter disini, kita melakukan logging pada request GET dan semua berjalan dengan lancar. Namun lain cerita ketika melakukannya pada metode lain yang memiliki body.
Request POST dengan body

Jika kita kirimkan request tersebut ke endpoint, maka akan mendapatkan pesan error sebagai response.
Log error pada terminal

Mengapa hal tersebut terjadi ? Mari kita telaah.

[Kenapa]
Pada gambar log error diatas, spring melakukan throw error IllegalStateException dengan pesan "getReader() has already been called for this request". Pengeluaran error tersebut terjadi ketika handler akan melakukan proses tertentu.
Jika dilihat kembali pada log error, terdapat pemanggilan getInputStream(). Berdasarkan dokumentasi, ketika suatu method telah melakukan pemanggilan method getReader() maka tidak dapat melakukan pemanggilan getInputStream() [dapat diakses disini]. Pada implementasi filter yang dicontohkan, terdapat pemanggilan getReader() untuk kebutuhan logging.
Pemanggilan InputStream pada log

Lalu bagai mana cara untuk mengatasi hal tersebut ? Ada beberapa cara tentunya. Namun dalam tulisan ini, hanya akan dibahas dengan menggunakan objek pembungkus pada request dan response.

[Request/Response Wrapper]
Kenapa kita menggunakan wrapper ? wrapper berfungsi untuk melakukan adaptasi fungsionalitas objek terhadap kebutuhan. Untuk mengimplementasikan wrapper pada kasus diatas, terlebih dahulu kita membuat sebuah kelas yang mengekstensi HttpServletRequestWrapper untuk request atau HttpServletResponseWrapper untuk response.
Implementasi wrapper pada request

NostraRequestWrapper merupakan inner class yang akan membuat request beradaptasi terhadap kasus. Kita dapat melakukan overriding method sehingga sesuai dengan kebutuhan.
Jika dilihat pada konstruktor kelas, NostraRequestWrapper melakukan penyimpanan informasi dari request pada field dengan menggunakan getReader() beserta mendefinisikan getter untuk field tersebut. Kemudian kita melakukan overriding method getInputStream() sehingga filter lain atau endpoint akan memanggil method getInputStream() hasil adaptasi. Pada contoh ini, kita hanya membuat sebuah input stream baru berdasarkan informasi yang sebelumnya disimpan dalam field.
Untuk menggunakan wrapper tersebut, kita membuat sebuah objek dengan argumen request, kemudian melempar objek wrapper, dan bukan request original, ke chain doFilter().
Penggunaan wrapper

Ketika dicoba, proses tidak mengalami masalah yang serupa.
Proses request aman dan terkendali

Prinsip yang sama juga digunakan pada response.

[Kesimpulan]
Dalam proses logging, kita tidak dapat melakukan akses data begitu saja pada filter. Perlu melakukan proses terlebih dahulu sehingga informasi pada request tersebut dapat diakses oleh filter berikutnya atau endpoint. Wrapper HttpServlet dapat digunakan untuk melakukan proses tersebut dengan proses overriding pada method yang diperlukan.

Happy Learning, Happy Programming, Happy Sharing
- Laman -

Resource
[1] HttpServletRequestWrapper API. Dapat diakses di https://docs.oracle.com/javaee/1.3/api/javax/servlet/ServletRequestWrapper.html
[2] BufferedReader API. Dapat diakses di https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html

No comments:

Post a Comment