Fixed enough thing sto be able to authenticate and get data from Strava.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4347 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2023-07-16 21:04:48 +00:00
parent 5074246462
commit 6ef466f3ed
2 changed files with 42 additions and 19 deletions

View File

@ -1,6 +1,7 @@
import * as app from './app.js';
import * as auth from './auth.js';
import * as form from './form.js';
import * as http from './http.js';
import * as httpd from './httpd.js';
let gProcessIndex = 0;
@ -66,6 +67,11 @@ const k_global_settings = {
default_value: undefined,
description: 'If connecting by HTTP and HTTPS is configured, Location header prefix (ie, "https://example.com")',
},
fetch_hosts: {
type: 'string',
default_value: undefined,
description: 'Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.',
},
};
let gGlobalSettings = {
@ -404,6 +410,9 @@ async function getProcessBlob(blobId, key, options) {
return ssb.privateMessageDecrypt(process.credentials.session.name, id, message);
}
};
imports.fetch = function(url, options) {
return http.fetch(url, options, gGlobalSettings.fetch_hosts);
}
if (process.credentials &&
process.credentials.session &&
@ -583,12 +592,12 @@ function guessTypeFromMagicBytes(data) {
}
}
function sendData(response, data, type, headers) {
function sendData(response, data, type, headers, status_code) {
if (data) {
response.writeHead(200, Object.assign({"Content-Type": type || guessTypeFromMagicBytes(data) || "application/binary", "Content-Length": data.byteLength}, headers || {}));
response.writeHead(status_code ?? 200, Object.assign({"Content-Type": type || guessTypeFromMagicBytes(data) || "application/binary", "Content-Length": data.byteLength}, headers || {}));
response.end(data);
} else {
response.writeHead(404, Object.assign({"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}, headers || {}));
response.writeHead(status_code ?? 404, Object.assign({"Content-Type": "text/plain; charset=utf-8", "Content-Length": "File not found".length}, headers || {}));
response.end("File not found");
}
}
@ -604,7 +613,8 @@ async function getBlobOrContent(id) {
}
let g_handler_index = 0;
async function useAppHandler(response, handler_blob_id, path, query, headers) {
async function useAppHandler(response, handler_blob_id, path, query, headers, packageOwner, packageName) {
print('useAppHandler', packageOwner, packageName);
let do_resolve;
let promise = new Promise(async function(resolve, reject) {
do_resolve = resolve;
@ -622,6 +632,8 @@ async function useAppHandler(response, handler_blob_id, path, query, headers) {
respond: do_resolve,
},
credentials: auth.query(headers),
packageOwner: packageOwner,
packageName: packageName,
});
await process.ready;
@ -784,7 +796,11 @@ async function blobHandler(request, response, blobId, uri) {
let match;
let id;
let app_id = blobId;
let packageOwner;
let packageName;
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
packageOwner = match[1];
packageName = match[2];
let db = new Database(match[1]);
app_id = await db.get('path:' + match[2]);
}
@ -794,7 +810,7 @@ async function blobHandler(request, response, blobId, uri) {
if (!id && app_object.files['handler.js']) {
let answer;
try {
answer = await useAppHandler(response, app_id, uri.substring(1), request.query ? form.decodeForm(request.query) : undefined, request.headers);
answer = await useAppHandler(response, app_id, uri.substring(1), request.query ? form.decodeForm(request.query) : undefined, request.headers, packageOwner, packageName);
} catch (error) {
data = utf8Encode(`Internal Server Error\n\n${error?.message}\n${error?.stack}`);
response.writeHead(500, {'Content-Type': 'text/plain; charset=utf-8', 'Content-Length': data.length});
@ -804,10 +820,10 @@ async function blobHandler(request, response, blobId, uri) {
if (answer && typeof answer.data == 'string') {
answer.data = utf8Encode(answer.data);
}
sendData(response, answer?.data, answer?.content_type, {
sendData(response, answer?.data, answer?.content_type, Object.assign(answer?.headers ?? {}, {
'Access-Control-Allow-Origin': '*',
'Content-Security-Policy': 'sandbox',
});
}), answer.status_code);
} else if (id) {
if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') {
let headers = {

View File

@ -1,43 +1,45 @@
function parseUrl(url) {
// XXX: Hack.
let match = url.match(new RegExp("(\\w+)://([^/]+)?(.*)"));
let match = url.match(new RegExp("(\\w+)://([^/:]+)(?::(\\d+))?(.*)"));
return {
protocol: match[1],
host: match[2],
path: match[3],
port: match[1] == "http" ? 80 : 443,
path: match[4],
port: match[3] ? parseInt(match[3]) : match[1] == "http" ? 80 : 443,
};
}
function parseResponse(data) {
let firstLine;
let headers = {};
while (true) {
let endLine = data.indexOf('\r\n');
let line = data.substring(0, endLine);
if (!firstLine) {
firstLine = line;
} else if (!line.length) {
data = data.substring(endLine + 2);
if (!line.length) {
break;
} else if (!firstLine) {
firstLine = line;
} else {
let colon = line.indexOf(":");
headers[line.substring(colon)] = line.substring(colon + 1);
}
data = data.substring(endLine + 2);
}
return {body: data};
}
export function fetch(url, options) {
export function fetch(url, options, allowed_hosts) {
let parsed = parseUrl(url);
return new Promise(function(resolve, reject) {
if (allowed_hosts.indexOf(parsed.host) == -1) {
throw new Error(`fetch() request to host ${parsed.host} is not allowed.`);
}
let socket = new Socket();
let buffer = new Uint8Array(0)
let buffer = new Uint8Array(0);
return socket.connect(parsed.host, parsed.port).then(function() {
socket.read(function(data) {
if (data) {
if (data && data.length) {
let newBuffer = new Uint8Array(buffer.length + data.length);
newBuffer.set(buffer, 0);
newBuffer.set(data, buffer.length);
@ -51,7 +53,12 @@ export function fetch(url, options) {
return socket.startTls();
}
}).then(function() {
socket.write(`${options?.method ?? 'GET'} ${parsed.path} HTTP/1.0\r\nHost: ${parsed.host}\r\nConnection: close\r\n\r\n`);
let body = typeof options?.body == 'string' ? utf8Encode(options.body) : (options.body || new Uint8Array(0));
let headers = utf8Encode(`${options?.method ?? 'GET'} ${parsed.path} HTTP/1.0\r\nHost: ${parsed.host}\r\nConnection: close\r\nContent-Length: ${body.length}\r\n\r\n`);
let fullRequest = new Uint8Array(headers.length + body.length);
fullRequest.set(headers, 0);
fullRequest.set(body, headers.length);
socket.write(fullRequest);
socket.shutdown();
}).catch(function(error) {
reject(error);