diff --git a/README.md b/README.md index 1843220..219feda 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,18 @@ bun install Other package managers can be used as well. +To start a development server, run: + +```bash +bun run dev +``` + +Or to deploy to Cloudflare Workers, run: + +```bash +bun run deploy +``` + ### Configuration Create file `.dev.vars` at the root of the project and add the following content: diff --git a/package.json b/package.json index 1441584..bbff1d6 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "deploy:dev": "wrangler deploy -c wrangler.deploy.toml --env development", "dev": "wrangler dev", "start": "wrangler dev", + "tail": "wrangler tail mirrors", "cf-typegen": "wrangler types" }, "devDependencies": { diff --git a/src/mw/proxy.ts b/src/mw/proxy.ts index 5a924d8..098e183 100644 --- a/src/mw/proxy.ts +++ b/src/mw/proxy.ts @@ -1,7 +1,7 @@ import { createMiddleware } from "hono/factory"; import type { Env, BlankEnv, MiddlewareHandler } from "hono/types"; import type { Context } from "hono"; -import { parseFunctional, pathStartsWith, isContentType } from "@/utils"; +import { parseFunctional, pathStartsWith, replaceContentType } from "@/utils"; type ProxyRewrite = (c: Context, path: string, url: string) => string @@ -37,15 +37,16 @@ export function changeOrigin(origin: string | ProxyRew urlobj.host = inobj.host urlobj.port = inobj.port urlobj.pathname = newpath + urlobj.search = urlobj.search const resp = await fetch(urlobj, { method: c.req.method, headers: c.req.raw.headers, redirect: 'follow', + body: c.req.raw.body }) const headers = new Headers(resp.headers) - if (opts.forbidHTML && isContentType(headers, 'text/html')) { - headers.delete('Content-Type') - headers.set('Content-Type', 'text/plain') + if (opts.forbidHTML) { + replaceContentType(headers, 'text/html', 'text/plain') } return new Response(resp.body, { status: resp.status, @@ -65,11 +66,11 @@ export function rewriteURL(rewrite: ProxyRewrite, o method: c.req.method, headers: c.req.raw.headers, redirect: 'follow', + body: c.req.raw.body }) const headers = new Headers(resp.headers) - if (opts.forbidHTML && isContentType(headers, 'text/html')) { - headers.delete('Content-Type') - headers.set('Content-Type', 'text/plain') + if (opts.forbidHTML) { + replaceContentType(headers, 'text/html', 'text/plain') } return new Response(resp.body, { status: resp.status, @@ -115,7 +116,8 @@ export function forwardPath(options?: Partial(async (c, next) => { opts.forbidHTML = parseFunctional(opts.forbidHTML) // format url to standard - let next_url = opts.forwardUrl || c.req.path.substring(1) + let search = new URL(c.req.url, "http://localhost").search + let next_url = opts.forwardUrl || c.req.path.substring(1) + search const thisUrlObj = new URL(c.req.url, "http://localhost") let _t = _testURLProtocol(next_url) if (_t === "invalid") return await next() @@ -129,14 +131,14 @@ export function forwardPath(options?: Partial { method: c.req.method, headers: c.req.raw.headers, redirect: 'follow', + body: c.req.raw.body }) if (resp.status === 401) { const wwwAuth = resp.headers.get('WWW-Authenticate') @@ -94,6 +95,7 @@ app.on('GET', ['/token', '/v2/auth'], async c => { // method: c.req.method, // headers: c.req.raw.headers, // redirect: 'follow', + // body: c.req.raw.body // }) // if (r.status !== 401) throw new HTTPException(500, { message: 'Unknown response' }) // const wwwAuth = r.headers.get('WWW-Authenticate') @@ -128,6 +130,7 @@ app.on('GET', ['/token', '/v2/auth'], async c => { method: c.req.method, headers: c.req.raw.headers, redirect: 'follow', + body: c.req.raw.body }) }) diff --git a/src/routes/git.ts b/src/routes/git.ts index 50555e3..2cc09b6 100644 --- a/src/routes/git.ts +++ b/src/routes/git.ts @@ -4,7 +4,8 @@ import Proxy, { _testURLProtocol } from "@/mw/proxy"; const app = new Hono(); app.use(async (c, next) => { - let path_url = c.req.path.substring(1) + let search = new URL(c.req.url, "http://localhost").search + let path_url = c.req.path.substring(1) + search let _t = _testURLProtocol(path_url) if (_t === "invalid") return await next() else if (_t === "miss_protocol") { diff --git a/src/utils.ts b/src/utils.ts index 146e6f5..7064101 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -54,6 +54,19 @@ export function isContentType(headers: Headers, t: string): boolean { return contentTypes.some(ct => ct.split(";")[0].trim() === t) } +export function replaceContentType(headers: Headers, _ori: string, _new: string): Headers { + if (!headers.has("Content-Type")) return headers + let contentTypes = headers.get("Content-Type")?.split(",") || [] + let newContentTypes = contentTypes.map(ct => { + let [t, ...params] = ct.split(";") + if (t.trim() === _ori.trim()) return _new.trim() + ';' + params.join(";") + return ct + }) + headers.delete("Content-Type") + headers.set("Content-Type", newContentTypes.join(",")) + return headers +} + export const parseFunctional = (v: T | (() => T)): T => typeof v === "function" ? (v as CallableFunction)() : v export async function hmac_sha256(key: ArrayBuffer, data: ArrayBuffer) {