Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorundan ve nasıl çözdüğümden bahsedeceğim. Kullanıcıların kamerasına ve mikrofonuna erişen bir web uygulaması geliştiriyordum. Chrome ve Firefox'ta her şey tıkırındaydı, ama Safari'yi açtığım anda navigator.mediaDevices.getUserMedia fonksiyonu sessiz sedasız hata verdi, hiçbir iz, hiçbir uyarı! Kafayı yemiştim, çünkü localhost'ta çalışıyordu ve diğer tarayıcılarda sorun yoktu.
Araştırmaya başladığımda, Safari'nin (ve diğer modern tarayıcıların) güvenlik politikası gereği, kamera/mikrofon gibi hassas cihazlara erişim için HTTPS bağlantısını zorunlu tuttuğunu öğrendim. "localhost" istisna gibi görünse de, Safari bazen bu istisnayı da es geçebiliyor, özellikle daha katı güvenlik ayarlarında. Development ortamında da HTTPS kullanmam gerekiyordu.
Sorunun Kökeni ve Çözüm Yolu
Sorun şuydu: Development sunucum (örneğin Laravel Valet, Vite dev server, Next.js dev server) varsayılan olarak HTTP ile çalışıyor. Çözüm ise bu sunuculara bir kendinden imzalı (self-signed) SSL sertifikası kurup, tarayıcıya bu sertifikaya güvenmesini söylemekti. İşte benim kullandığım en temiz ve evrensel çözüm: mkcert aracı.
Bu araç, localhost için tarayıcıların ve işletim sisteminin güvendiği geçerli sertifikalar oluşturuyor. Kurulumu ve kullanımı çok basit.
Adım Adım mkcert ile HTTPS Kurulumu
Öncelikle sisteminize mkcert'i kurmanız gerekiyor. Ben macOS kullanıyorum, Homebrew ile kuruyorum:
Windows'ta ise Chocolatey (`choco install mkcert`) veya Scoop (`scoop install mkcert`) kullanabilirsiniz. Linux'ta paket yöneticinizden kurabilirsiniz.
Kurulum tamamlandıktan sonra, ilk adım olarak mkcert'in yerel CA (Sertifika Otoritesi) sertifikasını oluşturup sisteminize yüklemek:
Bu komut, mkcert'in kendi kök sertifikasını oluşturup sistem güven deposuna ekler. Tarayıcılar artık bu CA tarafından imzalanan tüm sertifikalara güvenecek.
Şimdi, projemizin bulunduğu dizinde veya istediğiniz bir yerde, localhost için bir sertifika oluşturalım:
Bu komut, `localhost` (IPv4 ve IPv6 adresleri için) geçerli iki dosya oluşturacak: `localhost.pem` (sertifika) ve `localhost-key.pem` (özel anahtar).
Geliştirme Sunucusunu HTTPS'e Taşımak
Artık elimizde sertifikalar var. Şimdi bu sertifikaları kullanarak development sunucumuzu HTTPS modunda başlatmamız gerekiyor. Kullandığınız araçlara göre yöntem değişir.
Örnek 1: Node.js (Express) Sunucusu İçin:
Örnek 2: Vite / Next.js (package.json script'i):
`package.json` dosyanızdaki dev script'ini değiştirebilirsiniz:
Ancak Vite'e sertifika yolunu göstermek daha iyidir. Bir `vite.config.js` dosyası oluşturun:
Bu ayarlardan sonra, `npm run dev` dediğinizde artık uygulamanız `
` (veya benzeri bir port) üzerinden erişilebilir olacak. İlk defa giriş yaptığınızda tarayıcı "Güvenli Değil" uyarısı verebilir, çünkü sertifika kendinden imzalı. Ancak biz mkcert CA'sını yüklediğimiz için, genellikle bu uyarı otomatik olarak kaybolur veya "Gelişmiş" seçeneğinden devam edebilirsiniz.
Sonuç ve Test
Her şeyi doğru yaptıysanız, artık Safari'de de `getUserMedia` sorunsuz çalışacak. Hemen basit bir test yapalım:
Bu kodu HTTPS üzerinden çalıştırdığınızda, Safari size kamera/mikrofon izni soracak ve izin verdikten sonra görüntü akışı başlayacak.
İşte benim kullandığım en temiz çözüm buydu. mkcert sayesinde hem güvenli bir development ortamım oldu, hem de tarayıcılar arası uyumluluk sorununu kökünden çözdüm. Siz development ortamınızda HTTPS kurmak için hangi yöntemleri kullanıyorsunuz? Laravel Valet veya Docker gibi ortamlarda benzer bir sorunla karşılaştınız mı? Yorumlarda deneyimlerinizi paylaşın!
Araştırmaya başladığımda, Safari'nin (ve diğer modern tarayıcıların) güvenlik politikası gereği, kamera/mikrofon gibi hassas cihazlara erişim için HTTPS bağlantısını zorunlu tuttuğunu öğrendim. "localhost" istisna gibi görünse de, Safari bazen bu istisnayı da es geçebiliyor, özellikle daha katı güvenlik ayarlarında. Development ortamında da HTTPS kullanmam gerekiyordu.
Sorun şuydu: Development sunucum (örneğin Laravel Valet, Vite dev server, Next.js dev server) varsayılan olarak HTTP ile çalışıyor. Çözüm ise bu sunuculara bir kendinden imzalı (self-signed) SSL sertifikası kurup, tarayıcıya bu sertifikaya güvenmesini söylemekti. İşte benim kullandığım en temiz ve evrensel çözüm: mkcert aracı.
Bu araç, localhost için tarayıcıların ve işletim sisteminin güvendiği geçerli sertifikalar oluşturuyor. Kurulumu ve kullanımı çok basit.
Öncelikle sisteminize mkcert'i kurmanız gerekiyor. Ben macOS kullanıyorum, Homebrew ile kuruyorum:
Bash:
brew install mkcert
brew install nss # Firefox için (isteğe bağlı)
Windows'ta ise Chocolatey (`choco install mkcert`) veya Scoop (`scoop install mkcert`) kullanabilirsiniz. Linux'ta paket yöneticinizden kurabilirsiniz.
Kurulum tamamlandıktan sonra, ilk adım olarak mkcert'in yerel CA (Sertifika Otoritesi) sertifikasını oluşturup sisteminize yüklemek:
Bash:
mkcert -install
Bu komut, mkcert'in kendi kök sertifikasını oluşturup sistem güven deposuna ekler. Tarayıcılar artık bu CA tarafından imzalanan tüm sertifikalara güvenecek.
Şimdi, projemizin bulunduğu dizinde veya istediğiniz bir yerde, localhost için bir sertifika oluşturalım:
Bash:
mkcert localhost 127.0.0.1 ::1
Bu komut, `localhost` (IPv4 ve IPv6 adresleri için) geçerli iki dosya oluşturacak: `localhost.pem` (sertifika) ve `localhost-key.pem` (özel anahtar).
Artık elimizde sertifikalar var. Şimdi bu sertifikaları kullanarak development sunucumuzu HTTPS modunda başlatmamız gerekiyor. Kullandığınız araçlara göre yöntem değişir.
Örnek 1: Node.js (Express) Sunucusu İçin:
JavaScript:
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
const options = {
key: fs.readFileSync('localhost-key.pem'),
cert: fs.readFileSync('localhost.pem')
};
https.createServer(options, app).listen(3000, () => {
console.log('HTTPS Sunucusu https://localhost:3000 adresinde çalışıyor!');
});
Örnek 2: Vite / Next.js (package.json script'i):
`package.json` dosyanızdaki dev script'ini değiştirebilirsiniz:
JSON:
"scripts": {
"dev": "vite --https --host --open",
// veya Next.js için: "dev": "next dev --experimental-https"
}
Ancak Vite'e sertifika yolunu göstermek daha iyidir. Bir `vite.config.js` dosyası oluşturun:
JavaScript:
import { defineConfig } from 'vite'
import fs from 'fs'
export default defineConfig({
server: {
https: {
key: fs.readFileSync('localhost-key.pem'),
cert: fs.readFileSync('localhost.pem'),
},
host: true // LAN'da erişim için
}
})
Bu ayarlardan sonra, `npm run dev` dediğinizde artık uygulamanız `
Bu bağlantı ziyaretçiler için gizlenmiştir. Görmek için lütfen giriş yapın veya üye olun.
Her şeyi doğru yaptıysanız, artık Safari'de de `getUserMedia` sorunsuz çalışacak. Hemen basit bir test yapalım:
HTML:
<button id="start">Kamerayı Aç</button>
<video id="video" autoplay playsinline muted></video>
<script>
document.getElementById('start').addEventListener('click', async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
const videoElement = document.getElementById('video');
videoElement.srcObject = stream;
console.log("Kamera erişimi başarılı!");
} catch (error) {
console.error("Kamera hatası:", error.name, error.message);
}
});
</script>
Bu kodu HTTPS üzerinden çalıştırdığınızda, Safari size kamera/mikrofon izni soracak ve izin verdikten sonra görüntü akışı başlayacak.
İşte benim kullandığım en temiz çözüm buydu. mkcert sayesinde hem güvenli bir development ortamım oldu, hem de tarayıcılar arası uyumluluk sorununu kökünden çözdüm. Siz development ortamınızda HTTPS kurmak için hangi yöntemleri kullanıyorsunuz? Laravel Valet veya Docker gibi ortamlarda benzer bir sorunla karşılaştınız mı? Yorumlarda deneyimlerinizi paylaşın!