fix: mixed-content block for STT on HTTPS - add server-side proxy
Production runs HTTPS; browser blocks http://139.59.13.39:8000 (mixed content). Solution: CI4 proxy endpoints forward audio/health check server-side (HTTP→HTTP). - Home::sttProxy() POST stt-proxy - forwards audio to STT server - Home::sttProxyHealth() GET stt-proxy/health - pings STT and returns {ok:bool} - JS: auto-detect window.location.protocol; use proxy URLs on HTTPS, direct IP URLs on HTTP (local/dev) - checkComplaintsSttServer: parse {ok:bool} from proxy health response
This commit is contained in:
parent
e6c9939b09
commit
311a7bce4b
|
|
@ -10,6 +10,8 @@ $routes->get('dashboard', 'Home::dashboard');
|
|||
$routes->get('my-profile', 'Home::myProfile');
|
||||
$routes->post('my-profile/save', 'Home::myProfileSave');
|
||||
$routes->get('speech-test', 'Home::speechTest');
|
||||
$routes->post('stt-proxy', 'Home::sttProxy');
|
||||
$routes->get('stt-proxy/health', 'Home::sttProxyHealth');
|
||||
|
||||
// Pharmacy (Medical) - phase 1
|
||||
$routes->get('Medical', 'Medical::index');
|
||||
|
|
|
|||
|
|
@ -246,6 +246,90 @@ class Home extends BaseController
|
|||
return view('tools/speech_test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Server-side proxy for the STT service.
|
||||
* Forwards audio from HTTPS clients to the HTTP STT server,
|
||||
* avoiding browser mixed-content blocks.
|
||||
*/
|
||||
public function sttProxy()
|
||||
{
|
||||
$authRedirect = $this->ensureAuthenticated();
|
||||
if ($authRedirect !== null) {
|
||||
return $this->response->setStatusCode(401)->setJSON(['error' => 'Unauthorized']);
|
||||
}
|
||||
|
||||
$file = $this->request->getFile('audio');
|
||||
if ($file === null || ! $file->isValid()) {
|
||||
return $this->response->setStatusCode(400)->setJSON(['error' => 'No valid audio file received']);
|
||||
}
|
||||
|
||||
$lang = (string) ($this->request->getPost('lang') ?? 'en-IN');
|
||||
$context = (string) ($this->request->getPost('medical_context') ?? '');
|
||||
|
||||
$sttUrl = 'http://139.59.13.39:8000/stt/transcribe';
|
||||
|
||||
$tmpPath = $file->getTempName();
|
||||
$mime = $file->getMimeType() ?: 'audio/webm';
|
||||
$name = $file->getName() ?: 'audio.webm';
|
||||
|
||||
$ch = curl_init($sttUrl);
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_POST => true,
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_POSTFIELDS => [
|
||||
'audio' => new \CURLFile($tmpPath, $mime, $name),
|
||||
'lang' => $lang,
|
||||
'medical_context' => $context,
|
||||
],
|
||||
]);
|
||||
|
||||
$body = curl_exec($ch);
|
||||
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curlErr = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($body === false || $curlErr !== '') {
|
||||
return $this->response->setStatusCode(502)
|
||||
->setJSON(['error' => 'STT server unreachable', 'detail' => $curlErr]);
|
||||
}
|
||||
|
||||
$decoded = json_decode($body, true);
|
||||
if ($decoded === null) {
|
||||
return $this->response->setStatusCode(502)
|
||||
->setJSON(['error' => 'Invalid response from STT server']);
|
||||
}
|
||||
|
||||
return $this->response->setStatusCode($httpCode > 0 ? $httpCode : 200)
|
||||
->setContentType('application/json')
|
||||
->setBody($body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy health check — pings the STT server and returns its status.
|
||||
* Lets the browser check availability over HTTPS without mixed-content issues.
|
||||
*/
|
||||
public function sttProxyHealth()
|
||||
{
|
||||
$authRedirect = $this->ensureAuthenticated();
|
||||
if ($authRedirect !== null) {
|
||||
return $this->response->setStatusCode(401)->setJSON(['ok' => false]);
|
||||
}
|
||||
|
||||
$ch = curl_init('http://139.59.13.39:8000/health');
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_TIMEOUT => 4,
|
||||
CURLOPT_NOBODY => false,
|
||||
]);
|
||||
$body = curl_exec($ch);
|
||||
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
$ok = ($body !== false && $httpCode >= 200 && $httpCode < 300);
|
||||
return $this->response->setStatusCode(200)->setJSON(['ok' => $ok]);
|
||||
}
|
||||
|
||||
public function myProfileSave()
|
||||
{
|
||||
$authRedirect = $this->ensureAuthenticated();
|
||||
|
|
|
|||
|
|
@ -959,8 +959,10 @@
|
|||
var medicalSttStream = null;
|
||||
var medicalSttChunks = [];
|
||||
var medicalSttActive = false;
|
||||
var complaintsSttServerHealthUrl = 'http://139.59.13.39:8000/health';
|
||||
var complaintsSttServerTranscribeUrl = 'http://139.59.13.39:8000/stt/transcribe';
|
||||
// Use server-side proxy when page is HTTPS (avoids mixed-content block)
|
||||
var _onHttps = (window.location.protocol === 'https:');
|
||||
var complaintsSttServerHealthUrl = _onHttps ? '<?= base_url('stt-proxy/health') ?>' : 'http://139.59.13.39:8000/health';
|
||||
var complaintsSttServerTranscribeUrl = _onHttps ? '<?= base_url('stt-proxy') ?>' : 'http://139.59.13.39:8000/stt/transcribe';
|
||||
var draftKey = 'opd_rx_draft_' + ($('#opd_id').val() || '0');
|
||||
var templateLoadState = { target: '', section: '', rows: [] };
|
||||
var templateSaveState = { section: '', text: '', scope: 'doctor' };
|
||||
|
|
@ -1244,7 +1246,15 @@
|
|||
mode: 'cors',
|
||||
signal: controller.signal
|
||||
}).then(function(response) {
|
||||
return !!(response && response.ok);
|
||||
if (!response || !response.ok) {
|
||||
return false;
|
||||
}
|
||||
// Proxy returns {ok: bool}; direct server returns 200 with any body
|
||||
return response.json().then(function(data) {
|
||||
return data && data.ok !== false;
|
||||
}).catch(function() {
|
||||
return true; // direct server: 200 with non-JSON body is fine
|
||||
});
|
||||
}).catch(function() {
|
||||
return false;
|
||||
}).finally(function() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user