import*as b from"node:http";import{AsyncLocalStorage as A}from"node:async_hooks";import{Readable as y,Stream as k}from"node:stream";import{pipeline as x}from"node:stream/promises";import{ReadableStream as H}from"node:stream/web";import{getPathPrefix as L}from"@redocly/theme/core/utils";import{ALLOWED_CORS_ORIGINS as C}from"../../constants/common.js";import{logger as w}from"../tools/notifiers/logger.js";import{exit as I}from"../utils/process/exit.js";import{getClientIp as T}from"./utils/get-client-ip.js";import{normalizeIpAddress as v}from"./utils.js";const S=new A;globalThis.redoclyCookieStorage=S;function z(n,l=4e3){return new Promise((i,m)=>{const d=b.createServer(async(t,r)=>{const u=t.headers.cookie||"";S.run(u,async()=>{let s;try{const e=new URL(t.url||"",`http://${t.headers.host}`),o=[],c=t.rawHeaders.length;for(let h=0;h<c;h+=2)o.push([t.rawHeaders[h],t.rawHeaders[h+1]]);const a={headers:o,method:t.method};t.method==="GET"||t.method==="HEAD"||(a.body=y.toWeb(t),a.duplex="half");const f=new Request(e.toString(),a),R=T(f)||"127.0.0.1",E=f?.headers?.get("x-forwarded-host")||v(t.socket.remoteAddress);f.context={remoteAddr:{hostname:E,port:t.socket.localPort,ipAddress:R},url:e},s=await n.fetch(f)}catch(e){s=new Response(null,{status:500}),e instanceof Error&&(e.name==="TimeoutError"||e.constructor.name==="TimeoutError"?s=new Response(null,{status:504}):e.code==="ERR_INVALID_URL"&&(s=new Response("Invalid URL",{status:404})),w.error(`Error while handling request: %s
%s`,e.message,e.stack))}const p=t.headers.origin;p&&C.some(e=>p===e)&&(r.setHeader("Access-Control-Allow-Origin",p),r.setHeader("Access-Control-Allow-Credentials","true"));for(const[e,o]of s.headers||[])try{e==="set-cookie"?r.setHeader(e,s.headers.getSetCookie(e)):r.setHeader(e,o)}catch(c){w.error(`Error while setting header: ${c?.message}`)}if(r.setHeader("Vary","Cookie"),r.statusCode=s.status||500,s.body)try{if(O(s)){const e=new k.Transform({transform(o,c,a){if(r.closed||r.destroyed)return a();r.write(o,c)?process.nextTick(a):r.once("drain",a)},flush(o){if(r.closed||r.destroyed)return o();r.end(),o()}});await x(s.body instanceof H?y.fromWeb(s.body):s.body,e)}else{const e=await s.text();r.setHeader("Content-Length",Buffer.byteLength(e)),r.end(e)}}catch(e){console.error(e);const o=e instanceof Error?e:new Error("unknown error",{cause:e});r.destroy(o)}else r.end()})});process.on("SIGTERM",()=>{d.close(()=>{I(0)})}),d.listen(parseInt(String(l),10)).on("listening",()=>{w.logSticky("server",`  \u{1F310} Preview URL: http://127.0.0.1:${l}${L()}`),i(d)}).on("error",m)})}function O(n){const l=n.headers.get("content-type")||"",i=n.headers.get("x-accel-buffering")||"",m=n.headers.get("content-encoding"),d=n.headers.get("content-length"),t=n.headers.get("transfer-encoding");return m||t||d||/^no$/i.test(i)||!/^(text\/(?!event-stream\b))/i.test(l)}export{z as startHttpServer};
