download files from git repos via HTTP

shared-server
bat 3 years ago
parent 243a2a19d7
commit f13dba1912

@ -1,6 +1,17 @@
export class Frontend {
repoUrl(user, repo) {
constructor({apiBaseUrl, appBaseUrl}) {
this.apiBaseUrl = apiBaseUrl
this.appBaseUrl = appBaseUrl
this.files = {}
this.tasks = []
}
repoUrl(user, repo) {
return (
this.apiBaseUrl +
'/' + encodeURIComponent(user) +
'/' + encodeURIComponent(repo)
)
}
rawUrl(user, repo, commit, path) {
@ -12,10 +23,86 @@ export class Frontend {
)
}
async loadFile(user, repo, commit, src, dest) {
const url = this.rawUrl(user, repo)
const resp = await fetch(url)
const body = await resp.arrayBuffer()
this.files[dest] = {
user,
repo,
commit,
body,
contentType: (
dest.endsWith('.js') ?
'text/javascript' :
resp.headers.get('content-type')
)
}
}
contentsUrl(user, repo, path, ref) {
const url = new URL(
this.repoUrl(user, repo) +
'/contents' +
path.map(s => (
'/' + encodeURIComponent(s)
)).join('')
)
if (ref !== undefined) {
const search = new URLSearchParams()
search.set('ref', ref)
url.search = search.toString()
}
return url.toString()
}
async loadRepo(user, repo, opts) {
const {
srcPath = [], destPath = [], ref
} = opts
const url = this.contentsUrl(
user, repo, srcPath, ref
)
const resp = await fetch(url)
const contents = await resp.json()
for (const item of contents) {
if (item.type === 'dir') {
this.tasks.push(this.loadRepo(user, repo, {
...opts,
srcPath: [...srcPath, item.name],
destPath: [...destPath, item.name],
}))
} else {
this.tasks.push(this.loadFile(
user,
repo,
last_commit_sha,
[...srcPath, item.name],
[...destPath, item.name],
))
}
}
let prevCount = 0
while (this.tasks.count > prevCount) {
prevCount = this.tasks.count
await Promise.allSettled(this.tasks)
}
}
async serve(event) {
// TODO: load files from different mounted repos
event.respondWith(new Response(
'Not Found', {status: 404}
))
const {pathname} = new URL(event.request.url)
if (pathname in this.files) {
const file = this.files[pathname]
event.respondWith(new Response(file.body, {
status: 404,
headers: {
'Content-Type': file.contentType,
},
}))
} else {
event.respondWith(new Response(
'Not Found', {status: 404}
))
}
}
}

@ -2,11 +2,6 @@ import { Auth } from "./auth"
import { Frontend } from "./frontend"
export class Server {
constructor() {
this.auth = new Auth()
this.frontend = new Frontend()
}
async getEnv(variables) {
return Object.fromEntries(
await Promise.all(
@ -26,10 +21,27 @@ export class Server {
async configure() {
const env = await this.getEnv([
'PORT', 'BASE_URL'
'PORT',
'BASE_URL',
'GITEA_APP_BASE_URL',
'GITEA_API_BASE_URL',
])
this.port = env.PORT ?? 3000
this.baseUrl = env.BASE_URL ?? '/macchiato'
this.giteaAppBaseUrl = (
env.GITEA_APP_BASE_URL ?? 'http://gitea:3000'
)
this.giteaApiBaseUrl = (
env.GITEA_API_BASE_URL ?? 'http://gitea:3000/api/v1'
)
}
async init() {
this.auth = new Auth()
this.frontend = new Frontend({
appBaseUrl: this.giteaAppBaseUrl,
apiBaseUrl: this.giteaApiBaseUrl,
})
}
async serveRequest(event) {
@ -50,6 +62,7 @@ export class Server {
async serve() {
await this.configure()
await this.init()
this.server = Deno.listen({
port: this.port,
})

Loading…
Cancel
Save