Pull Request Pertama Saya di Laravel Framework — Part 2

Serial - Pull Request Pertama Saya di Laravel Framework

Check this article on Medium: @ngodingbang/pull-request-pertama-saya-di-laravel-framework-part-2-1b03fbdaf3c1

This article has been translated into English version: My First Pull Request to Laravel Framework — Part 2

PR saya di Laravel Framework ditandai dalam kotak merah, dirilis tanggal 11 Mei 2022 pada versi 9.12 (Sumber: https://laravel-news.com/laravel-9-12-0).
PR saya di Laravel Framework ditandai dalam kotak merah, dirilis tanggal 11 Mei 2022 pada versi 9.12 (Sumber: https://laravel-news.com/laravel-9-12-0).

Part sebelumnya sudah pernah saya jelaskan di sini: Pull Request Pertama Saya di Laravel Framework — Part 1. Bagi kamu yang penasaran dengan ceritanya, silakan dibaca dulu yak :)

Apa Sebenarnya Bug yang Saya Temukan Pada Saat Itu?

Jadi pada saat itu saya ingin menambahkan sebuah request header ketika mengirim HTTP Request menggunakan fitur HTTP Client yang ada di Laravel. Tapi penambahan request header tidak bisa dilakukan menggunakan method withHeaders() karena nilai dari request header tersebut bersifat dinamis dan mengandalkan alamat URL yang akan dituju oleh HTTP Request.

Sumber: https://laravel.com/docs/9.x/http-client#headers
Sumber: https://laravel.com/docs/9.x/http-client#headers

Alhasil saya menggunakan method beforeSending() yang disediakan dan menambahkan request header dengan cara membuat callback sebagai berikut.

Ini kode yang saya buat untuk menambahkan request header pada HTTP Client secara dinamis berdasarkan alamat URL yang dituju. Alamat URL tersebut didapatkan dari parameter Illuminate\Http\Client\Request $request yang diberi oleh method Http::beforeSending() dan diolah dan disimpan di variable $requestLine.
Ini kode yang saya buat untuk menambahkan request header pada HTTP Client secara dinamis berdasarkan alamat URL yang dituju. Alamat URL tersebut didapatkan dari parameter Illuminate\Http\Client\Request $request yang diberi oleh method Http::beforeSending() dan diolah dan disimpan di variable $requestLine.

Saya tidak bisa menggunakan method withHeaders() dari parameter Illuminate\Http\Client\PendingRequest $pendingRequest untuk menambahkan request header baru.

php

$pendingRequest->withHeaders([‘Authorization’ => ‘Bearer .$requestLine]);

Hal ini terjadi karena parameter $pendingRequest sudah ter-instantiate duluan sebelum method HTTP::beforeSending() dipanggil, sehingga penggunaan method withHeader() pada parameter $pendingRequest tidak akan ada gunanya. Jadi satu-satunya cara untuk menambahkan request header pada HTTP Client di atas adalah dengan menggunakan method withHeader() yang disediakan oleh parameter Illuminate\Http\Client\Request $request.

php

$request->toPsrRequest()->withHeader(‘Authorization’, ‘Bearer .$requestLine);

Ketika kita menggunakan HTTP::beforeSending(), maka yang terjadi sebenarnya adalah callback yang telah dibuat sebelumnya akan didaftarkan ke dalam property pada class PendingRequest seperti berikut.

Callback untuk menambahkan request header sebelumnya akan ditambahkan ke object pada class PendingRequest. Tepatnya pada property bertipe array $beforeSendingCallbacks milik class Pending Request.
Callback untuk menambahkan request header sebelumnya akan ditambahkan ke object pada class PendingRequest. Tepatnya pada property bertipe array $beforeSendingCallbacks milik class Pending Request.

Lalu seluruh callback yang sudah terdaftar akan dijalankan menggunakan method runBeforeSendingCallbacks() milik class PendingRequest seperti berikut.

Source code pada class PendingRequest sebelum dilakukan pull request. Di sinilah letak bug yang sempat saya singgung di part sebelumnya.
Source code pada class PendingRequest sebelum dilakukan pull request. Di sinilah letak bug yang sempat saya singgung di part sebelumnya.

Di sinilah masalah tersebut mulai muncul. Ketika menggunakan cara di atas, request header tidak berubah sama sekali. Saya terus mengutak-atik kode yang saya buat, namun hasilnya tetap saja tidak menunjukkan perubahan yang berarti. Request header yang sudah saya tambahkan pada callback sebelumnya tetap tidak terkirim pada HTTP Client.

Fokus pada kotak merah. Property headers dan headerNames dari object GuzzleHttp\Psr7\Request tidak berubah meski sudah ditambahkan request header baru “Authorization”.
Fokus pada kotak merah. Property headers dan headerNames dari object GuzzleHttp\Psr7\Request tidak berubah meski sudah ditambahkan request header baru “Authorization”.

Bagaimana Cara Saya Memecahkan Bug Tersebut?

Yang ingin saya lakukan pada laptop saya ketika bug tersebut tidak kunjung tuntas. Kesal sekali rasanya waktu itu 😤.
Yang ingin saya lakukan pada laptop saya ketika bug tersebut tidak kunjung tuntas. Kesal sekali rasanya waktu itu 😤.

Awalnya saya tidak mengerti kenapa hal ini bisa terjadi. Tapi setelah mengulik lebih jauh, akhirnya saya menemukan akar masalahnya. Ternyata method runBeforeSendingCallbacks() di class PendingRequest yang digunakan untuk menjalankan HTTP::beforeSending() tidak berjalan seperti yang diharapkan. Akhirnya saya coba men-tweak kode di class PendingRequest sebagai berikut.

Source code pada class PendingRequest setelah dilakukan pull request. Detailnya akan saya jelaskan di bawah ini.
Source code pada class PendingRequest setelah dilakukan pull request. Detailnya akan saya jelaskan di bawah ini.

Jadi dari tweak tersebut, ada beberapa perubahan yang saya lakukan. Di antaranya:

  1. @return dari method tersebut saya ganti dari \Closure menjadi \GuzzleHttp\Psr7\RequestInterface. Sebenarnya ini tidak memberi pengaruh secara langsung terhadap kode, tapi jelas dari sisi dokumentasi tipe data dari @return tersebut tidak benar. Karena method tap() yang digunakan untuk memodifikasi variable $request seharusnya mengembalikan $request itu sendiri yaitu \GuzzleHttp\Psr7\RequestInterface (Penjelasan lebih lanjut bisa dibaca di sini ya: @taylorotwell/tap-tap-tap-1fc6fc1f93a6).
  2. Saya membuat variable baru $callbackResult untuk menangkap hasil dari method call_user_func() yang sudah ada sebelumnya. Sehingga jika ada return value yang diberikan dari hasil eksekusi method call_user_func(), maka return value tersebut akan ditaruh ke variable $request.
  3. Selanjutnya variable $request pada method tap() dan each() saya ubah menjadi pass by reference sehingga perubahan yang dilakukan oleh $callbackResult dapat diteruskan sampai ke return value dari method runBeforeSendingCallbacks() itu sendiri.

Dari perubahan tersebut, maka request header yang sudah saya tambahkan pada callback sebelumnya akhirnya bisa terkirim pada HTTP Client seperti yang saya mau. Tentunya ada sedikit penyesuaian pada callback yang ada pada Http::beforeSending() seperti berikut.

Kode untuk menambahkan request header pada HTTP Client secara dinamis setelah dilakukan penyesuaian. Ada penambahan keyword “return” di akhir callback agar $request yang sudah dimodikasi bisa diteruskan pada $callbackResult milik class PendingRequest.
Kode untuk menambahkan request header pada HTTP Client secara dinamis setelah dilakukan penyesuaian. Ada penambahan keyword “return” di akhir callback agar $request yang sudah dimodikasi bisa diteruskan pada $callbackResult milik class PendingRequest.
Request header baru “Authorization” akhirnya berhasil ditambahkan ke property headers dan headerNames dari object GuzzleHttp\Psr7\Request.
Request header baru “Authorization” akhirnya berhasil ditambahkan ke property headers dan headerNames dari object GuzzleHttp\Psr7\Request.

Selanjutnya Apa?

Setelah melewati perjalanan yang berliku untuk menyelesaikan tersebut, saatnya men-submit bugfix ini ke Laravel. Tapi sepertinya cerita tersebut tidak muat jika saya taruh semuanya di part ini, jadi saya putuskan untuk membuatnya terpisah di part selanjutnya.

Pull Request Pertama Saya di Laravel Framework — Part 3

Bagi kamu yang penasaran atau mungkin ingin mencoba untuk membuat pull request ke Laravel, silakan lanjut ke part selanjutnya. Terima kasih sudah menyimak dan sampai jumpa di part selanjutnya! Arigatou 🙏

Konten Terkait