@doodad-js/http
Version:
HTTP server (alpha)
2 lines • 66.2 kB
JavaScript
// Copyright 2015-2018 Claude Petit, licensed under Apache License version 2.0
"use strict";exports.add=function add(modules){modules=(modules||{});modules['Doodad.Server.Http']={version:'2.2.1a',namespaces:['Interfaces','MixIns'],create:function create(root,_options,_shared){const doodad=root.Doodad,types=doodad.Types,tools=doodad.Tools,locale=tools.Locale,files=tools.Files,dates=tools.Dates,namespaces=doodad.Namespaces,mixIns=doodad.MixIns,extenders=doodad.Extenders,io=doodad.IO,server=doodad.Server,serverMixIns=server.MixIns,http=server.Http,httpMixIns=http.MixIns,ioJson=io.Json,moment=dates.Moment,unicode=tools.Unicode;const __Internal__={};tools.complete(_shared.Natives,{windowRegExp:global.RegExp,});__Internal__.isObsText=function isObsText(chrAscii){return(chrAscii>=0x80)};__Internal__.getNextTokenOrString=function getNextTokenOrString(value,pos,token,delimiters){const delims=delimiters&&delimiters[0];let i=pos[0],quoted=false,str='',quotePair=false,endOfToken=false;if(delimiters){delimiters[0]=null};let chr=unicode.nextChar(value,i);while(chr){const prevI=i,chrAscii=chr.codePoint;if(quoted){if(chrAscii===0x5C){quotePair=true}else if(quotePair){quotePair=false;if((chrAscii===0x09)||((chrAscii>=0x20)&&(chrAscii<=0x7E))||__Internal__.isObsText(chrAscii)){str+=chr.chr}else{str=null;break}}else if(chrAscii===0x22){quoted=false}else if((chrAscii===0x09)||(chrAscii===0x20)||(chrAscii===0x21)||((chrAscii>=0x23)&&(chrAscii<=0x5B))||((chrAscii>=0x5D)&&(chrAscii<=0x7E))||__Internal__.isObsText(chrAscii)){str+=chr.chr}else{str=null;break}}else{if((chrAscii===0x09)||(chrAscii===0x20)){if(str){endOfToken=true}}else if(chrAscii===0x22){if(endOfToken||str||token){str=null;break}else{quoted=true}}else if((chrAscii>=0x20)&&(chrAscii<=0x7E)){if(delims&&(delims.indexOf(chr.chr)>=0)){if(delimiters){delimiters[0]=chr.chr};i=chr.index+chr.size;break}else if(endOfToken){i=prevI;break}else{str+=chr.chr}}else{str=null;break}};i=chr.index+chr.size;chr=chr.nextChar()};if(quoted){str=null};pos[0]=i;return str};http.ADD('parseAcceptHeader',function parseAcceptHeader(value){const result=tools.nullObject(),pos=[],delimiters=[];let i=0,media,token,str,qvalue,acceptExts;while(i<value.length){qvalue=1.0;acceptExts=tools.nullObject();pos[0]=i;delimiters[0]=";,";media=__Internal__.getNextTokenOrString(value,pos,true,delimiters);i=pos[0];if(!media){return null};if(delimiters[0] !==','){newExt:while(i<value.length){pos[0]=i;delimiters[0]="=";token=__Internal__.getNextTokenOrString(value,pos,true,delimiters);i=pos[0];if(!token){return null};if(delimiters[0] !=="="){return null};token=token.toLowerCase();if(token==='q'){pos[0]=i;delimiters[0]=";,";qvalue=__Internal__.getNextTokenOrString(value,pos,false,delimiters);i=pos[0];qvalue=types.toFloat(qvalue,3);if((qvalue<0.0)||(qvalue>1.0)){return null}}else{pos[0]=i;delimiters[0]=";,";str=__Internal__.getNextTokenOrString(value,pos,false,delimiters);i=pos[0];if(str===null){return null};acceptExts[token]=str};if(delimiters[0]===','){break newExt}}};media=media.toLowerCase();token=tools.split(media,'/',2);const type=token[0]||'*',subtype=(token.length>1)&&token[1]||'*';result[media]=types.freezeObject(tools.nullObject({name:media,type:type,subtype:subtype,weight:qvalue,exts:types.freezeObject(acceptExts),}))};return types.values(result).sort(function(media1,media2){if(media1.weight>media2.weight){return-1}else if(media1.weight<media2.weight){return 1}else{return 0}})});http.ADD('parseAcceptEncodingHeader',function parseAcceptEncodingHeader(value){if(!value){return[]};const result=tools.nullObject(),pos=[],delimiters=[];let i=0,encoding,token,str,qvalue,acceptExts;while(i<value.length){qvalue=1.0;acceptExts=tools.nullObject();pos[0]=i;delimiters[0]=";,";encoding=__Internal__.getNextTokenOrString(value,pos,true,delimiters);i=pos[0];if(!encoding){return null};if(delimiters[0] !==','){newExt:while(i<value.length){pos[0]=i;delimiters[0]="=";token=__Internal__.getNextTokenOrString(value,pos,true,delimiters);i=pos[0];if(!token){return null};if(delimiters[0] !=="="){return null};token=token.toLowerCase();if(token==='q'){pos[0]=i;delimiters[0]=";,";qvalue=__Internal__.getNextTokenOrString(value,pos,false,delimiters);i=pos[0];qvalue=types.toFloat(qvalue,3);if((qvalue<0.0)||(qvalue>1.0)){return null}}else{pos[0]=i;delimiters[0]=";,";str=__Internal__.getNextTokenOrString(value,pos,false,delimiters);i=pos[0];if(str===null){return null};acceptExts[token]=str};if(delimiters[0]===','){break newExt}}};encoding=encoding.toLowerCase();if((qvalue>0.0)||(encoding==='identity')){result[encoding]=types.freezeObject(tools.nullObject({name:encoding,weight:qvalue,exts:types.freezeObject(acceptExts),}))}};if(result.identity){if(result.identity.weight<=0.0){delete result.identity}}else{result.identity=types.freezeObject(tools.nullObject({name:'identity',weight:-1.0,exts:types.freezeObject(tools.nullObject()),}))};return types.values(result).sort(function(encoding1,encoding2){if(encoding1.weight>encoding2.weight){return-1}else if(encoding1.weight<encoding2.weight){return 1}else{return 0}})});http.ADD('parseContentTypeHeader',function parseContentTypeHeader(contentType){if(!contentType){return null};const pos=[];let delimiters=[];pos[0]=0;delimiters=[';'];let media=__Internal__.getNextTokenOrString(contentType,pos,true,delimiters);if(!media){return null};media=media.toLowerCase();const tmp=tools.split(media,'/',2);const type=tmp[0],subtype=tmp[1];if(!type||!subtype){return null};const params=tools.nullObject();if(delimiters[0]===';'){while(pos[0]<contentType.length){delimiters=['='];let name=__Internal__.getNextTokenOrString(contentType,pos,true,delimiters);if(!name){return null};name=name.toLowerCase();delimiters=[';'];const value=__Internal__.getNextTokenOrString(contentType,pos,false,delimiters);params[name]=value||''}};const weight=types.toFloat(types.get(params,'q',1.0));return types.freezeObject(tools.nullObject({name:media,type:type,subtype:subtype,params:types.freezeObject(params),weight:weight,customData:tools.nullObject(),toString:function toString(){return this.name+tools.reduce(this.params,function(result,value,key){if(!types.isNothing(value)){result+="; "+types.toString(key)+"="+types.toString(value)};return result},"")},clone:function clone(){const params=tools.nullObject(this.params);const customData=tools.nullObject(this.customData);const newType=tools.nullObject(this);newType.params=types.freezeObject(params);newType.customData=customData;return types.freezeObject(newType)},set:function set(attrs){const params=tools.nullObject(this.params,types.get(attrs,'params'));const customData=tools.nullObject(this.customData,types.get(attrs,'customData'));const newType=tools.nullObject(this,attrs);newType.params=types.freezeObject(params);newType.customData=customData;return types.freezeObject(newType)},}))});http.ADD('parseContentDispositionHeader',function parseContentDispositionHeader(contentDisposition){if(!contentDisposition){return null};const pos=[];let delimiters=[];pos[0]=0;delimiters=[';='];let media=__Internal__.getNextTokenOrString(contentDisposition,pos,true,delimiters);if(media===null){return null};const params=tools.nullObject();if(delimiters[0]===';'){media=media.toLowerCase()}else{delimiters=[';'];const value=__Internal__.getNextTokenOrString(contentDisposition,pos,false,delimiters);params[media]=value||'';media=''};while(pos[0]<contentDisposition.length){delimiters=['='];let name=__Internal__.getNextTokenOrString(contentDisposition,pos,true,delimiters);if(!name){return null};name=name.toLowerCase();delimiters=[';'];const value=__Internal__.getNextTokenOrString(contentDisposition,pos,false,delimiters);params[name]=value||''};return types.freezeObject(tools.nullObject({name:media,params:types.freezeObject(params),toString:function toString(){return this.name+tools.reduce(this.params,function(result,value,key){if(!types.isNothing(value)){result+="; "+types.toString(key)+"="+types.toString(value)};return result},"")},}))});http.ADD('compareMimeTypes',function compareMimeTypes(mimeType1,mimeType2){if(mimeType1.name===mimeType2.name){return 40}else if((mimeType1.type===mimeType2.type)&&((mimeType1.subtype==='*')||(mimeType2.subtype==='*'))){return 30}else if(((mimeType1.type==='*')||(mimeType2.type==='*'))&&(mimeType1.subtype===mimeType2.subtype)){return 20}else if(((mimeType1.type==='*')&&(mimeType1.subtype==='*'))||((mimeType2.type==='*')&&(mimeType2.subtype==='*'))){return 10}else{return 0}});http.ADD('toRFC1123Date',function(date){if(moment&&moment.isMoment(date)){date=date.toDate()};return dates.strftime('%a, %d %b %Y %H:%M:%S GMT',date,__Internal__.enUSLocale,true)});httpMixIns.REGISTER(doodad.MIX_IN(doodad.Class.$extend(mixIns.Events,mixIns.Creatable,{$TYPE_NAME:'Headers',$TYPE_UUID:'' +'10742462-db57-4832-ad52-b817571a5734',headers:doodad.PROTECTED(null),contentType:doodad.PUBLIC(doodad.READ_ONLY(null)),contentDisposition:doodad.PUBLIC(doodad.READ_ONLY(null)),__varyingHeaders:doodad.PROTECTED(null),onHeadersChanged:doodad.EVENT(false),create:doodad.OVERRIDE(function create(...args){this.headers=tools.nullObject();this._super(...args)}),getHeader:doodad.PUBLIC(function getHeader(name){const fixed=tools.title(name,'-');return this.headers[fixed]}),getHeaders:doodad.PUBLIC(function getHeaders(names){if(names){if(!types.isArray(names)){names=[names]};const headers={};tools.forEach(names,function(name){const fixed=tools.title(name,'-');headers[name]=this.headers[fixed];if(name!==fixed){headers[fixed]=this.headers[fixed]}});return headers}else{return tools.extend({},this.headers)}}),addHeader:doodad.PUBLIC(function addHeader(name,value){const responseHeaders=this.headers;const fixed=tools.title(tools.trim(name),'-');value=(types.isNothing(value)?'':tools.trim(types.toString(value)));if(fixed==='Content-Type'){this.setContentType(value)}else if(fixed==='Content-Disposition'){this.setContentDisposition(value)}else if(fixed==='Vary'){this.setVary(value)}else{if(value){responseHeaders[fixed]=value}else{delete responseHeaders[fixed]};this.onHeadersChanged(new doodad.Event({headers:[fixed]}))}}),addHeaders:doodad.PUBLIC(function addHeaders(headers){const responseHeaders=this.headers;const changed=tools.nullObject();tools.forEach(headers,function(value,name){const fixed=tools.title(tools.trim(name),'-');value=(types.isNothing(value)?'':tools.trim(types.toString(value)));if(fixed==='Content-Type'){this.setContentType(value)}else if(fixed==='Content-Disposition'){this.setContentDisposition(value)}else if(fixed==='Vary'){this.setVary(value)}else{if(value){responseHeaders[fixed]=value}else{delete responseHeaders[fixed]};changed[fixed]=null}},this);const changedKeys=types.keys(changed);if(changedKeys.length){this.onHeadersChanged(new doodad.Event({headers:changedKeys}))}}),clearHeaders:doodad.PUBLIC(function clearHeaders(names){let changedHeaders;if(names){if(!types.isArray(names)){names=[names]};changedHeaders=[];for(let i=0;i<names.length;i++){const fixed=tools.title(tools.trim(names[i]),'-');if(fixed in this.headers){changedHeaders.push(fixed);if(fixed==='Content-Type'){types.setAttribute(this,'contentType',null)}else if(fixed==='Content-Disposition'){types.setAttribute(this,'contentDisposition',null)}else if(fixed==='Vary'){this.__varyingHeaders=null};delete this.headers[fixed]}}}else{changedHeaders=types.keys(this.headers);types.setAttributes(this,{headers:tools.nullObject(),contentType:null,})};if(changedHeaders.length){this.onHeadersChanged(new doodad.Event({headers:changedHeaders}))}}),setContentType:doodad.PUBLIC(function setContentType(contentType,options){options=tools.nullObject(options);if(types.isString(contentType)){contentType=http.parseContentTypeHeader(contentType)};const encoding=options.encoding;if(encoding){contentType=contentType.set({params:{charset:encoding}})};types.setAttribute(this,'contentType',contentType);this.headers['Content-Type']=contentType.toString();this.onHeadersChanged(new doodad.Event({headers:['Content-Type']}));return this.contentType}),setContentDisposition:doodad.PUBLIC(function setContentDisposition(contentDisposition){if(types.isString(contentDisposition)){contentDisposition=http.parseContentDispositionHeader(contentDisposition)};types.setAttribute(this,'contentDisposition',contentDisposition);this.headers['Content-Disposition']=(contentDisposition&&contentDisposition.toString()||"");this.onHeadersChanged(new doodad.Event({headers:['Content-Disposition']}));return this.contentDisposition}),setVary:doodad.PUBLIC(function setVary(names){if(!this.__varyingHeaders){this.__varyingHeaders=tools.nullObject()};tools.forEach(names.split(','),function(name){const fixed=tools.title(tools.trim(name),'-');this.__varyingHeaders[fixed]=true},this);const vary=tools.reduce(this.__varyingHeaders,function(result,dummy,name){return result+', '+name},"");this.headers['Vary']=vary.slice(2);this.onHeadersChanged(new doodad.Event({headers:['Vary']}));return vary}),storeHeaders:doodad.PUBLIC(function storeHeaders(storeObj,names){storeObj.addHeaders(this.getHeaders(names))}),})));http.REGISTER(doodad.BASE(doodad.Object.$extend(httpMixIns.Headers,{$TYPE_NAME:'Response',$TYPE_UUID:'' +'d2484a8d-6b38-4cdc-a9ea-02cd6035d2c4',onGetStream:doodad.EVENT(false),onError:doodad.ERROR_EVENT(),onStatus:doodad.EVENT(false),onSendHeaders:doodad.EVENT(false),__ending:doodad.PROTECTED(false),ended:doodad.PUBLIC(doodad.PERSISTENT(doodad.READ_ONLY(false))),request:doodad.PUBLIC(doodad.READ_ONLY(null)),status:doodad.PUBLIC(doodad.READ_ONLY(types.HttpStatus.OK)),message:doodad.PUBLIC(doodad.READ_ONLY('OK')),statusData:doodad.PUBLIC(doodad.READ_ONLY(null)),trailers:doodad.PROTECTED(null),headersSent:doodad.PUBLIC(doodad.READ_ONLY(false)),trailersSent:doodad.PUBLIC(doodad.READ_ONLY(false)),__pipes:doodad.PROTECTED(null),stream:doodad.PROTECTED(null),getStream:doodad.PUBLIC(doodad.ASYNC(doodad.MUST_OVERRIDE())),clear:doodad.PUBLIC(doodad.MUST_OVERRIDE()),respondWithStatus:doodad.PUBLIC(doodad.ASYNC(doodad.MUST_OVERRIDE())),respondWithError:doodad.PUBLIC(doodad.ASYNC(doodad.MUST_OVERRIDE())),reset:doodad.PUBLIC(function reset(){if(!this.ended){if(this.__handlersStates){const handlers=this.request.getHandlers().filter(function(handler){return!types.isFunction(handler)});this.clearEvents(handlers)};types.setAttributes(this,{headers:tools.nullObject(),trailers:tools.nullObject(),__pipes:[],stream:null,})}}),create:doodad.OVERRIDE(function create(request){this._super();types.setAttribute(this,'request',request);this.reset()}),setContentType:doodad.OVERRIDE(function setContentType(contentType,options){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.headersSent){throw new types.NotAvailable("Can't add new headers because headers have been sent to the client.")};contentType=this.request.getAcceptables(contentType,options)[0];if(!contentType){throw new types.HttpError(types.HttpStatus.NotAcceptable)};return this._super(contentType,options)}),addHeader:doodad.OVERRIDE(function addHeader(name,value){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.headersSent){throw new types.NotAvailable("Can't add new headers because headers have been sent to the client.")};this._super(name,value);this.request.setFullfilled(true)}),addHeaders:doodad.OVERRIDE(function addHeaders(headers){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.headersSent){throw new types.NotAvailable("Can't add new headers because headers have been sent to the client.")};this._super(headers);this.request.setFullfilled(true)}),clearHeaders:doodad.OVERRIDE(function clearHeaders(names){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.headersSent){throw new types.NotAvailable("Can't clear headers because they have been sent to the client.")};this._super(names)}),addTrailer:doodad.PUBLIC(function addTrailer(name,value){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.trailersSent){throw new types.NotAvailable("Can't add new trailers because trailers have been sent and the request has ended.")};const responseTrailers=this.trailers;const fixed=tools.title(tools.trim(name),'-');value=(types.isNothing(value)?'':tools.trim(types.toString(value)));if(value){responseTrailers[fixed]=value}else{delete responseTrailers[fixed]};this.onHeadersChanged(new doodad.Event({headers:[fixed],areTrailers:true}));this.request.setFullfilled(true)}),addTrailers:doodad.PUBLIC(function addTrailers(trailers){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};if(this.trailersSent){throw new types.NotAvailable("Can't add new trailers because trailers have been sent and the request has ended.")};const responseTrailers=this.trailers;const changed=tools.nullObject();tools.forEach(trailers,function(value,name){const fixed=tools.title(tools.trim(name),'-');value=(types.isNothing(value)?'':tools.trim(types.toString(value)));if(value){responseTrailers[fixed]=value}else{delete responseTrailers[fixed]};changed[fixed]=null});const changedKeys=types.keys(changed);if(changedKeys.length){this.onHeadersChanged(new doodad.Event({headers:changedKeys,areTrailers:true}))};this.request.setFullfilled(true)}),clearTrailers:doodad.PUBLIC(function clearTrailers(names){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};let changedTrailers;if(names){if(!types.isArray(names)){names=[names]};changedTrailers=[];for(let i=0;i<names.length;i++){const fixed=tools.title(tools.trim(names[i]),'-');if(fixed in this.trailers){changedTrailers.push(fixed);delete this.trailers[fixed]}}}else{changedTrailers=types.keys(this.tailers);types.setAttributes(this,{trailers:tools.nullObject(),})};if(changedTrailers.length){this.onHeadersChanged(new doodad.Event({headers:changedTrailers,areTrailers:true}))}}),setStatus:doodad.PUBLIC(function setStatus(status,message){if(this.ended){throw new server.EndOfRequest()};if(this.headersSent){throw new types.NotAvailable("Can't respond with a new status because the headers have already been sent to the client.")};types.setAttributes(this,{status:status||types.HttpStatus.OK,message:message||null,});if(status){this.request.setFullfilled(true)}}),addPipe:doodad.PUBLIC(function addPipe(stream,options){if(this.ended){throw new server.EndOfRequest()};if(!this.__pipes){throw new types.NotAvailable("'addPipe' is not available because pipes have already been proceed.")};options=tools.nullObject(options);const headers=options.headers;if(headers){this.addHeaders(headers)};const pipe={stream:stream,options:options};if(options.unshift){this.__pipes.unshift(pipe)}else{this.__pipes.push(pipe)}}),clearPipes:doodad.PUBLIC(function clearPipes(){if(this.ended){throw new server.EndOfRequest()};if(!this.__pipes){throw new types.NotAvailable("'clearPipes' is not available because pipes have already been proceed.")};this.__pipes=[]}),hasStream:doodad.PUBLIC(function hasStream(){return!!this.stream}),hasContent:doodad.PUBLIC(function hasContent(){return this.hasStream()||!types.isNothing(this.status)||!types.isEmpty(this.headers)||!types.isEmpty(this.trailers)}),})));http.REGISTER(doodad.EXPANDABLE(doodad.Object.$extend(mixIns.RawEvents,{$TYPE_NAME:'HandlerState',$TYPE_UUID:'' +'42434d37-95b7-4c7c-96e6-58f11a7dea4b',parent:doodad.PUBLIC(doodad.READ_ONLY(null)),matcherResult:doodad.PUBLIC(doodad.READ_ONLY(null)),mimeTypes:doodad.PUBLIC(doodad.READ_ONLY(null)),url:doodad.PUBLIC(doodad.READ_ONLY(null)),mustDestroy:doodad.PUBLIC(doodad.READ_ONLY(false)),})));http.REGISTER(doodad.BASE(doodad.Object.$extend(httpMixIns.Headers,serverMixIns.Request,{$TYPE_NAME:'Request',$TYPE_UUID:'' +'2d14fc8f-c3ee-4881-aeec-a8546793a586',onGetStream:doodad.EVENT(false),__ending:doodad.PROTECTED(false),ended:doodad.PUBLIC(doodad.PERSISTENT(doodad.READ_ONLY(false))),response:doodad.PUBLIC(doodad.READ_ONLY(null)),verb:doodad.PUBLIC(doodad.READ_ONLY(null)),url:doodad.PUBLIC(doodad.READ_ONLY(null)),data:doodad.PUBLIC(doodad.READ_ONLY(null)),clientCrashed:doodad.PUBLIC(doodad.READ_ONLY(false)),clientCrashRecovery:doodad.PUBLIC(doodad.READ_ONLY(false)),contentType:doodad.PUBLIC(doodad.READ_ONLY(null)),createResponse:doodad.PROTECTED(doodad.MUST_OVERRIDE()),stream:doodad.PROTECTED(null),__streamOptions:doodad.PROTECTED(null),getStream:doodad.PUBLIC(doodad.ASYNC(doodad.MUST_OVERRIDE())),__pipes:doodad.PROTECTED(null),__waitQueue:doodad.PROTECTED(null),__redirectsCount:doodad.PROTECTED(0),__parsedAccept:doodad.PROTECTED(null),id:doodad.PUBLIC(doodad.READ_ONLY(null)),__handlersStates:doodad.PROTECTED(null),currentHandler:doodad.PUBLIC(doodad.READ_ONLY(null)),__contentEncodings:doodad.PROTECTED(null),__fullfilled:doodad.PROTECTED(false),$__actives:doodad.PROTECTED(doodad.TYPE(0)),$__active_requests:doodad.PROTECTED(doodad.TYPE(new types.Set())),$__total:doodad.PROTECTED(doodad.TYPE(0)),$__successful:doodad.PROTECTED(doodad.TYPE(0)),$__redirected:doodad.PROTECTED(doodad.TYPE(0)),$__failed:doodad.PROTECTED(doodad.TYPE(null)),$__aborted:doodad.PROTECTED(doodad.TYPE(0)),$getStats:doodad.PUBLIC(doodad.TYPE(function $getStats(){return tools.nullObject({actives:this.$__actives,total:this.$__total,successful:this.$__successful,redirected:this.$__redirected,failed:this.$__failed,aborted:this.$__aborted,})})),$getActives:doodad.PUBLIC(doodad.TYPE(function $getActives(){const actives=[];this.$__active_requests.forEach(function(request){actives[actives.length]=request.url.toString()});return actives})),$clearStats:doodad.PUBLIC(doodad.TYPE(function $clearStats(){this.$__total=0;this.$__successful=0;this.$__redirected=0;this.$__failed=tools.nullObject();this.$__aborted=0})),$create:doodad.OVERRIDE(function $create(){this._super();this.$clearStats()}),reset:doodad.PUBLIC(function reset(){if(!this.ended){if(this.__handlersStates){const handlers=this.getHandlers().filter(function(handler){return!types.isFunction(handler)});this.response.clearEvents(handlers);this.clearEvents(handlers);tools.forEach(this.__handlersStates,function(state,handler){if(state.mustDestroy){types.DESTROY(handler);types.DESTROY(state)}})};types.setAttributes(this,{__pipes:[],__streamOptions:tools.nullObject(),__waitQueue:[],__handlersStates:new types.Map(),stream:null,__fullfilled:false,__contentEncodings:[],});this.onSanitize.stackSize=60}}),create:doodad.OVERRIDE(function create(server,verb,url,headers,responseArgs){const type=types.getType(this);if(type.$__total>=types.getSafeIntegerBounds().max){type.$clearStats()};type.$__total++;type.$__actives++;if(type.$__active_requests){type.$__active_requests.add(this)};try{if(types.isString(url)){url=files.Url.parse(url)};if(root.DD_ASSERT){root.DD_ASSERT&&root.DD_ASSERT(types._implements(server,httpMixIns.Server),"Invalid server.");root.DD_ASSERT(types.isString(verb),"Invalid verb.");root.DD_ASSERT(types._instanceof(url,files.Url),"Invalid URL.");root.DD_ASSERT(types.isObject(headers),"Invalid headers.")};this._super();types.setAttributes(this,{server:server,verb:verb.toUpperCase(),data:tools.nullObject(),id:tools.generateUUID(),});this.addHeaders(headers);let host=this.getHeader('Host');if(host){host=files.Url.parse(server.protocol+'://'+host+'/')};url=files.Url.parse(url);if(host){url=host.combine(url)};this.__redirectsCount=types.toInteger(url.args.get('redirects',true));if(!types.isFinite(this.__redirectsCount)||(this.__redirectsCount<0)){this.__redirectsCount=0};const clientCrashed=types.toBoolean(url.args.get('crashReport',false));const clientCrashRecovery=types.toBoolean(url.args.get('crashRecovery',false));url=url.removeArgs(['redirects','crashReport','crashRecovery']);this.reset();types.setAttributes(this,{url:url,clientCrashed:clientCrashed,clientCrashRecovery:(clientCrashRecovery&&!clientCrashed),__parsedAccept:http.parseAcceptHeader(this.getHeader('Accept')||'*/*'),response:this.createResponse.apply(this,responseArgs||[]),})}catch(ex){type.$__actives--;const failed=type.$__failed;const status=types.HttpStatus.InternalError;if(types.has(failed,status)){failed[status]++}else{failed[status]=1};throw ex}}),destroy:doodad.OVERRIDE(function destroy(){this.sanitize();tools.forEach(this.__handlersStates,function(state,handler){if(state.mustDestroy){types.DESTROY(handler);types.DESTROY(state)}});types.DESTROY(this.response);const type=types.getType(this);type.$__actives--;if(type.$__active_requests){type.$__active_requests.delete(this)};this._super()}),hasHandler:doodad.PUBLIC(function hasHandler(handler){const handlers=this.__handlersStates.keys();return tools.some(handlers,function someHandler(hndlr){return(types.isJsFunction(hndlr)?(hndlr===handler):types.isLike(hndlr,handler))})}),getHandlers:doodad.PUBLIC(function getHandlers(handler){const handlers=this.__handlersStates.keys();if(handler){return tools.filter(handlers,function someHandler(hndlr){return(types.isJsFunction(hndlr)?(hndlr===handler):types.isLike(hndlr,handler))})}else{return types.toArray(handlers)}}),getHandlerState:doodad.PUBLIC(function getHandlerState(handler){let state=null;if(types.isNothing(handler)){handler=this.currentHandler};if(types.isJsFunction(handler)||types._implements(handler,httpMixIns.Handler)){const states=this.__handlersStates;state=states.get(handler);if(!state){this.applyHandlerState(handler);state=states.get(handler)}};return state}),applyHandlerState:doodad.PUBLIC(function applyHandlerState(handler,stateProto){if(types.isNothing(handler)){handler=this.currentHandler}else if(types.isString(handler)){handler=namespaces.get(handler)};root.DD_ASSERT&&root.DD_ASSERT(types.isJsFunction(handler)||types._implements(handler,httpMixIns.Handler),"Invalid handler.");const handlerType=types.getType(handler)||handler;let hndlrs;if(types.isType(handler)){hndlrs=tools.filter(this.__handlersStates.keys(),function(hndlr){return!types.isType(hndlr)&&types.isLike(hndlr,handler)})}else{hndlrs=[handler]};let globalState=null;const states=this.__handlersStates;tools.forEach(hndlrs,function(hndlr){let state=states.get(hndlr);if(!state){if(!globalState){globalState=this.server.getGlobalHandlerState(handlerType)};state=new globalState();states.set(hndlr,state)};if(stateProto){state.extend(stateProto).create()}},this)}),getAcceptables:doodad.PUBLIC(function getAcceptables(contentTypes,options){options=tools.nullObject(options);const handlerState=options.handler&&this.getHandlerState(options.handler);const handlerTypes=handlerState&&handlerState.mimeTypes;const acceptableTypes=this.__parsedAccept;const allowedTypes=handlerTypes||acceptableTypes;const hasHandlerTypes=!!handlerTypes;const hasAcceptableTypes=!!acceptableTypes;const discardWilcards=hasHandlerTypes&&hasAcceptableTypes&&!tools.some(acceptableTypes,function(mimeType){return(mimeType.type==='*')&&(mimeType.subtype==='*')});if(!contentTypes){return allowedTypes};if(!types.isArray(contentTypes)){contentTypes=[contentTypes]};const acceptedTypes=[];if(allowedTypes){for(let i=0;i<contentTypes.length;i++){let contentType=contentTypes[i];if(types.isString(contentType)){contentType=http.parseContentTypeHeader(contentType)};if(contentType.weight>0.0){const result=tools.reduce(allowedTypes,function(result,handlerType,index){if(!discardWilcards||!((handlerType.type==='*')&&(handlerType.subtype==='*'))){const score=http.compareMimeTypes(handlerType,contentType);if(score>result.score){result.score=score;result.mimeType=handlerType;result.index=index}};return result},{mimeType:null,score:0,index:-1});if(result.mimeType){const newParams=tools.complete({},result.mimeType.params,contentType.params);const newContentType=contentType.set({weight:result.mimeType.weight,params:newParams});newContentType.customData.index=result.index;acceptedTypes.push(newContentType)}}}};acceptedTypes.sort(function(type1,type2){if(type1.weight>type2.weight){return-1}else if(type1.weight<type2.weight){return 1}else if(type1.customData.index>type2.customData.index){return 1}else if(type1.customData.index<type2.customData.index){return-1}else{return 0}});return acceptedTypes}),redirectClient:doodad.PUBLIC(doodad.ASYNC(function redirectClient(url,isPermanent){if(this.ended){throw new server.EndOfRequest()};const maxRedirects=this.server.options.maxRedirects||5;if(this.response.headersSent){throw new types.NotAvailable("Unable to redirect because HTTP headers are already sent.")}else if(this.__redirectsCount>=maxRedirects){return this.end()}else{this.__redirectsCount++;url=this.url.set({file:null}).combine(url);const status=(isPermanent?types.HttpStatus.MovedPermanently:types.HttpStatus.TemporaryRedirect);return this.response.respondWithStatus(status,null,{'Location':url.toString({args:{redirects:this.__redirectsCount,},}),})}})),redirectServer:doodad.PUBLIC(doodad.ASYNC(function redirectServer(url,options){if(this.ended){throw new server.EndOfRequest()};options=tools.nullObject(options);const maxRedirects=this.server.options.maxRedirects||5;if(this.response.headersSent){throw new types.NotAvailable("Unable to redirect because HTTP headers are already sent.")}else if(this.__redirectsCount>=maxRedirects){return this.end()}else{this.response.clear();this.__redirectsCount++;url=this.url.set({file:null}).combine(url);types.setAttribute(this,'url',url);const verb=options.verb;if(verb){types.setAttribute(this,'verb',verb)};const data=options.data;if(data){tools.extend(this.data,data)};this.reset();this.response.reset();throw new http.ProceedNewHandlers(this.server.handlersOptions)}})),addPipe:doodad.PUBLIC(function addPipe(stream,options){if(this.ended){throw new server.EndOfRequest()};if(!this.__pipes){throw new types.NotAvailable("'addPipe' is not available because pipes have already been proceed.")};options=tools.nullObject(options);const pipe={stream:stream,options:options};if(options.unshift){this.__pipes.unshift(pipe)}else{this.__pipes.push(pipe)}}),clearPipes:doodad.PUBLIC(function clearPipes(){if(this.ended){throw new server.EndOfRequest()};if(!this.__pipes){throw new types.NotAvailable("'clearPipes' is not available because pipes have already been proceed.")};this.__pipes=[]}),setStreamOptions:doodad.PUBLIC(function setStreamOptions(options){if(this.ended){throw new server.EndOfRequest()};const accept=types.get(this.__streamOptions,'accept')||[];tools.extend(this.__streamOptions,options);if(types.get(options,'accept')){let newAccept=options.accept;if(!types.isArray(newAccept)){newAccept=[newAccept]};this.__streamOptions.accept=tools.append(accept,newAccept.map(function(value){return(types.isString(value)?http.parseAcceptHeader(value)[0]:value)}))}}),hasStream:doodad.PUBLIC(function hasStream(){return!!this.stream}),isFullfilled:doodad.PUBLIC(function isFullfilled(){return this.__fullfilled}),setFullfilled:doodad.PUBLIC(function setFullfilled(fullfilled){this.__fullfilled=!!fullfilled}),resolve:doodad.PUBLIC(doodad.ASYNC(function resolve(url,type){if(this.ended){throw new server.EndOfRequest()};if(types.isString(type)){const tmp=namespaces.get(type);if(!tmp){throw new types.ValueError("Unknown type : '~0~'.",[type])};type=tmp};if(!types._implements(type,httpMixIns.Handler)){throw new types.ValueError("Invalid handler : '~0~'.",[types.getTypeName(type)||'<unknown>'])};return this.proceed(this.server.handlersOptions,{resolve:url,handlerType:type}).then(function(resolved){if(resolved&&type){resolved=resolved.filter(obj=>types.isLike(obj.handler,type))};if(resolved&&resolved.length){return resolved};return null})})),proceed:doodad.PUBLIC(doodad.ASYNC(function proceed(handlersOptions,options){const Promise=types.getPromise();if(this.ended){throw new server.EndOfRequest()};if(!types.isArray(handlersOptions)){handlersOptions=[handlersOptions]};const requestedUrl=this.url;const urlToResolve=types.get(options,'resolve',null);const handlerType=types.get(options,'handlerType',null);const runHandler=function _runHandler(handlerOptions,resolved){handlerOptions=tools.nullObject(handlerOptions);let handler=handlerOptions.handler;const acceptedMimeTypes=this.getAcceptables(handlerOptions.mimeTypes||['*/*']);if(acceptedMimeTypes&&acceptedMimeTypes.length){const parentState=handlerOptions.parent&&this.getHandlerState(handlerOptions.parent);const matcherResult=handlerOptions.matcherResult;const stateUrl=matcherResult&&(parentState&&parentState.url?parentState.url.combine(matcherResult.url,{isRelative:true}):requestedUrl.set({url:matcherResult.url}));let mustDestroy=false;if(types.isType(handler)){handler=handler.$createInstance(handlerOptions);mustDestroy=true};const handlerState=this.getHandlerState(handler);const stateValues={parent:handlerOptions.parent||null,matcherResult:matcherResult||null,mimeTypes:acceptedMimeTypes||null,url:stateUrl||null,mustDestroy:mustDestroy,};types.setAttributes(handlerState,stateValues,null,_shared.SECRET);const remaining=matcherResult&&matcherResult.urlRemaining;const full=(matcherResult?matcherResult.full:false);if(types._implements(handler,httpMixIns.Handler)){if(urlToResolve){if(full){const resolvedUrl=(remaining?stateUrl.combine(remaining):stateUrl);resolved.push({handler,url:resolvedUrl})};if(types.isImplemented(handler,'resolve')){return handler.resolve(this,handlerType).then(function(result){tools.append(resolved,result)})}}else{types.setAttribute(this,'currentHandler',handler);return handler.execute(this)}}else if(types.isJsFunction(handler)){if(!urlToResolve){types.setAttribute(this,'currentHandler',handler);return handler(this)}}else{throw new types.ValueError("Invalid handler.")}};return null};const loopProceedHandler=function _loopProceedHandler(handlersOptions,index,resolved){if(!this.ended){if(index<handlersOptions.length){const handlerOptions=handlersOptions[index];return Promise.resolve(runHandler.call(this,handlerOptions,resolved)).catch(this.catchError,this).then(function proceedNext(dummy){return loopProceedHandler.call(this,handlersOptions,index+1,resolved)},null,this)};if(urlToResolve){return resolved}};return undefined};if(urlToResolve){types.setAttribute(this,'url',urlToResolve);return Promise.resolve(loopProceedHandler.call(this,handlersOptions,0,[])).nodeify(function(err,result){types.setAttribute(this,'url',requestedUrl);if(err){throw err};return result},this)}else{return Promise.resolve(loopProceedHandler.call(this,handlersOptions,0,null))}})),catchError:doodad.OVERRIDE(function catchError(ex){const max=5;let count=0;const _catchError=function _catchError(ex){if(count>=max){try{doodad.trapException(ex)}catch(o){};throw ex}else if(_shared.DESTROYED(this)){if(ex.critical||!ex.bubble){throw ex}}else{count++;if(types._instanceof(ex,types.HttpError)){return this.response.respondWithStatus(ex.code).catch(_catchError,this)}else if(types._instanceof(ex,http.ProceedNewHandlers)){return this.proceed(ex.handlersOptions,ex.options).catch(_catchError,this)}else if(types._instanceof(ex,http.StreamAborted)){}else if(types._instanceof(ex,server.EndOfRequest)){}else if(ex.critical){throw ex}else if(ex.bubble){return this.end(true).catch(_catchError,this)}else{return this.response.respondWithError(ex).catch(_catchError,this)}};return undefined};return _catchError.call(this,ex)}),waitFor:doodad.PUBLIC(function waitFor(promise){if(this.ended&&!this.__ending){throw new server.EndOfRequest()};root.DD_ASSERT&&root.DD_ASSERT(types.isPromise(promise),"Invalid promise.");this.__waitQueue.push(promise)}),acceptContentEncodings:doodad.PUBLIC(function acceptContentEncodings(encodings){if(this.ended){throw new server.EndOfRequest()};if(!types.isArray(encodings)){encodings=[encodings]};tools.append(this.__contentEncodings,encodings.map(encoding=>encoding.toLowerCase()))}),})));httpMixIns.REGISTER(doodad.MIX_IN(doodad.Class.$extend({$TYPE_NAME:'HandlersContainer',$TYPE_UUID:'' +'adb3c84c-f6c7-4670-8aa6-1b6e0586c989',prepareHandlersOptions:doodad.PROTECTED(function prepareHandlersOptions(server,handlersOptions){if(!types.isArray(handlersOptions)){handlersOptions=[handlersOptions]};return tools.map(handlersOptions,function(handlerOptions){let handler;if(types.isJsObject(handlerOptions)){handlerOptions=tools.nullObject(handlerOptions);handler=handlerOptions.handler}else if(types.isJsFunction(handlerOptions)){handler=handlerOptions;handlerOptions=tools.nullObject(types.get(handler,'options'),{handler:handler})}else{throw new types.ValueError("Invalid handler options.")};if(types.isString(handler)){handler=namespaces.get(handler)};const isJsFunction=types.isJsFunction(handler);const handlerType=(isJsFunction?handler:types.getType(handler));if(!isJsFunction&&!types._implements(handlerType,httpMixIns.Handler)){throw new types.ValueError("Invalid handler type '~0~'.",[types.getTypeName(handler)])};handlerOptions.parent=this;handlerOptions.handler=handler;if(isJsFunction){handlerOptions=httpMixIns.Handler.$prepare(handlerOptions);if(handler.$prepare){handlerOptions=handler.$prepare(handlerOptions)};handler.options=handlerOptions}else{handlerOptions=handlerType.$prepare(handlerOptions);if(!types.isType(handler)){tools.extend(handler.options,handlerOptions)}};return handlerOptions},this)}),})));httpMixIns.REGISTER(doodad.MIX_IN(serverMixIns.Server.$extend(httpMixIns.HandlersContainer,{$TYPE_NAME:'Server',$TYPE_UUID:'' +'170f8731-7495-48de-926a-14fab8f0383f',protocol:doodad.PUBLIC(doodad.READ_ONLY(null)),handlersOptions:doodad.PUBLIC(doodad.READ_ONLY(null)),options:doodad.PUBLIC(doodad.READ_ONLY(null)),})));httpMixIns.REGISTER(doodad.MIX_IN(doodad.Class.$extend(mixIns.Creatable,serverMixIns.Response,{$TYPE_NAME:'Handler',$TYPE_UUID:'' +'d2a2868e-00e7-44b5-a250-a812959d6772',$applyGlobalHandlerStates:doodad.PUBLIC(doodad.METHOD()),$prepare:doodad.PUBLIC(function $prepare(options){options=tools.nullObject(options);let val;val=options.depth;if(!types.isNothing(val)){val=types.toInteger(val)};options.depth=val;val=options.mimeTypes;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,function(typ){return http.parseContentTypeHeader(typ)})};options.mimeTypes=val;val=options.extensions;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,function(ext){return types.toString(ext).toLowerCase()})};options.extensions=val;val=options.verbs;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,function(verb){return types.toString(verb).toUpperCase()})};options.verbs=val;val=options.caseSensitive;if(!types.isNothing(val)){val=types.toBoolean(val)};options.caseSensitive=val;const parentOptions=options.parent.options;options.depth=(types.isNothing(options.depth)?(types.isNothing(parentOptions.depth)?0:parentOptions.depth):options.depth);options.extensions=(options.extensions||parentOptions.extensions)&&tools.unique(options.extensions,parentOptions.extensions);options.verbs=(options.verbs||parentOptions.verbs)&&tools.unique(options.verbs,parentOptions.verbs);options.caseSensitive=(types.isNothing(options.caseSensitive)?!!parentOptions.caseSensitive:options.caseSensitive);return options}),create:doodad.OVERRIDE(function create(options){this._super();types.setAttribute(this,'options',options||tools.nullObject())}),resolve:doodad.PUBLIC(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),})));httpMixIns.REGISTER(doodad.MIX_IN(httpMixIns.Handler.$extend(httpMixIns.HandlersContainer,{$TYPE_NAME:'Routes',$TYPE_UUID:'' +'e8d5d3b5-8e23-411e-8725-100f71eae661',addRoutes:doodad.PUBLIC(doodad.MUST_OVERRIDE()),createHandlers:doodad.PUBLIC(doodad.MUST_OVERRIDE()),resolve:doodad.OVERRIDE(doodad.MUST_OVERRIDE()),})));httpMixIns.REGISTER(doodad.MIX_IN(httpMixIns.Handler.$extend({$TYPE_NAME:'Page',$TYPE_UUID:'' +'22412b94-6841-4db3-9036-9459cb31b26f',__knownVerbs:doodad.PROTECTED(doodad.ATTRIBUTE(['HEAD','GET','POST','PUT','DELETE','TRACE','CONNECT','OPTIONS'],extenders.UniqueArray)),__allowedVerbs:doodad.PROTECTED(doodad.READ_ONLY(null)),execute_HEAD:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_GET:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_POST:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_PUT:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_DELETE:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_TRACE:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_CONNECT:doodad.PROTECTED(doodad.ASYNC(doodad.NOT_IMPLEMENTED())),execute_OPTIONS:doodad.PROTECTED(doodad.ASYNC(function(request){let allowed=this.__allowedVerbs;if(!allowed){allowed=tools.filter(this.__knownVerbs,this.isAllowed,this);types.setAttribute(this,'__allowedVerbs',allowed)};request.response.addHeaders({Allow:allowed.join(',')})})),execute:doodad.OVERRIDE(function execute(request){const method='execute_'+request.verb;if(types.isImplemented(this,method)){return this[method](request)}else{return request.response.respondWithStatus(types.HttpStatus.NotImplemented)}}),isAllowed:doodad.PUBLIC(function(verb){return types.isImplemented(this,'execute_'+verb.toUpperCase())}),})));http.REGISTER(doodad.Object.$extend(httpMixIns.Page,{$TYPE_NAME:'NullPage',$TYPE_UUID:'' +'0bd7c9d2-ad12-45aa-9788-7e77f363d85c',}));http.REGISTER(doodad.Object.$extend(httpMixIns.Page,{$TYPE_NAME:'StatusPage',$TYPE_UUID:'' +'dac7c8b0-adae-4aef-a812-14636d385396',$prepare:doodad.OVERRIDE(function $prepare(options){types.getDefault(options,'depth',0);options=this._super(options);options.status=types.toInteger(options.status);return options}),execute_HEAD:doodad.OVERRIDE(function execute_HEAD(request){return request.response.respondWithStatus(this.options.status)}),execute_GET:doodad.OVERRIDE(function execute_GET(request){return request.response.respondWithStatus(this.options.status)}),}));http.REGISTER(doodad.BASE(doodad.Object.$extend(httpMixIns.Page,{$TYPE_NAME:'StaticPage',$TYPE_UUID:'' +'edca7324-cf65-4a87-9777-a815c72deafb',createStream:doodad.PUBLIC(doodad.ASYNC(doodad.MUST_OVERRIDE())),execute_HEAD:doodad.OVERRIDE(doodad.MUST_OVERRIDE()),execute_GET:doodad.OVERRIDE(doodad.MUST_OVERRIDE()),})));http.REGISTER(doodad.BASE(http.StaticPage.$extend({$TYPE_NAME:'FileSystemPage',$TYPE_UUID:'' +'2555114e-25c8-4799-85b0-f955472154f6',getSystemPath:doodad.PUBLIC(doodad.MUST_OVERRIDE()),})));http.REGISTER(doodad.Object.$extend(httpMixIns.Handler,{$TYPE_NAME:'RedirectHandler',$TYPE_UUID:'' +'e16db956-ccb3-4b46-b8d3-546fbc557d9c',$prepare:doodad.OVERRIDE(function $prepare(options){types.getDefault(options,'depth',0);options=this._super(options);let val;val=options.targetUrl;if(types.isString(val)){val=files.Url.parse(val)};options.targetUrl=val;options.internal=types.toBoolean(options.internal);options.permanent=types.toBoolean(options.permanent);return options}),execute:doodad.OVERRIDE(function execute(request){const handlerState=request.getHandlerState(this);const remaining=handlerState.matcherResult&&handlerState.matcherResult.urlRemaining;const baseUrl=handlerState.url.combine(this.options.targetUrl).set({isRelative:false});const url=(remaining?baseUrl.combine(remaining):baseUrl);if(this.options.internal){return request.redirectServer(url)}else{return request.redirectClient(url,this.options.permanent)}}),resolve:doodad.OVERRIDE(function resolve(request,type){if(this.options.internal){const handlerState=request.getHandlerState(this);const remaining=handlerState.matcherResult&&handlerState.matcherResult.urlRemaining;const baseUrl=handlerState.url.combine(this.options.targetUrl).set({isRelative:false});const url=(remaining?baseUrl.combine(remaining):baseUrl);return request.resolve(url,type)};return undefined}),}));http.REGISTER(doodad.Object.$extend(httpMixIns.Handler,{$TYPE_NAME:'CrossOriginHandler',$TYPE_UUID:'' +'a3bf4e0d-c3b3-4ce2-9a8d-c41c3ffff518',$prepare:doodad.OVERRIDE(function $prepare(options){types.getDefault(options,'depth',Infinity);options=this._super(options);let val;val=options.allowedOrigins;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,tools.toString)};options.allowedOrigins=val||[];val=options.allowedHeaders;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,tools.toString)};options.allowedHeaders=val||[];val=options.exposedHeaders;if(!types.isNothing(val)){if(!types.isArray(val)){val=[val]};val=tools.map(val,tools.toString)};options.exposedHeaders=val||[];options.allowCredentials=types.toBoolean(options.allowCredentials);val=options.maxAge;options.maxAge=(types.isNothing(val)?null:types.toInteger(val)||null);return options}),execute_OPTIONS:doodad.PROTECTED(doodad.ASYNC(function execute_OPTIONS(request){const cors=request.getHeader('Origin');if(cors){const allowedOrigins=this.options.allowedOrigins;if(allowedOrigins.length&&(tools.indexOf(allowedOrigins,cors)<0)){return request.end()};const allowCredentials=this.options.allowCredentials;const wantedMethod=request.getHeader('Access-Control-Request-Method');if(!wantedMethod){return request.end()};const allowedMethods=this.options.verbs||['HEAD','GET','POST'];if(tools.indexOf(allowedMethods,wantedMethod)<0){return request.end()};let wantedHeaders=request.getHeader('Access-Control-Request-Headers');const allowedHeaders=this.options.allowedHeaders;if(wantedHeaders){wantedHeaders=wantedHeaders.split(',').map(function(val){return val.trim().toLowerCase()});const allowedHeadersLC=allowedHeaders.map(function(val){return val.toLowerCase()});if(!tools.every(wantedHeaders,function(val){return(tools.indexOf(allowedHeadersLC,val)>=0)})){return request.end()}};request.response.addHeaders({'Access-Control-Max-Age':(types.isNothing(this.options.maxAge)?'':types.toString(this.options.maxAge)),'Access-Control-Allow-Origin':(allowCredentials||allowedOrigins.length?cors:'*'),'Access-Control-Allow-Credentials':(allowCredentials?'true':'false'),'Access-Control-Allow-Methods':allowedMethods.join(', '),'Access-Control-Allow-Headers':allowedHeaders.join(', '),});request.setFullfilled(false)};return undefined})),execute:doodad.OVERRIDE(function execute(request){const method='execute_'+request.verb;if(types.isImplemented(this,method)){return this[method](request)}else{const cors=request.getHeader('Origin');if(cors){const allowedOrigins=this.options.allowedOrigins;if(allowedOrigins.length&&(tools.indexOf(allowedOrigins,cors)<0)){return request.end()};const allowedMethods=this.options.verbs||['HEAD','GET','POST'];if(tools.indexOf(allowedMethods,request.verb)<0){return request.end()};const allowCredentials=this.options.allowCredentials;const exposedHeaders=this.options.exposedHeaders;request.response.addHeaders({'Access-Control-Allow-Origin':(allowCredentials||allowedOrigins.length?cors:'*'),'Access-Control-Allow-Credentials':(allowCredentials?'true':'false'),'Access-Control-Expose-Headers':exposedHeaders.join(', '),});request.setFullfilled(false)}};return undefined}),}));http.REGISTER(doodad.Object.$extend(httpMixIns.Handler,{$TYPE_NAME:'ContentSecurityPolicyHandler',$TYPE_UUID:'' +'8c7c099c-b5c0-4867-83b6-febda5d8db32',$createPolicy:doodad.PUBLIC(doodad.TYPE(function $createPolicy(){return tools.nullObject({'base-uri':null,'child-src':null,'connect-src':null,'default-src':null,'font-src':null,'form-action':null,'frame-ancestors':null,'frame-src':null,'img-src':null,'manifest-src':null,'media-src':null,'object-src':null,'plugin-types':null, 'require-sri-for':null, 'sandbox':null,'script-src':null,'style-src':null,'worker-src':null,'block-all-mixed-content':null,'upgrade-insecure-requests':null,})})),$updatePolicy:doodad.PUBLIC(doodad.TYPE(function $updatePolicy(policy,value,replace){tools.forEach(tools.trim(value,';',0).split(';'),function(val){const args=val.trim().split(' ');const name=args[0].toLowerCase();if(!(name in policy)){throw new types.Error("Invalid or unknown policy name : '~0~'.",[name])};if(replace||!policy[name]){policy[name]=tools.nullObject()};const obj=policy[name];if(args.length>1){tools.forEach(args.slice(1),function(val){obj[val.trim()]=true})}})})),$getPolicyString:doodad.PUBLIC(doodad.TYPE(function $getPolicyString(policy){let value='';tools.forEach(policy,function(args,name){if(args){value+='; '+name;tools.forEach(args,function(dummy,arg){value+=' '+arg})}});return value.slice(2)})),$applyGlobalHandlerStates:doodad.OVERRIDE(function $applyGlobalHandlerStates(server){this._super(server);const type=this;server.applyGlobalHandlerState(type,{policy:doodad.READ_ONLY(type.$createPolicy()),update:doodad.PUBLIC(function(value,replace){type.$updatePolicy(this.policy,value,replace)}),})}),$prepare:doodad.OVERRIDE(function $prepare(options){types.getDefault(options,'depth',Infinity);options=this._super(options);const val=options.policy;const policy=this.$createPolicy();if(val){this.$updatePolicy(policy,val)};options.policy=this.$getPolicyString(policy);return options}),__onGetStream:doodad.PROTECTED(function __onGetStream(ev){const request=ev.handlerData[0];const type=types.getType(this);const state=request.getHandlerState(this);const contentType=request.getAcceptables(request.response.contentType,{handler:this})[0];if(contentType){state.update(this.options.policy)};const value=type.$getPolicyString(state.policy);request.response.addHeader('Content-Security-Policy',value)}),execute:doodad.OVERRIDE(function(request){request.response.onGetStream.attach(this,this.__onGetStream,null,[request])}),}));http.REGISTER(doodad.Object.$extend(httpMixIns.Handler,{$TYPE_NAME:'UpgradeInsecureRequestsHandler',$TYPE_UUID:'' +'4d1a9e2d-bf42-472a-a246-c1185f6aa22d',$prepare:doodad.OVERRIDE(function $prepare(options){types.getDefault(options,'depth',Infinity);options=this._super(options);options.sslPort=(types.toInteger(options.sslPort)||443);const val=options.sslDomain;options.sslDomain=(types.isNothing(val)?null:types.toString(val));options.hstsSafe=types.toBoolean(options.hstsSafe);options.hstsMaxAge=(types.toInteger(options.hstsMaxAge)||10886400);return options}),execute:doodad.OVERRIDE(function execute(request){const cspState=request.getHandlerState(http.ContentSecurityPolicyHandler);if(!cspState){return undefined};const uirs=request.getHeader('Upgrade-Insecure-Requests');if(this.options.hstsSafe){request.response.addHeader('Strict-Transport-Security','max-age='+types.toString(this.options.hstsMaxAge)+'; preload');cspState.update('block-all-mixed-content')}else{cspState.update('upgrade-insecure-requests')}