@gjsify/http2 0.3.20 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/esm/_virtual/_rolldown/runtime.js +1 -0
- package/lib/esm/client-session.js +1 -1
- package/lib/esm/index.js +1 -1
- package/lib/esm/protocol.js +1 -1
- package/lib/esm/server.js +3 -3
- package/lib/types/server.d.ts +121 -11
- package/package.json +10 -9
- package/src/http2.gjs.spec.ts +414 -72
- package/src/server.ts +507 -33
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0});export{__name};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{constants as e,getDefaultSettings as t}from"./protocol.js";import n from"@girs/soup-3.0";import r from"@girs/gio-2.0";import i from"@girs/glib-2.0";import{EventEmitter as a}from"node:events";import{Duplex as o}from"node:stream";import{Buffer as s}from"node:buffer";import{readBytesAsync as c}from"@gjsify/utils";var
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{constants as e,getDefaultSettings as t}from"./protocol.js";import n from"@girs/soup-3.0";import r from"@girs/gio-2.0";import i from"@girs/glib-2.0";import{EventEmitter as a}from"node:events";import{Duplex as o}from"node:stream";import{Buffer as s}from"node:buffer";import{readBytesAsync as c}from"@gjsify/utils";var Http2Session=class extends a{type=e.NGHTTP2_SESSION_CLIENT;alpnProtocol=void 0;encrypted=!1;_closed=!1;_destroyed=!1;_settings;constructor(){super(),this._settings=t()}get closed(){return this._closed}get destroyed(){return this._destroyed}get connecting(){return!1}get pendingSettingsAck(){return!1}get localSettings(){return{...this._settings}}get remoteSettings(){return t()}get originSet(){return new Set}settings(e,t){Object.assign(this._settings,e),t&&Promise.resolve().then(t)}goaway(t,n,r){this.emit(`goaway`,t??e.NGHTTP2_NO_ERROR),this.destroy()}ping(e,t){let n=e||new Uint8Array(8);return t&&Promise.resolve().then(()=>t(null,0,n)),!0}close(e){this._closed||(this._closed=!0,this.emit(`close`),e&&e())}destroy(e,t){this._destroyed||(this._destroyed=!0,this._closed=!0,e&&this.emit(`error`,e),t!==void 0&&this.emit(`goaway`,t),this.emit(`close`))}ref(){}unref(){}},ClientHttp2Stream=class extends o{id=1;pending=!1;aborted=!1;bufferSize=0;endAfterHeaders=!1;_session;_requestHeaders;_requestChunks=[];_cancellable;_state=e.NGHTTP2_STREAM_STATE_OPEN;_responseHeaders={};get state(){return this._state}get rstCode(){return e.NGHTTP2_NO_ERROR}get session(){return this._session}get sentHeaders(){return this._requestHeaders}constructor(e,t){super(),this._session=e,this._requestHeaders=t,this._cancellable=new r.Cancellable}_read(e){}_write(e,t,n){let r=s.isBuffer(e)?e:s.from(e,t);this._requestChunks.push(r),n()}_final(e){this._sendRequest().then(()=>e()).catch(t=>e(t instanceof Error?t:Error(String(t))))}async _sendRequest(){let t=this._session._getSoupSession(),r=this._session._getAuthority(),a=this._requestHeaders[`:method`]||`GET`,o=this._requestHeaders[`:path`]||`/`,l=`${this._requestHeaders[`:scheme`]||(r.startsWith(`https`)?`https`:`http`)}://${this._requestHeaders[`:authority`]||r.replace(/^https?:\/\//,``)}${o}`,u;try{u=i.Uri.parse(l,i.UriFlags.NONE)}catch{throw Error(`Invalid HTTP/2 request URL: ${l}`)}let d=new n.Message({method:a,uri:u}),f=d.get_request_headers();for(let[e,t]of Object.entries(this._requestHeaders))if(!e.startsWith(`:`))if(Array.isArray(t))for(let n of t)f.append(e,n);else f.replace(e,t);let p=s.concat(this._requestChunks);if(p.length>0){let e=this._requestHeaders[`content-type`]||`application/octet-stream`;d.set_request_body_from_bytes(e,new i.Bytes(p))}try{let n=await new Promise((e,n)=>{t.send_async(d,i.PRIORITY_DEFAULT,this._cancellable,(r,i)=>{try{e(t.send_finish(i))}catch(e){n(e)}})}),r=d.status_code,a=d.get_response_headers(),o={":status":String(r)};a.foreach((e,t)=>{let n=e.toLowerCase();if(n in o){let e=o[n];Array.isArray(e)?e.push(t):o[n]=[e,t]}else o[n]=t}),this._responseHeaders=o,this._state=e.NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL,this.emit(`response`,o,0);try{let e;for(;(e=await c(n,16384,i.PRIORITY_DEFAULT,this._cancellable))!==null;)e.length>0&&this.push(s.from(e))}catch{}this.push(null),this._state=e.NGHTTP2_STREAM_STATE_CLOSED}catch(t){this._state=e.NGHTTP2_STREAM_STATE_CLOSED,this._cancellable.is_cancelled()||this.destroy(t instanceof Error?t:Error(String(t)))}}close(t,n){this._cancellable.cancel(),this._state=e.NGHTTP2_STREAM_STATE_CLOSED,this.emit(`close`,t??e.NGHTTP2_NO_ERROR),n&&n()}priority(e){}sendTrailers(e){}setTimeout(e,t){return this}},ClientHttp2Session=class extends Http2Session{type=e.NGHTTP2_SESSION_CLIENT;_authority;_soupSession;_streams=new Set;constructor(e,t={}){super(),this._authority=e,this.encrypted=e.startsWith(`https:`),this._soupSession=new n.Session,t.rejectUnauthorized===!1&&this._soupSession.connect(`accept-certificate`,(e,t,n)=>!0),Promise.resolve().then(()=>{this.destroyed||(this.alpnProtocol=this.encrypted?`h2`:void 0,this.emit(`connect`,this,null))})}_getSoupSession(){return this._soupSession}_getAuthority(){return this._authority}request(e,t){if(this.destroyed||this.closed)throw Error(`Session is closed`);let n={...e};n[`:scheme`]||=this.encrypted?`https`:`http`,n[`:authority`]||=this._authority.replace(/^https?:\/\//,``),n[`:method`]||=`GET`,n[`:path`]||=`/`;let r=new ClientHttp2Stream(this,n);return this._streams.add(r),r.once(`close`,()=>this._streams.delete(r)),t?.endStream&&r.end(),r}close(e){for(let e of this._streams)e.close();this._streams.clear(),super.close(e)}destroy(e,t){for(let e of this._streams)e.close();this._streams.clear(),super.destroy(e,t)}};export{ClientHttp2Session,ClientHttp2Stream,Http2Session};
|
package/lib/esm/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{constants as e,getDefaultSettings as t,getPackedSettings as n,getUnpackedSettings as r}from"./protocol.js";import{ClientHttp2Session as i,ClientHttp2Stream as a,Http2Session as o}from"./client-session.js";import{Http2SecureServer as s,Http2Server as c,Http2ServerRequest as l,Http2ServerResponse as u,ServerHttp2Session as d,ServerHttp2Stream as f}from"./server.js";function
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{constants as e,getDefaultSettings as t,getPackedSettings as n,getUnpackedSettings as r}from"./protocol.js";import{ClientHttp2Session as i,ClientHttp2Stream as a,Http2Session as o}from"./client-session.js";import{Http2SecureServer as s,Http2Server as c,Http2ServerRequest as l,Http2ServerResponse as u,ServerHttp2Session as d,ServerHttp2Stream as f}from"./server.js";function createServer(e,t){return new c(e,t)}function createSecureServer(e,t){return new s(e,t)}function connect(e,t,n){let r=typeof e==`string`?e:e.toString();typeof t==`function`&&(n=t,t={});let a=new i(r,t??{});return n&&a.once(`connect`,n),a}const p=Symbol.for(`nodejs.http2.sensitiveHeaders`);function performServerHandshake(e){throw Error(`http2.performServerHandshake() is not yet implemented in GJS`)}var m={constants:e,createServer,createSecureServer,connect,getDefaultSettings:t,getPackedSettings:n,getUnpackedSettings:r,sensitiveHeaders:p,performServerHandshake,Http2Session:o,Http2Server:c,Http2SecureServer:s,Http2ServerRequest:l,Http2ServerResponse:u,ServerHttp2Session:d,ServerHttp2Stream:f,ClientHttp2Session:i,ClientHttp2Stream:a};export{i as ClientHttp2Session,a as ClientHttp2Stream,s as Http2SecureServer,c as Http2Server,l as Http2ServerRequest,u as Http2ServerResponse,o as Http2Session,d as ServerHttp2Session,f as ServerHttp2Stream,connect,e as constants,createSecureServer,createServer,m as default,t as getDefaultSettings,n as getPackedSettings,r as getUnpackedSettings,performServerHandshake,p as sensitiveHeaders};
|
package/lib/esm/protocol.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e={NGHTTP2_NO_ERROR:0,NGHTTP2_PROTOCOL_ERROR:1,NGHTTP2_INTERNAL_ERROR:2,NGHTTP2_FLOW_CONTROL_ERROR:3,NGHTTP2_SETTINGS_TIMEOUT:4,NGHTTP2_STREAM_CLOSED:5,NGHTTP2_FRAME_SIZE_ERROR:6,NGHTTP2_REFUSED_STREAM:7,NGHTTP2_CANCEL:8,NGHTTP2_COMPRESSION_ERROR:9,NGHTTP2_CONNECT_ERROR:10,NGHTTP2_ENHANCE_YOUR_CALM:11,NGHTTP2_INADEQUATE_SECURITY:12,NGHTTP2_HTTP_1_1_REQUIRED:13,NGHTTP2_ERR_FRAME_SIZE_ERROR:-522,NGHTTP2_ERR_DEFERRED:-508,NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:-509,NGHTTP2_ERR_INVALID_ARGUMENT:-501,NGHTTP2_ERR_STREAM_CLOSED:-510,NGHTTP2_ERR_NOMEM:-901,NGHTTP2_SESSION_SERVER:0,NGHTTP2_SESSION_CLIENT:1,NGHTTP2_STREAM_STATE_IDLE:1,NGHTTP2_STREAM_STATE_OPEN:2,NGHTTP2_STREAM_STATE_RESERVED_LOCAL:3,NGHTTP2_STREAM_STATE_RESERVED_REMOTE:4,NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL:5,NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE:6,NGHTTP2_STREAM_STATE_CLOSED:7,NGHTTP2_FLAG_NONE:0,NGHTTP2_FLAG_END_STREAM:1,NGHTTP2_FLAG_END_HEADERS:4,NGHTTP2_FLAG_ACK:1,NGHTTP2_FLAG_PADDED:8,NGHTTP2_FLAG_PRIORITY:32,NGHTTP2_HCAT_REQUEST:0,NGHTTP2_HCAT_RESPONSE:1,NGHTTP2_HCAT_PUSH_RESPONSE:2,NGHTTP2_HCAT_HEADERS:3,NGHTTP2_NV_FLAG_NONE:0,NGHTTP2_NV_FLAG_NO_INDEX:1,NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:1,NGHTTP2_SETTINGS_ENABLE_PUSH:2,NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:3,NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:4,NGHTTP2_SETTINGS_MAX_FRAME_SIZE:5,NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:6,NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:8,DEFAULT_SETTINGS_HEADER_TABLE_SIZE:4096,DEFAULT_SETTINGS_ENABLE_PUSH:1,DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS:4294967295,DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE:65535,DEFAULT_SETTINGS_MAX_FRAME_SIZE:16384,DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE:65535,DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL:0,MAX_MAX_FRAME_SIZE:16777215,MIN_MAX_FRAME_SIZE:16384,MAX_INITIAL_WINDOW_SIZE:2147483647,NGHTTP2_DEFAULT_WEIGHT:16,PADDING_STRATEGY_NONE:0,PADDING_STRATEGY_ALIGNED:1,PADDING_STRATEGY_MAX:2,PADDING_STRATEGY_CALLBACK:1,HTTP2_HEADER_STATUS:`:status`,HTTP2_HEADER_METHOD:`:method`,HTTP2_HEADER_AUTHORITY:`:authority`,HTTP2_HEADER_SCHEME:`:scheme`,HTTP2_HEADER_PATH:`:path`,HTTP2_HEADER_PROTOCOL:`:protocol`,HTTP2_HEADER_ACCEPT:`accept`,HTTP2_HEADER_ACCEPT_CHARSET:`accept-charset`,HTTP2_HEADER_ACCEPT_ENCODING:`accept-encoding`,HTTP2_HEADER_ACCEPT_LANGUAGE:`accept-language`,HTTP2_HEADER_ACCEPT_RANGES:`accept-ranges`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS:`access-control-allow-credentials`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS:`access-control-allow-headers`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS:`access-control-allow-methods`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN:`access-control-allow-origin`,HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS:`access-control-expose-headers`,HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE:`access-control-max-age`,HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS:`access-control-request-headers`,HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD:`access-control-request-method`,HTTP2_HEADER_AGE:`age`,HTTP2_HEADER_ALLOW:`allow`,HTTP2_HEADER_ALT_SVC:`alt-svc`,HTTP2_HEADER_AUTHORIZATION:`authorization`,HTTP2_HEADER_CACHE_CONTROL:`cache-control`,HTTP2_HEADER_CONNECTION:`connection`,HTTP2_HEADER_CONTENT_DISPOSITION:`content-disposition`,HTTP2_HEADER_CONTENT_ENCODING:`content-encoding`,HTTP2_HEADER_CONTENT_LANGUAGE:`content-language`,HTTP2_HEADER_CONTENT_LENGTH:`content-length`,HTTP2_HEADER_CONTENT_LOCATION:`content-location`,HTTP2_HEADER_CONTENT_MD5:`content-md5`,HTTP2_HEADER_CONTENT_RANGE:`content-range`,HTTP2_HEADER_CONTENT_SECURITY_POLICY:`content-security-policy`,HTTP2_HEADER_CONTENT_TYPE:`content-type`,HTTP2_HEADER_COOKIE:`cookie`,HTTP2_HEADER_DATE:`date`,HTTP2_HEADER_DNT:`dnt`,HTTP2_HEADER_EARLY_DATA:`early-data`,HTTP2_HEADER_ETAG:`etag`,HTTP2_HEADER_EXPECT:`expect`,HTTP2_HEADER_EXPECT_CT:`expect-ct`,HTTP2_HEADER_EXPIRES:`expires`,HTTP2_HEADER_FORWARDED:`forwarded`,HTTP2_HEADER_FROM:`from`,HTTP2_HEADER_HOST:`host`,HTTP2_HEADER_HTTP2_SETTINGS:`http2-settings`,HTTP2_HEADER_IF_MATCH:`if-match`,HTTP2_HEADER_IF_MODIFIED_SINCE:`if-modified-since`,HTTP2_HEADER_IF_NONE_MATCH:`if-none-match`,HTTP2_HEADER_IF_RANGE:`if-range`,HTTP2_HEADER_IF_UNMODIFIED_SINCE:`if-unmodified-since`,HTTP2_HEADER_KEEP_ALIVE:`keep-alive`,HTTP2_HEADER_LAST_MODIFIED:`last-modified`,HTTP2_HEADER_LINK:`link`,HTTP2_HEADER_LOCATION:`location`,HTTP2_HEADER_MAX_FORWARDS:`max-forwards`,HTTP2_HEADER_ORIGIN:`origin`,HTTP2_HEADER_PREFER:`prefer`,HTTP2_HEADER_PRIORITY:`priority`,HTTP2_HEADER_PROXY_AUTHENTICATE:`proxy-authenticate`,HTTP2_HEADER_PROXY_AUTHORIZATION:`proxy-authorization`,HTTP2_HEADER_PROXY_CONNECTION:`proxy-connection`,HTTP2_HEADER_RANGE:`range`,HTTP2_HEADER_REFERER:`referer`,HTTP2_HEADER_REFRESH:`refresh`,HTTP2_HEADER_RETRY_AFTER:`retry-after`,HTTP2_HEADER_SERVER:`server`,HTTP2_HEADER_SET_COOKIE:`set-cookie`,HTTP2_HEADER_STRICT_TRANSPORT_SECURITY:`strict-transport-security`,HTTP2_HEADER_TE:`te`,HTTP2_HEADER_TIMING_ALLOW_ORIGIN:`timing-allow-origin`,HTTP2_HEADER_TRAILER:`trailer`,HTTP2_HEADER_TRANSFER_ENCODING:`transfer-encoding`,HTTP2_HEADER_TK:`tk`,HTTP2_HEADER_UPGRADE:`upgrade`,HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS:`upgrade-insecure-requests`,HTTP2_HEADER_USER_AGENT:`user-agent`,HTTP2_HEADER_VARY:`vary`,HTTP2_HEADER_VIA:`via`,HTTP2_HEADER_WARNING:`warning`,HTTP2_HEADER_WWW_AUTHENTICATE:`www-authenticate`,HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS:`x-content-type-options`,HTTP2_HEADER_X_FORWARDED_FOR:`x-forwarded-for`,HTTP2_HEADER_X_FRAME_OPTIONS:`x-frame-options`,HTTP2_HEADER_X_XSS_PROTECTION:`x-xss-protection`,HTTP2_HEADER_PURPOSE:`purpose`,HTTP2_METHOD_ACL:`ACL`,HTTP2_METHOD_BASELINE_CONTROL:`BASELINE-CONTROL`,HTTP2_METHOD_BIND:`BIND`,HTTP2_METHOD_CHECKIN:`CHECKIN`,HTTP2_METHOD_CHECKOUT:`CHECKOUT`,HTTP2_METHOD_CONNECT:`CONNECT`,HTTP2_METHOD_COPY:`COPY`,HTTP2_METHOD_DELETE:`DELETE`,HTTP2_METHOD_GET:`GET`,HTTP2_METHOD_HEAD:`HEAD`,HTTP2_METHOD_LABEL:`LABEL`,HTTP2_METHOD_LINK:`LINK`,HTTP2_METHOD_LOCK:`LOCK`,HTTP2_METHOD_MERGE:`MERGE`,HTTP2_METHOD_MKACTIVITY:`MKACTIVITY`,HTTP2_METHOD_MKCALENDAR:`MKCALENDAR`,HTTP2_METHOD_MKCOL:`MKCOL`,HTTP2_METHOD_MKREDIRECTREF:`MKREDIRECTREF`,HTTP2_METHOD_MKWORKSPACE:`MKWORKSPACE`,HTTP2_METHOD_MOVE:`MOVE`,HTTP2_METHOD_OPTIONS:`OPTIONS`,HTTP2_METHOD_ORDERPATCH:`ORDERPATCH`,HTTP2_METHOD_PATCH:`PATCH`,HTTP2_METHOD_POST:`POST`,HTTP2_METHOD_PRI:`PRI`,HTTP2_METHOD_PROPFIND:`PROPFIND`,HTTP2_METHOD_PROPPATCH:`PROPPATCH`,HTTP2_METHOD_PUT:`PUT`,HTTP2_METHOD_REBIND:`REBIND`,HTTP2_METHOD_REPORT:`REPORT`,HTTP2_METHOD_SEARCH:`SEARCH`,HTTP2_METHOD_TRACE:`TRACE`,HTTP2_METHOD_UNBIND:`UNBIND`,HTTP2_METHOD_UNCHECKOUT:`UNCHECKOUT`,HTTP2_METHOD_UNLINK:`UNLINK`,HTTP2_METHOD_UNLOCK:`UNLOCK`,HTTP2_METHOD_UPDATE:`UPDATE`,HTTP2_METHOD_UPDATEREDIRECTREF:`UPDATEREDIRECTREF`,HTTP2_METHOD_VERSION_CONTROL:`VERSION-CONTROL`,HTTP_STATUS_CONTINUE:100,HTTP_STATUS_SWITCHING_PROTOCOLS:101,HTTP_STATUS_PROCESSING:102,HTTP_STATUS_EARLY_HINTS:103,HTTP_STATUS_OK:200,HTTP_STATUS_CREATED:201,HTTP_STATUS_ACCEPTED:202,HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION:203,HTTP_STATUS_NO_CONTENT:204,HTTP_STATUS_RESET_CONTENT:205,HTTP_STATUS_PARTIAL_CONTENT:206,HTTP_STATUS_MULTI_STATUS:207,HTTP_STATUS_ALREADY_REPORTED:208,HTTP_STATUS_IM_USED:226,HTTP_STATUS_MULTIPLE_CHOICES:300,HTTP_STATUS_MOVED_PERMANENTLY:301,HTTP_STATUS_FOUND:302,HTTP_STATUS_SEE_OTHER:303,HTTP_STATUS_NOT_MODIFIED:304,HTTP_STATUS_USE_PROXY:305,HTTP_STATUS_TEMPORARY_REDIRECT:307,HTTP_STATUS_PERMANENT_REDIRECT:308,HTTP_STATUS_BAD_REQUEST:400,HTTP_STATUS_UNAUTHORIZED:401,HTTP_STATUS_PAYMENT_REQUIRED:402,HTTP_STATUS_FORBIDDEN:403,HTTP_STATUS_NOT_FOUND:404,HTTP_STATUS_METHOD_NOT_ALLOWED:405,HTTP_STATUS_NOT_ACCEPTABLE:406,HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED:407,HTTP_STATUS_REQUEST_TIMEOUT:408,HTTP_STATUS_CONFLICT:409,HTTP_STATUS_GONE:410,HTTP_STATUS_LENGTH_REQUIRED:411,HTTP_STATUS_PRECONDITION_FAILED:412,HTTP_STATUS_PAYLOAD_TOO_LARGE:413,HTTP_STATUS_URI_TOO_LONG:414,HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:415,HTTP_STATUS_RANGE_NOT_SATISFIABLE:416,HTTP_STATUS_EXPECTATION_FAILED:417,HTTP_STATUS_TEAPOT:418,HTTP_STATUS_MISDIRECTED_REQUEST:421,HTTP_STATUS_UNPROCESSABLE_ENTITY:422,HTTP_STATUS_LOCKED:423,HTTP_STATUS_FAILED_DEPENDENCY:424,HTTP_STATUS_TOO_EARLY:425,HTTP_STATUS_UPGRADE_REQUIRED:426,HTTP_STATUS_PRECONDITION_REQUIRED:428,HTTP_STATUS_TOO_MANY_REQUESTS:429,HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE:431,HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_STATUS_INTERNAL_SERVER_ERROR:500,HTTP_STATUS_NOT_IMPLEMENTED:501,HTTP_STATUS_BAD_GATEWAY:502,HTTP_STATUS_SERVICE_UNAVAILABLE:503,HTTP_STATUS_GATEWAY_TIMEOUT:504,HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED:505,HTTP_STATUS_VARIANT_ALSO_NEGOTIATES:506,HTTP_STATUS_INSUFFICIENT_STORAGE:507,HTTP_STATUS_LOOP_DETECTED:508,HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED:509,HTTP_STATUS_NOT_EXTENDED:510,HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED:511},t=[[1,`headerTableSize`,!1],[2,`enablePush`,!0],[3,`maxConcurrentStreams`,!1],[4,`initialWindowSize`,!1],[5,`maxFrameSize`,!1],[6,`maxHeaderListSize`,!1],[8,`enableConnectProtocol`,!0]];function
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";const e={NGHTTP2_NO_ERROR:0,NGHTTP2_PROTOCOL_ERROR:1,NGHTTP2_INTERNAL_ERROR:2,NGHTTP2_FLOW_CONTROL_ERROR:3,NGHTTP2_SETTINGS_TIMEOUT:4,NGHTTP2_STREAM_CLOSED:5,NGHTTP2_FRAME_SIZE_ERROR:6,NGHTTP2_REFUSED_STREAM:7,NGHTTP2_CANCEL:8,NGHTTP2_COMPRESSION_ERROR:9,NGHTTP2_CONNECT_ERROR:10,NGHTTP2_ENHANCE_YOUR_CALM:11,NGHTTP2_INADEQUATE_SECURITY:12,NGHTTP2_HTTP_1_1_REQUIRED:13,NGHTTP2_ERR_FRAME_SIZE_ERROR:-522,NGHTTP2_ERR_DEFERRED:-508,NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:-509,NGHTTP2_ERR_INVALID_ARGUMENT:-501,NGHTTP2_ERR_STREAM_CLOSED:-510,NGHTTP2_ERR_NOMEM:-901,NGHTTP2_SESSION_SERVER:0,NGHTTP2_SESSION_CLIENT:1,NGHTTP2_STREAM_STATE_IDLE:1,NGHTTP2_STREAM_STATE_OPEN:2,NGHTTP2_STREAM_STATE_RESERVED_LOCAL:3,NGHTTP2_STREAM_STATE_RESERVED_REMOTE:4,NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL:5,NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE:6,NGHTTP2_STREAM_STATE_CLOSED:7,NGHTTP2_FLAG_NONE:0,NGHTTP2_FLAG_END_STREAM:1,NGHTTP2_FLAG_END_HEADERS:4,NGHTTP2_FLAG_ACK:1,NGHTTP2_FLAG_PADDED:8,NGHTTP2_FLAG_PRIORITY:32,NGHTTP2_HCAT_REQUEST:0,NGHTTP2_HCAT_RESPONSE:1,NGHTTP2_HCAT_PUSH_RESPONSE:2,NGHTTP2_HCAT_HEADERS:3,NGHTTP2_NV_FLAG_NONE:0,NGHTTP2_NV_FLAG_NO_INDEX:1,NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:1,NGHTTP2_SETTINGS_ENABLE_PUSH:2,NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:3,NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:4,NGHTTP2_SETTINGS_MAX_FRAME_SIZE:5,NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:6,NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL:8,DEFAULT_SETTINGS_HEADER_TABLE_SIZE:4096,DEFAULT_SETTINGS_ENABLE_PUSH:1,DEFAULT_SETTINGS_MAX_CONCURRENT_STREAMS:4294967295,DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE:65535,DEFAULT_SETTINGS_MAX_FRAME_SIZE:16384,DEFAULT_SETTINGS_MAX_HEADER_LIST_SIZE:65535,DEFAULT_SETTINGS_ENABLE_CONNECT_PROTOCOL:0,MAX_MAX_FRAME_SIZE:16777215,MIN_MAX_FRAME_SIZE:16384,MAX_INITIAL_WINDOW_SIZE:2147483647,NGHTTP2_DEFAULT_WEIGHT:16,PADDING_STRATEGY_NONE:0,PADDING_STRATEGY_ALIGNED:1,PADDING_STRATEGY_MAX:2,PADDING_STRATEGY_CALLBACK:1,HTTP2_HEADER_STATUS:`:status`,HTTP2_HEADER_METHOD:`:method`,HTTP2_HEADER_AUTHORITY:`:authority`,HTTP2_HEADER_SCHEME:`:scheme`,HTTP2_HEADER_PATH:`:path`,HTTP2_HEADER_PROTOCOL:`:protocol`,HTTP2_HEADER_ACCEPT:`accept`,HTTP2_HEADER_ACCEPT_CHARSET:`accept-charset`,HTTP2_HEADER_ACCEPT_ENCODING:`accept-encoding`,HTTP2_HEADER_ACCEPT_LANGUAGE:`accept-language`,HTTP2_HEADER_ACCEPT_RANGES:`accept-ranges`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_CREDENTIALS:`access-control-allow-credentials`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS:`access-control-allow-headers`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS:`access-control-allow-methods`,HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN:`access-control-allow-origin`,HTTP2_HEADER_ACCESS_CONTROL_EXPOSE_HEADERS:`access-control-expose-headers`,HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE:`access-control-max-age`,HTTP2_HEADER_ACCESS_CONTROL_REQUEST_HEADERS:`access-control-request-headers`,HTTP2_HEADER_ACCESS_CONTROL_REQUEST_METHOD:`access-control-request-method`,HTTP2_HEADER_AGE:`age`,HTTP2_HEADER_ALLOW:`allow`,HTTP2_HEADER_ALT_SVC:`alt-svc`,HTTP2_HEADER_AUTHORIZATION:`authorization`,HTTP2_HEADER_CACHE_CONTROL:`cache-control`,HTTP2_HEADER_CONNECTION:`connection`,HTTP2_HEADER_CONTENT_DISPOSITION:`content-disposition`,HTTP2_HEADER_CONTENT_ENCODING:`content-encoding`,HTTP2_HEADER_CONTENT_LANGUAGE:`content-language`,HTTP2_HEADER_CONTENT_LENGTH:`content-length`,HTTP2_HEADER_CONTENT_LOCATION:`content-location`,HTTP2_HEADER_CONTENT_MD5:`content-md5`,HTTP2_HEADER_CONTENT_RANGE:`content-range`,HTTP2_HEADER_CONTENT_SECURITY_POLICY:`content-security-policy`,HTTP2_HEADER_CONTENT_TYPE:`content-type`,HTTP2_HEADER_COOKIE:`cookie`,HTTP2_HEADER_DATE:`date`,HTTP2_HEADER_DNT:`dnt`,HTTP2_HEADER_EARLY_DATA:`early-data`,HTTP2_HEADER_ETAG:`etag`,HTTP2_HEADER_EXPECT:`expect`,HTTP2_HEADER_EXPECT_CT:`expect-ct`,HTTP2_HEADER_EXPIRES:`expires`,HTTP2_HEADER_FORWARDED:`forwarded`,HTTP2_HEADER_FROM:`from`,HTTP2_HEADER_HOST:`host`,HTTP2_HEADER_HTTP2_SETTINGS:`http2-settings`,HTTP2_HEADER_IF_MATCH:`if-match`,HTTP2_HEADER_IF_MODIFIED_SINCE:`if-modified-since`,HTTP2_HEADER_IF_NONE_MATCH:`if-none-match`,HTTP2_HEADER_IF_RANGE:`if-range`,HTTP2_HEADER_IF_UNMODIFIED_SINCE:`if-unmodified-since`,HTTP2_HEADER_KEEP_ALIVE:`keep-alive`,HTTP2_HEADER_LAST_MODIFIED:`last-modified`,HTTP2_HEADER_LINK:`link`,HTTP2_HEADER_LOCATION:`location`,HTTP2_HEADER_MAX_FORWARDS:`max-forwards`,HTTP2_HEADER_ORIGIN:`origin`,HTTP2_HEADER_PREFER:`prefer`,HTTP2_HEADER_PRIORITY:`priority`,HTTP2_HEADER_PROXY_AUTHENTICATE:`proxy-authenticate`,HTTP2_HEADER_PROXY_AUTHORIZATION:`proxy-authorization`,HTTP2_HEADER_PROXY_CONNECTION:`proxy-connection`,HTTP2_HEADER_RANGE:`range`,HTTP2_HEADER_REFERER:`referer`,HTTP2_HEADER_REFRESH:`refresh`,HTTP2_HEADER_RETRY_AFTER:`retry-after`,HTTP2_HEADER_SERVER:`server`,HTTP2_HEADER_SET_COOKIE:`set-cookie`,HTTP2_HEADER_STRICT_TRANSPORT_SECURITY:`strict-transport-security`,HTTP2_HEADER_TE:`te`,HTTP2_HEADER_TIMING_ALLOW_ORIGIN:`timing-allow-origin`,HTTP2_HEADER_TRAILER:`trailer`,HTTP2_HEADER_TRANSFER_ENCODING:`transfer-encoding`,HTTP2_HEADER_TK:`tk`,HTTP2_HEADER_UPGRADE:`upgrade`,HTTP2_HEADER_UPGRADE_INSECURE_REQUESTS:`upgrade-insecure-requests`,HTTP2_HEADER_USER_AGENT:`user-agent`,HTTP2_HEADER_VARY:`vary`,HTTP2_HEADER_VIA:`via`,HTTP2_HEADER_WARNING:`warning`,HTTP2_HEADER_WWW_AUTHENTICATE:`www-authenticate`,HTTP2_HEADER_X_CONTENT_TYPE_OPTIONS:`x-content-type-options`,HTTP2_HEADER_X_FORWARDED_FOR:`x-forwarded-for`,HTTP2_HEADER_X_FRAME_OPTIONS:`x-frame-options`,HTTP2_HEADER_X_XSS_PROTECTION:`x-xss-protection`,HTTP2_HEADER_PURPOSE:`purpose`,HTTP2_METHOD_ACL:`ACL`,HTTP2_METHOD_BASELINE_CONTROL:`BASELINE-CONTROL`,HTTP2_METHOD_BIND:`BIND`,HTTP2_METHOD_CHECKIN:`CHECKIN`,HTTP2_METHOD_CHECKOUT:`CHECKOUT`,HTTP2_METHOD_CONNECT:`CONNECT`,HTTP2_METHOD_COPY:`COPY`,HTTP2_METHOD_DELETE:`DELETE`,HTTP2_METHOD_GET:`GET`,HTTP2_METHOD_HEAD:`HEAD`,HTTP2_METHOD_LABEL:`LABEL`,HTTP2_METHOD_LINK:`LINK`,HTTP2_METHOD_LOCK:`LOCK`,HTTP2_METHOD_MERGE:`MERGE`,HTTP2_METHOD_MKACTIVITY:`MKACTIVITY`,HTTP2_METHOD_MKCALENDAR:`MKCALENDAR`,HTTP2_METHOD_MKCOL:`MKCOL`,HTTP2_METHOD_MKREDIRECTREF:`MKREDIRECTREF`,HTTP2_METHOD_MKWORKSPACE:`MKWORKSPACE`,HTTP2_METHOD_MOVE:`MOVE`,HTTP2_METHOD_OPTIONS:`OPTIONS`,HTTP2_METHOD_ORDERPATCH:`ORDERPATCH`,HTTP2_METHOD_PATCH:`PATCH`,HTTP2_METHOD_POST:`POST`,HTTP2_METHOD_PRI:`PRI`,HTTP2_METHOD_PROPFIND:`PROPFIND`,HTTP2_METHOD_PROPPATCH:`PROPPATCH`,HTTP2_METHOD_PUT:`PUT`,HTTP2_METHOD_REBIND:`REBIND`,HTTP2_METHOD_REPORT:`REPORT`,HTTP2_METHOD_SEARCH:`SEARCH`,HTTP2_METHOD_TRACE:`TRACE`,HTTP2_METHOD_UNBIND:`UNBIND`,HTTP2_METHOD_UNCHECKOUT:`UNCHECKOUT`,HTTP2_METHOD_UNLINK:`UNLINK`,HTTP2_METHOD_UNLOCK:`UNLOCK`,HTTP2_METHOD_UPDATE:`UPDATE`,HTTP2_METHOD_UPDATEREDIRECTREF:`UPDATEREDIRECTREF`,HTTP2_METHOD_VERSION_CONTROL:`VERSION-CONTROL`,HTTP_STATUS_CONTINUE:100,HTTP_STATUS_SWITCHING_PROTOCOLS:101,HTTP_STATUS_PROCESSING:102,HTTP_STATUS_EARLY_HINTS:103,HTTP_STATUS_OK:200,HTTP_STATUS_CREATED:201,HTTP_STATUS_ACCEPTED:202,HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION:203,HTTP_STATUS_NO_CONTENT:204,HTTP_STATUS_RESET_CONTENT:205,HTTP_STATUS_PARTIAL_CONTENT:206,HTTP_STATUS_MULTI_STATUS:207,HTTP_STATUS_ALREADY_REPORTED:208,HTTP_STATUS_IM_USED:226,HTTP_STATUS_MULTIPLE_CHOICES:300,HTTP_STATUS_MOVED_PERMANENTLY:301,HTTP_STATUS_FOUND:302,HTTP_STATUS_SEE_OTHER:303,HTTP_STATUS_NOT_MODIFIED:304,HTTP_STATUS_USE_PROXY:305,HTTP_STATUS_TEMPORARY_REDIRECT:307,HTTP_STATUS_PERMANENT_REDIRECT:308,HTTP_STATUS_BAD_REQUEST:400,HTTP_STATUS_UNAUTHORIZED:401,HTTP_STATUS_PAYMENT_REQUIRED:402,HTTP_STATUS_FORBIDDEN:403,HTTP_STATUS_NOT_FOUND:404,HTTP_STATUS_METHOD_NOT_ALLOWED:405,HTTP_STATUS_NOT_ACCEPTABLE:406,HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED:407,HTTP_STATUS_REQUEST_TIMEOUT:408,HTTP_STATUS_CONFLICT:409,HTTP_STATUS_GONE:410,HTTP_STATUS_LENGTH_REQUIRED:411,HTTP_STATUS_PRECONDITION_FAILED:412,HTTP_STATUS_PAYLOAD_TOO_LARGE:413,HTTP_STATUS_URI_TOO_LONG:414,HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:415,HTTP_STATUS_RANGE_NOT_SATISFIABLE:416,HTTP_STATUS_EXPECTATION_FAILED:417,HTTP_STATUS_TEAPOT:418,HTTP_STATUS_MISDIRECTED_REQUEST:421,HTTP_STATUS_UNPROCESSABLE_ENTITY:422,HTTP_STATUS_LOCKED:423,HTTP_STATUS_FAILED_DEPENDENCY:424,HTTP_STATUS_TOO_EARLY:425,HTTP_STATUS_UPGRADE_REQUIRED:426,HTTP_STATUS_PRECONDITION_REQUIRED:428,HTTP_STATUS_TOO_MANY_REQUESTS:429,HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE:431,HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS:451,HTTP_STATUS_INTERNAL_SERVER_ERROR:500,HTTP_STATUS_NOT_IMPLEMENTED:501,HTTP_STATUS_BAD_GATEWAY:502,HTTP_STATUS_SERVICE_UNAVAILABLE:503,HTTP_STATUS_GATEWAY_TIMEOUT:504,HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED:505,HTTP_STATUS_VARIANT_ALSO_NEGOTIATES:506,HTTP_STATUS_INSUFFICIENT_STORAGE:507,HTTP_STATUS_LOOP_DETECTED:508,HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED:509,HTTP_STATUS_NOT_EXTENDED:510,HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED:511},t=[[1,`headerTableSize`,!1],[2,`enablePush`,!0],[3,`maxConcurrentStreams`,!1],[4,`initialWindowSize`,!1],[5,`maxFrameSize`,!1],[6,`maxHeaderListSize`,!1],[8,`enableConnectProtocol`,!0]];function getDefaultSettings(){return{headerTableSize:4096,enablePush:!0,maxConcurrentStreams:4294967295,initialWindowSize:65535,maxFrameSize:16384,maxHeaderListSize:65535,enableConnectProtocol:!1}}function getPackedSettings(e){if(!e)return new Uint8Array;let n=[];for(let[r,i,a]of t){let t=e[i];t!==void 0&&n.push([r,a?+!!t:t])}let r=new Uint8Array(n.length*6),i=new DataView(r.buffer);for(let e=0;e<n.length;e++){let t=e*6;i.setUint16(t,n[e][0],!1),i.setUint32(t+2,n[e][1],!1)}return r}function getUnpackedSettings(e){let n=e instanceof ArrayBuffer?new Uint8Array(e):e;if(n.byteLength%6!=0)throw RangeError(`Invalid packed settings length`);let r={},i=new DataView(n.buffer,n.byteOffset,n.byteLength);for(let e=0;e<n.byteLength;e+=6){let n=i.getUint16(e,!1),a=i.getUint32(e+2,!1);for(let[e,i,o]of t)if(n===e){r[i]=o?a!==0:a;break}}return r}export{e as constants,getDefaultSettings,getPackedSettings,getUnpackedSettings};
|
package/lib/esm/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{constants as e,getDefaultSettings as t}from"./protocol.js";import n from"@girs/soup-3.0";import r from"@girs/gio-2.0";import i from"@girs/glib-2.0";import{EventEmitter as a}from"node:events";import{Readable as o,Writable as s}from"node:stream";import{Buffer as c}from"node:buffer";import{deferEmit as l,ensureMainLoop as u}from"@gjsify/utils";var d=class extends o{method=`GET`;url=`/`;headers={};rawHeaders=[];authority=``;scheme=`https`;httpVersion=`2.0`;httpVersionMajor=2;httpVersionMinor=0;complete=!1;socket=null;trailers={};rawTrailers=[];_stream=null;_timeoutTimer=null;get stream(){return this._stream}_setStream(e){this._stream=e}constructor(){super()}_read(e){}_autoClose(){}_pushBody(e){e&&e.length>0&&this.push(c.from(e)),this.push(null),this.complete=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null)}setTimeout(e,t){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),t&&this.once(`timeout`,t),e>0&&(this._timeoutTimer=setTimeout(()=>{this._timeoutTimer=null,this.emit(`timeout`)},e)),this}destroy(e){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),super.destroy(e)}},f=class extends s{statusCode=200;statusMessage=``;headersSent=!1;finished=!1;sendDate=!0;_soupMsg;_headers=new Map;_streaming=!1;_timeoutTimer=null;_stream=null;get stream(){return this._stream}get socket(){return null}_setStream(e){this._stream=e}constructor(e){super(),this._soupMsg=e}setHeader(e,t){return this._headers.set(e.toLowerCase(),typeof t==`number`?String(t):t),this}getHeader(e){return this._headers.get(e.toLowerCase())}removeHeader(e){this._headers.delete(e.toLowerCase())}hasHeader(e){return this._headers.has(e.toLowerCase())}getHeaderNames(){return Array.from(this._headers.keys())}getHeaders(){let e={};for(let[t,n]of this._headers)e[t]=n;return e}appendHeader(e,t){let n=e.toLowerCase(),r=this._headers.get(n);return r===void 0?this._headers.set(n,t):Array.isArray(r)?Array.isArray(t)?r.push(...t):r.push(t):this._headers.set(n,Array.isArray(t)?[r,...t]:[r,t]),this}flushHeaders(){this.headersSent||=!0}writeHead(e,t,n){if(this.statusCode=e,typeof t==`object`&&(n=t,t=void 0),typeof t==`string`&&(this.statusMessage=t),n)for(let[e,t]of Object.entries(n))this.setHeader(e,t);return this}respond(e,t){let n=Number(e[`:status`]??200),r={};for(let[t,n]of Object.entries(e))t!==`:status`&&(r[t]=typeof n==`number`?String(n):n);this.writeHead(n,r),t?.endStream&&this.end()}writeContinue(e){e&&Promise.resolve().then(e)}writeEarlyHints(e,t){t&&Promise.resolve().then(t)}addTrailers(e){}setTimeout(e,t){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),t&&this.once(`timeout`,t),e>0&&(this._timeoutTimer=setTimeout(()=>{this._timeoutTimer=null,this.emit(`timeout`)},e)),this}_startStreaming(){if(this._streaming)return;this._streaming=!0,this.headersSent=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),this._soupMsg.set_status(this.statusCode,this.statusMessage||null);let e=this._soupMsg.get_response_headers();this._headers.has(`content-length`)?e.set_encoding(n.Encoding.CONTENT_LENGTH):e.set_encoding(n.Encoding.CHUNKED);for(let[t,n]of this._headers)if(Array.isArray(n))for(let r of n)e.append(t,r);else e.replace(t,n)}_write(e,t,n){let r=c.isBuffer(e)?e:c.from(e,t);this._startStreaming(),this._soupMsg.get_response_body().append(new Uint8Array(r.buffer,r.byteOffset,r.byteLength)),this._soupMsg.unpause(),n()}_final(e){this._streaming?(this._soupMsg.get_response_body().complete(),this._soupMsg.unpause()):this._sendBatchResponse(),this.finished=!0,e()}_sendBatchResponse(){if(this.headersSent)return;this.headersSent=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),this._soupMsg.set_status(this.statusCode,this.statusMessage||null);let e=this._soupMsg.get_response_headers();for(let[t,n]of this._headers)if(Array.isArray(n))for(let r of n)e.append(t,r);else e.replace(t,n);let t=this._headers.get(`content-type`)||`text/plain`;this._soupMsg.set_response(t,n.MemoryUse.COPY,new Uint8Array)}end(e,t,n){return typeof e==`function`?(n=e,e=void 0):typeof t==`function`&&(n=t,t=void 0),e!=null&&this.write(e,t),super.end(n),this}respondWithFD(e,t,n){throw Error(`http2 respondWithFD is not yet implemented in GJS (Phase 2)`)}respondWithFile(e,t,n){throw Error(`http2 respondWithFile is not yet implemented in GJS (Phase 2)`)}pushStream(e,t,n){throw Error(`http2 server push is not yet implemented in GJS (Phase 2)`)}createPushResponse(e,t){throw Error(`http2 server push is not yet implemented in GJS (Phase 2)`)}},p=class extends a{id=1;pushAllowed=!1;sentHeaders={};_res;_session;get session(){return this._session}get headersSent(){return this._res.headersSent}get closed(){return this._res.writableEnded}get destroyed(){return this._res.destroyed}get pending(){return!1}get state(){return this.closed?e.NGHTTP2_STREAM_STATE_CLOSED:e.NGHTTP2_STREAM_STATE_OPEN}constructor(e,t=null){super(),this._res=e,this._session=t,e.on(`finish`,()=>this.emit(`close`)),e.on(`error`,e=>this.emit(`error`,e))}respond(e,t){this._res.respond(e,t)}write(e,t,n){return this._res.write(e,t,n)}end(e,t,n){return this._res.end(e,t,n),this}destroy(e){return this._res.destroy(e),this}close(e,t){t&&this.once(`close`,t),this._res.end()}priority(e){}setTimeout(e,t){return this._res.setTimeout(e,t),this}sendTrailers(e){}additionalHeaders(e){}respondWithFD(e,t,n){throw Error(`http2 respondWithFD is not yet implemented in GJS (Phase 2)`)}respondWithFile(e,t,n){throw Error(`http2 respondWithFile is not yet implemented in GJS (Phase 2)`)}pushStream(e,t,n){throw Error(`http2 server push is not yet implemented in GJS (Phase 2)`)}},m=class extends a{type=e.NGHTTP2_SESSION_SERVER;alpnProtocol=`h2`;encrypted=!0;_closed=!1;_destroyed=!1;_settings;constructor(){super(),this._settings=t()}get closed(){return this._closed}get destroyed(){return this._destroyed}get pendingSettingsAck(){return!1}get localSettings(){return{...this._settings}}get remoteSettings(){return t()}get originSet(){return[]}settings(e,t){Object.assign(this._settings,e),t&&Promise.resolve().then(t)}goaway(t,n,r){this.emit(`goaway`,t??e.NGHTTP2_NO_ERROR),this.destroy()}ping(e,t){let n=new Uint8Array(8);return t&&Promise.resolve().then(()=>t(null,0,n)),!0}close(e){this._closed||(this._closed=!0,this.emit(`close`),e&&e())}destroy(e,t){this._destroyed||(this._destroyed=!0,this._closed=!0,e&&this.emit(`error`,e),t!==void 0&&this.emit(`goaway`,t),this.emit(`close`))}altsvc(e,t){}origin(...e){}ref(){}unref(){}};const h=new Set;var g=class extends a{listening=!1;maxHeadersCount=2e3;timeout=0;_soupServer=null;_address=null;_options;get soupServer(){return this._soupServer}constructor(e,t){super(),typeof e==`function`&&(t=e,e={}),this._options=e??{},t&&this.on(`request`,t)}listen(...e){let t=0,r=`0.0.0.0`,i;for(let n of e)typeof n==`number`?t=n:typeof n==`string`?r=n:typeof n==`function`&&(i=n);i&&this.once(`listening`,i);try{this._soupServer=new n.Server({}),this._configureSoupServer(this._soupServer),this._soupServer.add_handler(null,(e,t,n)=>{this._handleRequest(t)}),this._soupServer.listen_local(t,n.ServerListenOptions.IPV4_ONLY),u();let e=this._soupServer.get_listeners(),i=t;if(e&&e.length>0){let t=e[0].get_local_address();t&&typeof t.get_port==`function`&&(i=t.get_port())}this.listening=!0,this._address={port:i,family:`IPv4`,address:r},h.add(this),l(this,`listening`)}catch(e){let t=e instanceof Error?e:Error(String(e));if(this.listenerCount(`error`)===0)throw t;l(this,`error`,t)}return this}_configureSoupServer(e){}_handleRequest(e){let t=new d,i=new f(e);t.method=e.get_method();let a=e.get_uri(),o=a.get_path(),s=a.get_query();t.url=s?o+`?`+s:o,t.authority=a.get_host()??``,t.scheme=a.get_scheme()??`http`,e.get_http_version()===n.HTTPVersion.HTTP_2_0?(t.httpVersion=`2.0`,t.httpVersionMajor=2,t.httpVersionMinor=0):(t.httpVersion=`1.1`,t.httpVersionMajor=1,t.httpVersionMinor=1),e.get_request_headers().foreach((e,n)=>{let r=e.toLowerCase();if(t.rawHeaders.push(e,n),r in t.headers){let e=t.headers[r];Array.isArray(e)?e.push(n):t.headers[r]=[e,n]}else t.headers[r]=n});let c=e.get_remote_host()??`127.0.0.1`,l=e.get_remote_address();t.socket={remoteAddress:c,remotePort:l instanceof r.InetSocketAddress?l.get_port():0,localAddress:this._address?.address??`127.0.0.1`,localPort:this._address?.port??0,encrypted:this instanceof _};let u=e.get_request_body();u?.data&&u.data.length>0?t._pushBody(u.data):t._pushBody(null);let h={":method":t.method,":path":t.url,":authority":t.authority,":scheme":t.scheme,...t.headers};e.pause(),i.on(`finish`,()=>e.unpause());let g=new p(i,new m);t._setStream(g),i._setStream(g),this.emit(`stream`,g,h),this.emit(`request`,t,i)}address(){return this._address}close(e){return e&&this.once(`close`,e),this._soupServer&&=(this._soupServer.disconnect(),null),this.listening=!1,h.delete(this),l(this,`close`),this}setTimeout(e,t){return this.timeout=e,t&&this.on(`timeout`,t),this}},_=class extends g{_tlsCert=null;constructor(e,t){if(super(e,t),e.cert&&e.key){let t=v(e.cert),n=v(e.key);this._tlsCert=y(t,n)}else e.pfx}_configureSoupServer(e){this._tlsCert&&e.set_tls_certificate(this._tlsCert)}setSecureContext(e){if(e.cert&&e.key){let t=v(e.cert),n=v(e.key);this._tlsCert=y(t,n),this._soupServer&&this._tlsCert&&this._soupServer.set_tls_certificate(this._tlsCert)}}};function v(e){return Array.isArray(e)?e.map(v).join(`
|
|
2
|
-
`):c.isBuffer(e)?e.toString(`utf8`):e}function
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import{constants as e,getDefaultSettings as t}from"./protocol.js";import n from"@girs/soup-3.0";import r from"@girs/gio-2.0";import i from"@girs/glib-2.0";import{EventEmitter as a}from"node:events";import{Readable as o,Writable as s}from"node:stream";import{Buffer as c}from"node:buffer";import{deferEmit as l,ensureMainLoop as u}from"@gjsify/utils";import{closeSync as d,openSync as f,read as p,statSync as m}from"node:fs";import{loadNativeHttp2 as h}from"@gjsify/http2-native";var Http2ServerRequest=class extends o{method=`GET`;url=`/`;headers={};rawHeaders=[];authority=``;scheme=`https`;httpVersion=`2.0`;httpVersionMajor=2;httpVersionMinor=0;complete=!1;socket=null;trailers={};rawTrailers=[];_stream=null;_timeoutTimer=null;get stream(){return this._stream}_setStream(e){this._stream=e}constructor(){super()}_read(e){}_autoClose(){}_pushBody(e){e&&e.length>0&&this.push(c.from(e)),this.push(null),this.complete=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null)}setTimeout(e,t){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),t&&this.once(`timeout`,t),e>0&&(this._timeoutTimer=setTimeout(()=>{this._timeoutTimer=null,this.emit(`timeout`)},e)),this}destroy(e){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),super.destroy(e)}},Http2ServerResponse=class extends s{statusCode=200;statusMessage=``;headersSent=!1;finished=!1;sendDate=!0;_soupMsg;_headers=new Map;_streaming=!1;_timeoutTimer=null;_stream=null;_detachedBody=null;get stream(){return this._stream}get socket(){return null}get isDetached(){return this._soupMsg===null}get detachedBody(){return this._detachedBody?c.concat(this._detachedBody):null}_setStream(e){this._stream=e}constructor(e){super(),this._soupMsg=e,e===null&&(this._detachedBody=[])}setHeader(e,t){return this._headers.set(e.toLowerCase(),typeof t==`number`?String(t):t),this}getHeader(e){return this._headers.get(e.toLowerCase())}removeHeader(e){this._headers.delete(e.toLowerCase())}hasHeader(e){return this._headers.has(e.toLowerCase())}getHeaderNames(){return Array.from(this._headers.keys())}getHeaders(){let e={};for(let[t,n]of this._headers)e[t]=n;return e}appendHeader(e,t){let n=e.toLowerCase(),r=this._headers.get(n);return r===void 0?this._headers.set(n,t):Array.isArray(r)?Array.isArray(t)?r.push(...t):r.push(t):this._headers.set(n,Array.isArray(t)?[r,...t]:[r,t]),this}flushHeaders(){this.headersSent||=!0}writeHead(e,t,n){if(this.statusCode=e,typeof t==`object`&&(n=t,t=void 0),typeof t==`string`&&(this.statusMessage=t),n)for(let[e,t]of Object.entries(n))this.setHeader(e,t);return this}respond(e,t){let n=Number(e[`:status`]??200),r={};for(let[t,n]of Object.entries(e))t!==`:status`&&(r[t]=typeof n==`number`?String(n):n);this.writeHead(n,r),t?.endStream&&this.end()}writeContinue(e){e&&Promise.resolve().then(e)}writeEarlyHints(e,t){t&&Promise.resolve().then(t)}addTrailers(e){}setTimeout(e,t){return this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),t&&this.once(`timeout`,t),e>0&&(this._timeoutTimer=setTimeout(()=>{this._timeoutTimer=null,this.emit(`timeout`)},e)),this}_startStreaming(){if(this._streaming||(this._streaming=!0,this.headersSent=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),!this._soupMsg))return;this._soupMsg.set_status(this.statusCode,this.statusMessage||null);let e=this._soupMsg.get_response_headers();this._headers.has(`content-length`)?e.set_encoding(n.Encoding.CONTENT_LENGTH):e.set_encoding(n.Encoding.CHUNKED);for(let[t,n]of this._headers)if(Array.isArray(n))for(let r of n)e.append(t,r);else e.replace(t,n)}_write(e,t,n){let r=c.isBuffer(e)?e:c.from(e,t);this._startStreaming(),this._soupMsg?(this._soupMsg.get_response_body().append(new Uint8Array(r.buffer,r.byteOffset,r.byteLength)),this._soupMsg.unpause()):this._detachedBody&&this._detachedBody.push(r),n()}_final(e){this._streaming?this._soupMsg&&(this._soupMsg.get_response_body().complete(),this._soupMsg.unpause()):this._sendBatchResponse(),this.finished=!0,e()}_sendBatchResponse(){if(this.headersSent||(this.headersSent=!0,this._timeoutTimer&&=(clearTimeout(this._timeoutTimer),null),!this._soupMsg))return;this._soupMsg.set_status(this.statusCode,this.statusMessage||null);let e=this._soupMsg.get_response_headers();for(let[t,n]of this._headers)if(Array.isArray(n))for(let r of n)e.append(t,r);else e.replace(t,n);let t=this._headers.get(`content-type`)||`text/plain`;this._soupMsg.set_response(t,n.MemoryUse.COPY,new Uint8Array)}end(e,t,n){return typeof e==`function`?(n=e,e=void 0):typeof t==`function`&&(n=t,t=void 0),e!=null&&this.write(e,t),super.end(n),this}respondWithFD(e,t,n){_respondFromFD(this,e,t,n??{},!1)}respondWithFile(e,t,n){let r;try{r=f(e,`r`)}catch(e){if(n?.onError){n.onError(e);return}throw e}_respondFromFD(this,r,t,n??{},!0)}pushStream(e,t,n){if(typeof t==`function`&&(n=t,t={}),!n)throw TypeError(`callback must be a function`);if(!this._stream){n(Error(`No associated stream`),null,{});return}this._stream.pushStream(e,t,n)}createPushResponse(e,t){if(typeof t!=`function`)throw TypeError(`callback must be a function`);this.pushStream(e,{},(e,n)=>{if(e){t(e,null);return}let r=n._res;t(null,r??null)})}},g=class ServerHttp2Stream extends a{id;pushAllowed;sentHeaders={};_res;_session;_isPushedStream;_pushedChildren=[];_pushPromiseFrame=null;_pushRequestHeaders=null;get session(){return this._session}get headersSent(){return this._res.headersSent}get closed(){return this._res.writableEnded}get destroyed(){return this._res.destroyed}get pending(){return!1}get state(){return this.closed?e.NGHTTP2_STREAM_STATE_CLOSED:e.NGHTTP2_STREAM_STATE_OPEN}get pushPromiseFrame(){return this._pushPromiseFrame}get pushRequestHeaders(){return this._pushRequestHeaders}get pushedChildren(){return this._pushedChildren}constructor(e,t=null,n={}){super(),this._res=e,this._session=t,this._isPushedStream=n.isPushedStream===!0,this.id=n.streamId??1,this.pushAllowed=!this._isPushedStream&&t?.canPush!==!1,e.on(`finish`,()=>this.emit(`close`)),e.on(`error`,e=>this.emit(`error`,e))}respond(e,t){this._res.respond(e,t)}write(e,t,n){return this._res.write(e,t,n)}end(e,t,n){return this._res.end(e,t,n),this}destroy(e){return this._res.destroy(e),this}close(e,t){t&&this.once(`close`,t),this._res.end()}priority(e){}setTimeout(e,t){return this._res.setTimeout(e,t),this}sendTrailers(e){}additionalHeaders(e){}respondWithFD(e,t,n){this._res.respondWithFD(e,t,n)}respondWithFile(e,t,n){this._res.respondWithFile(e,t,n)}pushStream(e,t,n){if(typeof t==`function`&&(n=t,t={}),!n)throw TypeError(`callback must be a function`);if(this._isPushedStream){let e=Object.assign(Error(`Cannot initiate nested push streams`),{code:`ERR_HTTP2_NESTED_PUSH`});n(e,null,{});return}if(this._session&&this._session.canPush===!1){let e=Object.assign(Error(`HTTP/2 server push has been disabled`),{code:`ERR_HTTP2_PUSH_DISABLED`});n(e,null,{});return}let r,i=null,a={},o={};for(let[t,n]of Object.entries(e))o[t]=typeof n==`number`?String(n):n;if(o[`:method`]||=`GET`,a=o,this._session){if(r=this._session._allocatePushId(),r===0){let e=Object.assign(Error(`No available stream ids`),{code:`ERR_HTTP2_OUT_OF_STREAMS`});n(e,null,{});return}i=this._session._buildPushPromise(this.id,r,o)}else r=2;let s=new Http2ServerResponse(_makeDetachedSoupMessage()),c=new ServerHttp2Stream(s,this._session,{isPushedStream:!0,streamId:r});c._pushPromiseFrame=i,c._pushRequestHeaders=o,s._setStream(c),this._pushedChildren.push(c),Promise.resolve().then(()=>{n(null,c,a)})}},ServerHttp2Session=class extends a{type=e.NGHTTP2_SESSION_SERVER;alpnProtocol=`h2`;encrypted=!0;_closed=!1;_destroyed=!1;_settings;_canPush=!0;_frameEncoder=null;_streamIdAllocator=null;_fallbackPushId=2;constructor(){super(),this._settings=t()}get canPush(){return this._canPush}set canPush(e){this._canPush=e}_allocatePushId(){let e=h();if(e)return this._streamIdAllocator||=e.StreamIdAllocator.new(),this._streamIdAllocator.next_promised();let t=this._fallbackPushId;return t>2147483647?0:(this._fallbackPushId+=2,t)}_buildPushPromise(e,t,n){let r=h();if(!r)return null;this._frameEncoder||=r.FrameEncoder.new();let i=[],a=[];for(let[e,t]of Object.entries(n)){let n=e.toLowerCase();if(Array.isArray(t))for(let e of t)i.push(n),a.push(String(e));else i.push(n),a.push(String(t))}let o=this._frameEncoder.encode_headers(i,a);if(!o)return null;let s=this._frameEncoder.build_push_promise(e,t,o),c=s.toArray;if(typeof c==`function`)return c.call(s);let l=s.get_data;return typeof l==`function`?l.call(s)??null:null}get closed(){return this._closed}get destroyed(){return this._destroyed}get pendingSettingsAck(){return!1}get localSettings(){return{...this._settings}}get remoteSettings(){return t()}get originSet(){return[]}settings(e,t){Object.assign(this._settings,e),t&&Promise.resolve().then(t)}goaway(t,n,r){this.emit(`goaway`,t??e.NGHTTP2_NO_ERROR),this.destroy()}ping(e,t){let n=new Uint8Array(8);return t&&Promise.resolve().then(()=>t(null,0,n)),!0}close(e){this._closed||(this._closed=!0,this.emit(`close`),e&&e())}destroy(e,t){this._destroyed||(this._destroyed=!0,this._closed=!0,e&&this.emit(`error`,e),t!==void 0&&this.emit(`goaway`,t),this.emit(`close`))}altsvc(e,t){}origin(...e){}ref(){}unref(){}};const _=new Set;var Http2Server=class extends a{listening=!1;maxHeadersCount=2e3;timeout=0;_soupServer=null;_address=null;_options;get soupServer(){return this._soupServer}constructor(e,t){super(),typeof e==`function`&&(t=e,e={}),this._options=e??{},t&&this.on(`request`,t)}listen(...e){let t=0,r=`0.0.0.0`,i;for(let n of e)typeof n==`number`?t=n:typeof n==`string`?r=n:typeof n==`function`&&(i=n);i&&this.once(`listening`,i);try{this._soupServer=new n.Server({}),this._configureSoupServer(this._soupServer),this._soupServer.add_handler(null,(e,t,n)=>{this._handleRequest(t)}),this._soupServer.listen_local(t,n.ServerListenOptions.IPV4_ONLY),u();let e=this._soupServer.get_listeners(),i=t;if(e&&e.length>0){let t=e[0].get_local_address();t&&typeof t.get_port==`function`&&(i=t.get_port())}this.listening=!0,this._address={port:i,family:`IPv4`,address:r},_.add(this),l(this,`listening`)}catch(e){let t=e instanceof Error?e:Error(String(e));if(this.listenerCount(`error`)===0)throw t;l(this,`error`,t)}return this}_configureSoupServer(e){}_handleRequest(e){let t=new Http2ServerRequest,i=new Http2ServerResponse(e);t.method=e.get_method();let a=e.get_uri(),o=a.get_path(),s=a.get_query();t.url=s?o+`?`+s:o,t.authority=a.get_host()??``,t.scheme=a.get_scheme()??`http`,e.get_http_version()===n.HTTPVersion.HTTP_2_0?(t.httpVersion=`2.0`,t.httpVersionMajor=2,t.httpVersionMinor=0):(t.httpVersion=`1.1`,t.httpVersionMajor=1,t.httpVersionMinor=1),e.get_request_headers().foreach((e,n)=>{let r=e.toLowerCase();if(t.rawHeaders.push(e,n),r in t.headers){let e=t.headers[r];Array.isArray(e)?e.push(n):t.headers[r]=[e,n]}else t.headers[r]=n});let c=e.get_remote_host()??`127.0.0.1`,l=e.get_remote_address();t.socket={remoteAddress:c,remotePort:l instanceof r.InetSocketAddress?l.get_port():0,localAddress:this._address?.address??`127.0.0.1`,localPort:this._address?.port??0,encrypted:this instanceof Http2SecureServer};let u=e.get_request_body();u?.data&&u.data.length>0?t._pushBody(u.data):t._pushBody(null);let d={":method":t.method,":path":t.url,":authority":t.authority,":scheme":t.scheme,...t.headers};e.pause(),i.on(`finish`,()=>e.unpause());let f=new g(i,new ServerHttp2Session);t._setStream(f),i._setStream(f),this.emit(`stream`,f,d),this.emit(`request`,t,i)}address(){return this._address}close(e){return e&&this.once(`close`,e),this._soupServer&&=(this._soupServer.disconnect(),null),this.listening=!1,_.delete(this),l(this,`close`),this}setTimeout(e,t){return this.timeout=e,t&&this.on(`timeout`,t),this}},Http2SecureServer=class extends Http2Server{_tlsCert=null;constructor(e,t){if(super(e,t),e.cert&&e.key){let t=_toPemString(e.cert),n=_toPemString(e.key);this._tlsCert=_createTlsCertificate(t,n)}else e.pfx}_configureSoupServer(e){this._tlsCert&&e.set_tls_certificate(this._tlsCert)}setSecureContext(e){if(e.cert&&e.key){let t=_toPemString(e.cert),n=_toPemString(e.key);this._tlsCert=_createTlsCertificate(t,n),this._soupServer&&this._tlsCert&&this._soupServer.set_tls_certificate(this._tlsCert)}}};function _toPemString(e){return Array.isArray(e)?e.map(_toPemString).join(`
|
|
2
|
+
`):c.isBuffer(e)?e.toString(`utf8`):e}function _createTlsCertificate(e,t){let n=e.trimEnd()+`
|
|
3
3
|
`+t.trimEnd()+`
|
|
4
|
-
`;try{return r.TlsCertificate.new_from_pem(n,-1)}catch{let n=i.get_tmp_dir(),a=i.build_filenamev([n,`gjsify-http2-cert.pem`]),o=i.build_filenamev([n,`gjsify-http2-key.pem`]);try{return i.file_set_contents(a,e),i.file_set_contents(o,t),r.TlsCertificate.new_from_files(a,o)}finally{try{r.File.new_for_path(a).delete(null)}catch{}try{r.File.new_for_path(o).delete(null)}catch{}}}}
|
|
4
|
+
`;try{return r.TlsCertificate.new_from_pem(n,-1)}catch{let n=i.get_tmp_dir(),a=i.build_filenamev([n,`gjsify-http2-cert.pem`]),o=i.build_filenamev([n,`gjsify-http2-key.pem`]);try{return i.file_set_contents(a,e),i.file_set_contents(o,t),r.TlsCertificate.new_from_files(a,o)}finally{try{r.File.new_for_path(a).delete(null)}catch{}try{r.File.new_for_path(o).delete(null)}catch{}}}}function _makeDetachedSoupMessage(){return null}function _respondFromFD(e,t,n,r,i){let a=typeof t==`number`?t:t.fd,o=a,s={...n??{}};if(r.statCheck)try{let t=m(_fdPath(a)??`/proc/self/fd/`+a);if(r.statCheck(t,s,r)===!1){i&&d(a),e.end();return}}catch(e){if(r.onError){r.onError(e),i&&d(a);return}}let l=Number(s[`:status`]??200);delete s[`:status`];let u={};for(let[e,t]of Object.entries(s))u[e]=typeof t==`number`?String(t):t;e.writeHead(l,u),e.flushHeaders();let f=Math.max(0,r.offset??0),h=r.length,g=64*1024,_=c.alloc(g),v=f,y=typeof h==`number`?h:1/0,b=0,readNext=()=>{if(y<=0){finish();return}p(o,_,0,Math.min(g,y),v,(t,n)=>{if(t){cleanup(t);return}if(n===0){finish();return}v+=n,b+=n,y-=n;let r=c.allocUnsafe(n);_.copy(r,0,0,n),e.write(r)?readNext():e.once(`drain`,readNext)})},finish=()=>{if(e.end(),i)try{d(o)}catch{}},cleanup=t=>{if(r.onError?r.onError(t):e.destroy(t),i)try{d(o)}catch{}};if(y===0){finish();return}readNext()}function _fdPath(e){return typeof e!=`number`||e<0?null:`/proc/self/fd/`+e}export{Http2SecureServer,Http2Server,Http2ServerRequest,Http2ServerResponse,ServerHttp2Session,g as ServerHttp2Stream};
|
package/lib/types/server.d.ts
CHANGED
|
@@ -40,10 +40,16 @@ export declare class Http2ServerResponse extends Writable {
|
|
|
40
40
|
private _streaming;
|
|
41
41
|
private _timeoutTimer;
|
|
42
42
|
private _stream;
|
|
43
|
+
/** Detached responses (PUSH_PROMISE children) buffer their output. */
|
|
44
|
+
private _detachedBody;
|
|
43
45
|
get stream(): ServerHttp2Stream | null;
|
|
44
46
|
get socket(): null;
|
|
47
|
+
/** Whether this response is detached from a Soup connection (push streams). */
|
|
48
|
+
get isDetached(): boolean;
|
|
49
|
+
/** Buffered body bytes for detached (push) responses — null on regular responses. */
|
|
50
|
+
get detachedBody(): Buffer | null;
|
|
45
51
|
_setStream(stream: ServerHttp2Stream): void;
|
|
46
|
-
constructor(soupMsg: Soup.ServerMessage);
|
|
52
|
+
constructor(soupMsg: Soup.ServerMessage | null);
|
|
47
53
|
setHeader(name: string, value: string | number | string[]): this;
|
|
48
54
|
getHeader(name: string): string | string[] | undefined;
|
|
49
55
|
removeHeader(name: string): void;
|
|
@@ -65,24 +71,90 @@ export declare class Http2ServerResponse extends Writable {
|
|
|
65
71
|
_final(callback: (error?: Error | null) => void): void;
|
|
66
72
|
private _sendBatchResponse;
|
|
67
73
|
end(chunk?: unknown, encoding?: BufferEncoding | (() => void), callback?: () => void): this;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
/**
|
|
75
|
+
* respondWithFD — stream the contents of an open file descriptor as the
|
|
76
|
+
* response body. Headers are sent once `statCheck()` (if provided) has
|
|
77
|
+
* had a chance to mutate them; payload is read in 64 KiB chunks via
|
|
78
|
+
* `fs.read()` and dispatched through the existing Soup chunked-write path.
|
|
79
|
+
*
|
|
80
|
+
* Reference: Node.js doc/api/http2.md § respondWithFD()
|
|
81
|
+
*/
|
|
82
|
+
respondWithFD(fd: number | {
|
|
83
|
+
fd: number;
|
|
84
|
+
}, headers?: Record<string, string | string[] | number>, options?: {
|
|
85
|
+
offset?: number;
|
|
86
|
+
length?: number;
|
|
87
|
+
statCheck?: (stat: any, headers: any, statOptions: any) => void;
|
|
88
|
+
}): void;
|
|
89
|
+
/**
|
|
90
|
+
* respondWithFile — stream a regular file by path. Opens the file with
|
|
91
|
+
* fs.openSync, runs the optional `statCheck()` callback so the user can
|
|
92
|
+
* mutate headers based on stat results (last-modified, size, etag, …),
|
|
93
|
+
* then delegates to the same FD-streaming path as `respondWithFD()`.
|
|
94
|
+
*
|
|
95
|
+
* Reference: Node.js doc/api/http2.md § respondWithFile()
|
|
96
|
+
*/
|
|
97
|
+
respondWithFile(path: string, headers?: Record<string, string | string[] | number>, options?: {
|
|
98
|
+
offset?: number;
|
|
99
|
+
length?: number;
|
|
100
|
+
statCheck?: (stat: any, headers: any, statOptions: any) => void;
|
|
101
|
+
onError?: (err: Error) => void;
|
|
102
|
+
}): void;
|
|
103
|
+
/**
|
|
104
|
+
* pushStream — request the server to push an additional resource on a
|
|
105
|
+
* fresh server-initiated stream. The Vala/nghttp2 bridge allocates the
|
|
106
|
+
* promised even stream-id and constructs the PUSH_PROMISE frame; wire-level
|
|
107
|
+
* delivery requires raw nghttp2-on-socket access that Soup does not expose,
|
|
108
|
+
* so the byte-frame is currently a no-op on the wire — but the bridge
|
|
109
|
+
* allocator and frame builder are exercised end-to-end and the callback
|
|
110
|
+
* receives a fully-usable `ServerHttp2Stream` whose `respond()` / `end()`
|
|
111
|
+
* calls write into a synthetic in-memory stream observable from tests.
|
|
112
|
+
*
|
|
113
|
+
* See STATUS.md "Open TODOs" → "http2 PUSH_PROMISE wire delivery".
|
|
114
|
+
*/
|
|
115
|
+
pushStream(headers: Record<string, string | string[] | number>, options: {
|
|
116
|
+
parent?: number;
|
|
117
|
+
weight?: number;
|
|
118
|
+
exclusive?: boolean;
|
|
119
|
+
} | ((err: Error | null, pushStream: ServerHttp2Stream, headers: Record<string, string | string[]>) => void), callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: Record<string, string | string[]>) => void): void;
|
|
120
|
+
/**
|
|
121
|
+
* createPushResponse — alternate API: create a child Http2ServerResponse
|
|
122
|
+
* for the push without needing to bridge through ServerHttp2Stream. The
|
|
123
|
+
* created response shares the parent's stream allocator + bridge.
|
|
124
|
+
*
|
|
125
|
+
* Reference: Node.js doc/api/http2.md § Http2ServerResponse#createPushResponse()
|
|
126
|
+
*/
|
|
127
|
+
createPushResponse(headers: Record<string, string | string[] | number>, callback: (err: Error | null, res: Http2ServerResponse) => void): void;
|
|
72
128
|
}
|
|
73
129
|
export declare class ServerHttp2Stream extends EventEmitter {
|
|
74
|
-
readonly id
|
|
75
|
-
readonly pushAllowed
|
|
130
|
+
readonly id: number;
|
|
131
|
+
readonly pushAllowed: boolean;
|
|
76
132
|
readonly sentHeaders: Record<string, string | string[]>;
|
|
77
133
|
private _res;
|
|
78
134
|
private _session;
|
|
135
|
+
private _isPushedStream;
|
|
136
|
+
/** Children pushed off this request stream (parent → array). */
|
|
137
|
+
private _pushedChildren;
|
|
138
|
+
/** Cached PUSH_PROMISE frame bytes for inspection in tests. */
|
|
139
|
+
private _pushPromiseFrame;
|
|
140
|
+
/** Push request headers (`:method`, `:path`, …). */
|
|
141
|
+
private _pushRequestHeaders;
|
|
79
142
|
get session(): ServerHttp2Session | null;
|
|
80
143
|
get headersSent(): boolean;
|
|
81
144
|
get closed(): boolean;
|
|
82
145
|
get destroyed(): boolean;
|
|
83
146
|
get pending(): boolean;
|
|
84
147
|
get state(): number;
|
|
85
|
-
|
|
148
|
+
/** Bytes of the PUSH_PROMISE frame this stream was reserved with (push streams only). */
|
|
149
|
+
get pushPromiseFrame(): Uint8Array | null;
|
|
150
|
+
/** Request headers the push was promised with (push streams only). */
|
|
151
|
+
get pushRequestHeaders(): Record<string, string | string[]> | null;
|
|
152
|
+
/** Push streams created from this stream. */
|
|
153
|
+
get pushedChildren(): ReadonlyArray<ServerHttp2Stream>;
|
|
154
|
+
constructor(res: Http2ServerResponse, session?: ServerHttp2Session | null, options?: {
|
|
155
|
+
isPushedStream?: boolean;
|
|
156
|
+
streamId?: number;
|
|
157
|
+
});
|
|
86
158
|
respond(headers: Record<string, string | string[] | number>, options?: {
|
|
87
159
|
endStream?: boolean;
|
|
88
160
|
}): void;
|
|
@@ -99,9 +171,34 @@ export declare class ServerHttp2Stream extends EventEmitter {
|
|
|
99
171
|
setTimeout(msecs: number, callback?: () => void): this;
|
|
100
172
|
sendTrailers(_headers: Record<string, string | string[]>): void;
|
|
101
173
|
additionalHeaders(_headers: Record<string, string | string[]>): void;
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
174
|
+
/** See {@link Http2ServerResponse.respondWithFD}. */
|
|
175
|
+
respondWithFD(fd: number | {
|
|
176
|
+
fd: number;
|
|
177
|
+
}, headers?: Record<string, string | string[] | number>, options?: {
|
|
178
|
+
offset?: number;
|
|
179
|
+
length?: number;
|
|
180
|
+
statCheck?: (stat: any, headers: any, statOptions: any) => void;
|
|
181
|
+
}): void;
|
|
182
|
+
/** See {@link Http2ServerResponse.respondWithFile}. */
|
|
183
|
+
respondWithFile(path: string, headers?: Record<string, string | string[] | number>, options?: {
|
|
184
|
+
offset?: number;
|
|
185
|
+
length?: number;
|
|
186
|
+
statCheck?: (stat: any, headers: any, statOptions: any) => void;
|
|
187
|
+
onError?: (err: Error) => void;
|
|
188
|
+
}): void;
|
|
189
|
+
/**
|
|
190
|
+
* pushStream — see {@link Http2ServerResponse.pushStream} for the full
|
|
191
|
+
* contract. This is the lower-level entry point: it allocates a promised
|
|
192
|
+
* stream-id from the session-bound `GjsifyHttp2.StreamIdAllocator`, builds
|
|
193
|
+
* the PUSH_PROMISE frame via `GjsifyHttp2.FrameEncoder`, then synthesises
|
|
194
|
+
* a child `ServerHttp2Stream` whose response surface is independent of
|
|
195
|
+
* the parent's underlying SoupServerMessage.
|
|
196
|
+
*/
|
|
197
|
+
pushStream(headers: Record<string, string | string[] | number>, options: {
|
|
198
|
+
parent?: number;
|
|
199
|
+
weight?: number;
|
|
200
|
+
exclusive?: boolean;
|
|
201
|
+
} | ((err: Error | null, pushStream: ServerHttp2Stream, headers: Record<string, string | string[]>) => void), callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: Record<string, string | string[]>) => void): void;
|
|
105
202
|
}
|
|
106
203
|
export declare class ServerHttp2Session extends EventEmitter {
|
|
107
204
|
readonly type: 0;
|
|
@@ -110,7 +207,20 @@ export declare class ServerHttp2Session extends EventEmitter {
|
|
|
110
207
|
private _closed;
|
|
111
208
|
private _destroyed;
|
|
112
209
|
private _settings;
|
|
210
|
+
private _canPush;
|
|
211
|
+
/** Lazy-initialised native bridge handles. */
|
|
212
|
+
private _frameEncoder;
|
|
213
|
+
private _streamIdAllocator;
|
|
214
|
+
/** Fallback id counter used when the native bridge is unavailable. */
|
|
215
|
+
private _fallbackPushId;
|
|
113
216
|
constructor();
|
|
217
|
+
/** Whether server-push is currently permitted on this session. */
|
|
218
|
+
get canPush(): boolean;
|
|
219
|
+
set canPush(v: boolean);
|
|
220
|
+
/** @internal Allocate the next promised (even) stream id for a push. */
|
|
221
|
+
_allocatePushId(): number;
|
|
222
|
+
/** @internal Build PUSH_PROMISE frame bytes via the native bridge (or null when unavailable). */
|
|
223
|
+
_buildPushPromise(associatedStreamId: number, promisedStreamId: number, headers: Record<string, string | string[]>): Uint8Array | null;
|
|
114
224
|
get closed(): boolean;
|
|
115
225
|
get destroyed(): boolean;
|
|
116
226
|
get pendingSettingsAck(): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/http2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Node.js http2 module for Gjs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "lib/esm/index.js",
|
|
@@ -30,17 +30,18 @@
|
|
|
30
30
|
"http2"
|
|
31
31
|
],
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@gjsify/cli": "^0.
|
|
34
|
-
"@gjsify/unit": "^0.
|
|
33
|
+
"@gjsify/cli": "^0.4.0",
|
|
34
|
+
"@gjsify/unit": "^0.4.0",
|
|
35
35
|
"@types/node": "^25.6.2",
|
|
36
36
|
"typescript": "^6.0.3"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@girs/gio-2.0": "2.88.0-4.0.0-rc.
|
|
40
|
-
"@girs/glib-2.0": "2.88.0-4.0.0-rc.
|
|
41
|
-
"@girs/gobject-2.0": "2.88.0-4.0.0-rc.
|
|
42
|
-
"@girs/soup-3.0": "3.6.6-4.0.0-rc.
|
|
43
|
-
"@gjsify/events": "^0.
|
|
44
|
-
"@gjsify/
|
|
39
|
+
"@girs/gio-2.0": "2.88.0-4.0.0-rc.15",
|
|
40
|
+
"@girs/glib-2.0": "2.88.0-4.0.0-rc.15",
|
|
41
|
+
"@girs/gobject-2.0": "2.88.0-4.0.0-rc.15",
|
|
42
|
+
"@girs/soup-3.0": "3.6.6-4.0.0-rc.15",
|
|
43
|
+
"@gjsify/events": "^0.4.0",
|
|
44
|
+
"@gjsify/http2-native": "^0.4.0",
|
|
45
|
+
"@gjsify/utils": "^0.4.0"
|
|
45
46
|
}
|
|
46
47
|
}
|