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:
parent
5074246462
commit
6ef466f3ed
30
core/core.js
30
core/core.js
@ -1,6 +1,7 @@
|
|||||||
import * as app from './app.js';
|
import * as app from './app.js';
|
||||||
import * as auth from './auth.js';
|
import * as auth from './auth.js';
|
||||||
import * as form from './form.js';
|
import * as form from './form.js';
|
||||||
|
import * as http from './http.js';
|
||||||
import * as httpd from './httpd.js';
|
import * as httpd from './httpd.js';
|
||||||
|
|
||||||
let gProcessIndex = 0;
|
let gProcessIndex = 0;
|
||||||
@ -66,6 +67,11 @@ const k_global_settings = {
|
|||||||
default_value: undefined,
|
default_value: undefined,
|
||||||
description: 'If connecting by HTTP and HTTPS is configured, Location header prefix (ie, "https://example.com")',
|
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 = {
|
let gGlobalSettings = {
|
||||||
@ -404,6 +410,9 @@ async function getProcessBlob(blobId, key, options) {
|
|||||||
return ssb.privateMessageDecrypt(process.credentials.session.name, id, message);
|
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 &&
|
if (process.credentials &&
|
||||||
process.credentials.session &&
|
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) {
|
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);
|
response.end(data);
|
||||||
} else {
|
} 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");
|
response.end("File not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,7 +613,8 @@ async function getBlobOrContent(id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let g_handler_index = 0;
|
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 do_resolve;
|
||||||
let promise = new Promise(async function(resolve, reject) {
|
let promise = new Promise(async function(resolve, reject) {
|
||||||
do_resolve = resolve;
|
do_resolve = resolve;
|
||||||
@ -622,6 +632,8 @@ async function useAppHandler(response, handler_blob_id, path, query, headers) {
|
|||||||
respond: do_resolve,
|
respond: do_resolve,
|
||||||
},
|
},
|
||||||
credentials: auth.query(headers),
|
credentials: auth.query(headers),
|
||||||
|
packageOwner: packageOwner,
|
||||||
|
packageName: packageName,
|
||||||
});
|
});
|
||||||
await process.ready;
|
await process.ready;
|
||||||
|
|
||||||
@ -784,7 +796,11 @@ async function blobHandler(request, response, blobId, uri) {
|
|||||||
let match;
|
let match;
|
||||||
let id;
|
let id;
|
||||||
let app_id = blobId;
|
let app_id = blobId;
|
||||||
|
let packageOwner;
|
||||||
|
let packageName;
|
||||||
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
|
||||||
|
packageOwner = match[1];
|
||||||
|
packageName = match[2];
|
||||||
let db = new Database(match[1]);
|
let db = new Database(match[1]);
|
||||||
app_id = await db.get('path:' + match[2]);
|
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']) {
|
if (!id && app_object.files['handler.js']) {
|
||||||
let answer;
|
let answer;
|
||||||
try {
|
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) {
|
} catch (error) {
|
||||||
data = utf8Encode(`Internal Server Error\n\n${error?.message}\n${error?.stack}`);
|
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});
|
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') {
|
if (answer && typeof answer.data == 'string') {
|
||||||
answer.data = utf8Encode(answer.data);
|
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': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
'Content-Security-Policy': 'sandbox',
|
'Content-Security-Policy': 'sandbox',
|
||||||
});
|
}), answer.status_code);
|
||||||
} else if (id) {
|
} else if (id) {
|
||||||
if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') {
|
if (request.headers['if-none-match'] && request.headers['if-none-match'] == '"' + id + '"') {
|
||||||
let headers = {
|
let headers = {
|
||||||
|
31
core/http.js
31
core/http.js
@ -1,43 +1,45 @@
|
|||||||
function parseUrl(url) {
|
function parseUrl(url) {
|
||||||
// XXX: Hack.
|
// XXX: Hack.
|
||||||
let match = url.match(new RegExp("(\\w+)://([^/]+)?(.*)"));
|
let match = url.match(new RegExp("(\\w+)://([^/:]+)(?::(\\d+))?(.*)"));
|
||||||
return {
|
return {
|
||||||
protocol: match[1],
|
protocol: match[1],
|
||||||
host: match[2],
|
host: match[2],
|
||||||
path: match[3],
|
path: match[4],
|
||||||
port: match[1] == "http" ? 80 : 443,
|
port: match[3] ? parseInt(match[3]) : match[1] == "http" ? 80 : 443,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResponse(data) {
|
function parseResponse(data) {
|
||||||
let firstLine;
|
let firstLine;
|
||||||
let headers = {};
|
let headers = {};
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
let endLine = data.indexOf('\r\n');
|
let endLine = data.indexOf('\r\n');
|
||||||
let line = data.substring(0, endLine);
|
let line = data.substring(0, endLine);
|
||||||
if (!firstLine) {
|
data = data.substring(endLine + 2);
|
||||||
firstLine = line;
|
if (!line.length) {
|
||||||
} else if (!line.length) {
|
|
||||||
break;
|
break;
|
||||||
|
} else if (!firstLine) {
|
||||||
|
firstLine = line;
|
||||||
} else {
|
} else {
|
||||||
let colon = line.indexOf(":");
|
let colon = line.indexOf(":");
|
||||||
headers[line.substring(colon)] = line.substring(colon + 1);
|
headers[line.substring(colon)] = line.substring(colon + 1);
|
||||||
}
|
}
|
||||||
data = data.substring(endLine + 2);
|
|
||||||
}
|
}
|
||||||
return {body: data};
|
return {body: data};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetch(url, options) {
|
export function fetch(url, options, allowed_hosts) {
|
||||||
let parsed = parseUrl(url);
|
let parsed = parseUrl(url);
|
||||||
return new Promise(function(resolve, reject) {
|
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 socket = new Socket();
|
||||||
let buffer = new Uint8Array(0)
|
let buffer = new Uint8Array(0);
|
||||||
|
|
||||||
return socket.connect(parsed.host, parsed.port).then(function() {
|
return socket.connect(parsed.host, parsed.port).then(function() {
|
||||||
socket.read(function(data) {
|
socket.read(function(data) {
|
||||||
if (data) {
|
if (data && data.length) {
|
||||||
let newBuffer = new Uint8Array(buffer.length + data.length);
|
let newBuffer = new Uint8Array(buffer.length + data.length);
|
||||||
newBuffer.set(buffer, 0);
|
newBuffer.set(buffer, 0);
|
||||||
newBuffer.set(data, buffer.length);
|
newBuffer.set(data, buffer.length);
|
||||||
@ -51,7 +53,12 @@ export function fetch(url, options) {
|
|||||||
return socket.startTls();
|
return socket.startTls();
|
||||||
}
|
}
|
||||||
}).then(function() {
|
}).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();
|
socket.shutdown();
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
|
Loading…
Reference in New Issue
Block a user