'use strict'; const { requestBuffer } = require('./http-client'); function authHeader(config) { const token = Buffer.from(`${config.username}:${config.password}`).toString('base64'); return `Basic ${token}`; } function ocsUrl(config, path, query) { const base = config.nextcloudUrl.replace(/\/$/, ''); const q = query || 'format=json'; const sep = path.includes('?') ? '&' : '?'; return `${base}${path}${sep}${q}`; } function tlsOptions(config) { return config.verifyTls !== false && config.verifyTls !== 'false'; } function parseOcsBody(bodyBuffer) { const text = bodyBuffer.toString('utf8'); try { const json = JSON.parse(text); const ocs = json.ocs || json; const meta = ocs.meta || {}; const statuscode = Number(meta.statuscode ?? meta.statusCode ?? 200); if (statuscode >= 400) { // 996 = intern serverfel, 998 = not found m.m. — inkludera alltid // OCS-bodyn så felet går att felsöka utan logggrävning. const message = meta.message || meta.status || ''; const raw = text.slice(0, 300); throw new Error(`OCS ${statuscode}: ${message}${message && raw !== message ? ` (${raw})` : raw}`); } return { statusCode: statuscode, data: ocs.data, raw: json }; } catch (err) { if (err.message.startsWith('OCS ')) { throw err; } throw new Error(`OCS-svar kunde inte parsas (HTTP-body): ${text.slice(0, 200)}`); } } async function ocsRequest(config, { method = 'GET', path, query, body, headers = {}, contentType }) { const url = ocsUrl(config, path, query); const reqHeaders = { Authorization: authHeader(config), 'OCS-APIRequest': 'true', Accept: 'application/json', ...headers }; let payload; if (body !== undefined) { if (Buffer.isBuffer(body)) { payload = body; } else if (typeof body === 'string') { payload = Buffer.from(body, 'utf8'); reqHeaders['Content-Type'] = contentType || 'application/json'; } else { payload = Buffer.from(JSON.stringify(body), 'utf8'); reqHeaders['Content-Type'] = contentType || 'application/json'; } reqHeaders['Content-Length'] = payload.length; } const res = await requestBuffer({ url, method, headers: reqHeaders, body: payload, rejectUnauthorized: tlsOptions(config) }); if (res.statusCode === 401 || res.statusCode === 403) { throw new Error(`OCS ${res.statusCode}: kontrollera app-lösenord`); } // OCS-fel (996/998/…) kommer med HTTP 4xx/5xx men har parsbar meta-body — // försök alltid parsa först så felet innehåller OCS-meddelandet. const parsed = parseOcsBody(res.body); if (res.statusCode < 200 || res.statusCode >= 300) { const bodyText = res.body.toString('utf8').slice(0, 200); throw new Error(`OCS-anrop misslyckades (HTTP ${res.statusCode}) för ${path}: ${bodyText || ''}`); } return { httpStatus: res.statusCode, ...parsed }; } module.exports = { ocsRequest, ocsUrl };