routup 3.2.0 → 3.3.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/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { subtle } from 'uncrypto';
4
4
  import { compile, all } from 'proxy-addr';
5
5
  import { getType, get } from 'mime-explorer';
6
6
  import Negotiator from 'negotiator';
7
- import { Readable, Writable } from 'readable-stream';
7
+ import { Readable, PassThrough, Writable } from 'readable-stream';
8
8
  import { HTTPError } from '@ebec/http';
9
9
  import { pathToRegexp } from 'path-to-regexp';
10
10
 
@@ -32,6 +32,7 @@ var HeaderName;
32
32
  HeaderName["CONTENT_LENGTH"] = "content-length";
33
33
  HeaderName["CONTENT_RANGE"] = "content-range";
34
34
  HeaderName["CONTENT_TYPE"] = "content-type";
35
+ HeaderName["CONNECTION"] = "connection";
35
36
  HeaderName["COOKIE"] = "cookie";
36
37
  HeaderName["ETag"] = "etag";
37
38
  HeaderName["HOST"] = "host";
@@ -46,6 +47,7 @@ var HeaderName;
46
47
  HeaderName["RETRY_AFTER"] = "retry-after";
47
48
  HeaderName["SET_COOKIE"] = "set-cookie";
48
49
  HeaderName["TRANSFER_ENCODING"] = "transfer-encoding";
50
+ HeaderName["X_ACCEL_BUFFERING"] = "x-accel-buffering";
49
51
  HeaderName["X_FORWARDED_HOST"] = "x-forwarded-host";
50
52
  HeaderName["X_FORWARDED_FOR"] = "x-forwarded-for";
51
53
  HeaderName["X_FORWARDED_PROTO"] = "x-forwarded-proto";
@@ -544,6 +546,10 @@ function getRequestHostName(req, options) {
544
546
  return index !== -1 ? hostname.substring(0, index) : hostname;
545
547
  }
546
548
 
549
+ function isRequestHTTP2(req) {
550
+ return typeof getRequestHeader(req, ':path') !== 'undefined' && typeof getRequestHeader(req, ':method') !== 'undefined';
551
+ }
552
+
547
553
  function getRequestIP(req, options) {
548
554
  options = options || {};
549
555
  let trustProxy;
@@ -759,6 +765,96 @@ function isResponseGone(res) {
759
765
  }
760
766
  return false;
761
767
  }
768
+ function setResponseGone(res, value) {
769
+ res[GoneSymbol] = value;
770
+ }
771
+
772
+ function serializeEventStreamMessage(message) {
773
+ let result = '';
774
+ if (message.id) {
775
+ result += `id: ${message.id}\n`;
776
+ }
777
+ if (message.event) {
778
+ result += `event: ${message.event}\n`;
779
+ }
780
+ if (typeof message.retry === 'number' && Number.isInteger(message.retry)) {
781
+ result += `retry: ${message.retry}\n`;
782
+ }
783
+ result += `data: ${message.data}\n\n`;
784
+ return result;
785
+ }
786
+
787
+ class EventStream {
788
+ open() {
789
+ this.response.req.on('close', ()=>this.end());
790
+ this.response.req.on('error', (err)=>{
791
+ this.emit('error', err);
792
+ this.end();
793
+ });
794
+ this.passThrough.on('data', (chunk)=>this.response.write(chunk));
795
+ this.passThrough.on('error', (err)=>{
796
+ this.emit('error', err);
797
+ this.end();
798
+ });
799
+ this.passThrough.on('close', ()=>this.end());
800
+ this.response.setHeader(HeaderName.CONTENT_TYPE, 'text/event-stream');
801
+ this.response.setHeader(HeaderName.CACHE_CONTROL, 'private, no-cache, no-store, no-transform, must-revalidate, max-age=0');
802
+ this.response.setHeader(HeaderName.X_ACCEL_BUFFERING, 'no');
803
+ if (!isRequestHTTP2(this.response.req)) {
804
+ this.response.setHeader(HeaderName.CONNECTION, 'keep-alive');
805
+ }
806
+ this.response.statusCode = 200;
807
+ }
808
+ write(message) {
809
+ if (typeof message === 'string') {
810
+ this.write({
811
+ data: message
812
+ });
813
+ return;
814
+ }
815
+ if (!this.passThrough.closed && this.passThrough.writable) {
816
+ this.passThrough.write(serializeEventStreamMessage(message));
817
+ }
818
+ }
819
+ end() {
820
+ if (this.flushed) return;
821
+ this.flushed = true;
822
+ if (!this.passThrough.closed) {
823
+ this.passThrough.end();
824
+ }
825
+ this.emit('close');
826
+ setResponseGone(this.response, true);
827
+ this.response.end();
828
+ }
829
+ on(event, listener) {
830
+ if (typeof this.eventHandlers[event] === 'undefined') {
831
+ this.eventHandlers[event] = [];
832
+ }
833
+ this.eventHandlers[event].push(listener);
834
+ }
835
+ emit(event, ...args) {
836
+ if (typeof this.eventHandlers[event] === 'undefined') {
837
+ return;
838
+ }
839
+ const listeners = this.eventHandlers[event].slice();
840
+ for(let i = 0; i < listeners.length; i++){
841
+ listeners[i].apply(this, args);
842
+ }
843
+ }
844
+ constructor(response){
845
+ this.response = response;
846
+ this.passThrough = new PassThrough({
847
+ encoding: 'utf-8'
848
+ });
849
+ this.flushed = false;
850
+ this.eventHandlers = {};
851
+ this.open();
852
+ }
853
+ }
854
+
855
+ function createEventStream(response) {
856
+ return new EventStream(response);
857
+ }
762
858
 
763
859
  function appendResponseHeader(res, name, value) {
764
860
  let header = res.getHeader(name);
@@ -2137,5 +2233,5 @@ class Router {
2137
2233
  }
2138
2234
  }
2139
2235
 
2140
- export { DispatchErrorEvent, DispatchEvent, Handler, HandlerSymbol, HandlerType, HeaderName, MethodName, PathMatcher, Router, RoutupError, appendResponseHeader, appendResponseHeaderDirective, coreHandler, createError, createNodeDispatcher, createRawDispatcher, createRequest, createResponse, createWebDispatcher, dispatch, dispatchNodeRequest, dispatchRawRequest, dispatchWebRequest, errorHandler, getRequestAcceptableCharset, getRequestAcceptableCharsets, getRequestAcceptableContentType, getRequestAcceptableContentTypes, getRequestAcceptableEncoding, getRequestAcceptableEncodings, getRequestAcceptableLanguage, getRequestAcceptableLanguages, getRequestHeader, getRequestHostName, getRequestIP, getRequestProtocol, isDispatcherErrorEvent, isError, isHandler, isHandlerConfig, isPath, isPlugin, isRequestCacheable, isResponseGone, matchRequestContentType, send, sendAccepted, sendCreated, sendFile, sendFormat, sendRedirect, sendStream, sendWebBlob, sendWebResponse, setRequestEnv, setRequestHeader, setRequestMountPath, setRequestParam, setRequestParams, setRequestRouterPath, setResponseCacheHeaders, setResponseContentTypeByFileName, setResponseHeaderAttachment, setResponseHeaderContentType, transformHeaderToTuples, transformHeadersToTuples, unsetRequestEnv, useRequestEnv, useRequestMountPath, useRequestNegotiator, useRequestParam, useRequestParams, useRequestPath, useRequestRouterPath };
2236
+ export { DispatchErrorEvent, DispatchEvent, EventStream, Handler, HandlerSymbol, HandlerType, HeaderName, MethodName, PathMatcher, Router, RoutupError, appendResponseHeader, appendResponseHeaderDirective, coreHandler, createError, createEventStream, createNodeDispatcher, createRawDispatcher, createRequest, createResponse, createWebDispatcher, dispatch, dispatchNodeRequest, dispatchRawRequest, dispatchWebRequest, errorHandler, getRequestAcceptableCharset, getRequestAcceptableCharsets, getRequestAcceptableContentType, getRequestAcceptableContentTypes, getRequestAcceptableEncoding, getRequestAcceptableEncodings, getRequestAcceptableLanguage, getRequestAcceptableLanguages, getRequestHeader, getRequestHostName, getRequestIP, getRequestProtocol, isDispatcherErrorEvent, isError, isHandler, isHandlerConfig, isPath, isPlugin, isRequestCacheable, isRequestHTTP2, isResponseGone, matchRequestContentType, send, sendAccepted, sendCreated, sendFile, sendFormat, sendRedirect, sendStream, sendWebBlob, sendWebResponse, setRequestEnv, setRequestHeader, setRequestMountPath, setRequestParam, setRequestParams, setRequestRouterPath, setResponseCacheHeaders, setResponseContentTypeByFileName, setResponseGone, setResponseHeaderAttachment, setResponseHeaderContentType, transformHeaderToTuples, transformHeadersToTuples, unsetRequestEnv, useRequestEnv, useRequestMountPath, useRequestNegotiator, useRequestParam, useRequestParams, useRequestPath, useRequestRouterPath };
2141
2237
  //# sourceMappingURL=index.mjs.map