Basic server methods transferred to AngelHttp
This commit is contained in:
parent
3527da6f4b
commit
e2af07c813
3 changed files with 409 additions and 428 deletions
|
@ -2,8 +2,8 @@
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="7b89ff1e-1260-4dcf-9c3d-345de0471ea1" name="Default" comment="">
|
<list default="true" id="7b89ff1e-1260-4dcf-9c3d-345de0471ea1" name="Default" comment="">
|
||||||
<change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/lib/src/http/angel_http.dart" />
|
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
|
||||||
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/lib/src/http/angel_http.dart" afterPath="$PROJECT_DIR$/lib/src/http/angel_http.dart" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/lib/src/http/server.dart" afterPath="$PROJECT_DIR$/lib/src/http/server.dart" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/lib/src/http/server.dart" afterPath="$PROJECT_DIR$/lib/src/http/server.dart" />
|
||||||
</list>
|
</list>
|
||||||
<ignored path="$PROJECT_DIR$/.tmp/" />
|
<ignored path="$PROJECT_DIR$/.tmp/" />
|
||||||
|
@ -26,6 +26,8 @@
|
||||||
<favorites_list name="framework" />
|
<favorites_list name="framework" />
|
||||||
</component>
|
</component>
|
||||||
<component name="FileEditorManager">
|
<component name="FileEditorManager">
|
||||||
|
<splitter split-orientation="horizontal" split-proportion="0.5">
|
||||||
|
<split-first>
|
||||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="375">
|
<leaf SIDE_TABS_SIZE_LIMIT_KEY="375">
|
||||||
<file leaf-file-name="service.dart" pinned="false" current-in-tab="false">
|
<file leaf-file-name="service.dart" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/http/service.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/http/service.dart">
|
||||||
|
@ -87,76 +89,18 @@
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="server.dart" pinned="false" current-in-tab="false">
|
<file leaf-file-name="server.dart" pinned="false" current-in-tab="true">
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/http/server.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/http/server.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="409">
|
<state relative-caret-position="-1684">
|
||||||
<caret line="464" column="0" lean-forward="true" selection-start-line="464" selection-start-column="0" selection-end-line="464" selection-end-column="0" />
|
<caret line="380" column="7" lean-forward="false" selection-start-line="380" selection-start-column="7" selection-end-line="380" selection-end-column="7" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#1894#1949#0" expanded="false" />
|
<element signature="e#38#58#0" expanded="true" />
|
||||||
<element signature="e#2304#2311#0" expanded="false" />
|
|
||||||
<element signature="e#2534#2611#0" expanded="false" />
|
|
||||||
<element signature="e#2869#2964#0" expanded="false" />
|
|
||||||
<element signature="e#3252#3306#0" expanded="false" />
|
|
||||||
<element signature="e#3430#3485#0" expanded="false" />
|
|
||||||
<element signature="e#3611#3652#0" expanded="false" />
|
|
||||||
<element signature="e#3866#4128#0" expanded="false" />
|
|
||||||
<element signature="e#5025#5047#0" expanded="false" />
|
|
||||||
<element signature="e#5175#5490#0" expanded="false" />
|
|
||||||
<element signature="e#5601#5948#0" expanded="false" />
|
|
||||||
<element signature="e#6038#6405#0" expanded="false" />
|
|
||||||
<element signature="e#6498#6736#0" expanded="false" />
|
|
||||||
<element signature="e#6740#6807#0" expanded="false" />
|
|
||||||
<element signature="e#6911#7587#0" expanded="false" />
|
|
||||||
<element signature="e#7749#8389#0" expanded="false" />
|
|
||||||
<element signature="e#8501#8536#0" expanded="false" />
|
|
||||||
<element signature="e#8709#8750#0" expanded="false" />
|
|
||||||
<element signature="e#8886#8921#0" expanded="false" />
|
|
||||||
<element signature="e#9006#9723#0" expanded="false" />
|
|
||||||
<element signature="e#9892#10283#0" expanded="false" />
|
|
||||||
<element signature="e#10352#10696#0" expanded="false" />
|
|
||||||
<element signature="e#10837#10854#0" expanded="false" />
|
|
||||||
<element signature="e#11138#11281#0" expanded="false" />
|
|
||||||
<element signature="e#11380#11513#0" expanded="false" />
|
|
||||||
<element signature="e#11731#12311#0" expanded="false" />
|
|
||||||
<element signature="e#12660#13030#0" expanded="false" />
|
|
||||||
<element signature="e#12899#12904#0" expanded="false" />
|
|
||||||
<element signature="e#13199#13224#0" expanded="false" />
|
|
||||||
<element signature="e#14842#14904#0" expanded="false" />
|
|
||||||
<element signature="e#15220#15852#0" expanded="false" />
|
|
||||||
<element signature="e#15313#15437#0" expanded="false" />
|
|
||||||
<element signature="e#15471#15716#0" expanded="false" />
|
|
||||||
<element signature="e#15856#15914#0" expanded="false" />
|
|
||||||
<element signature="e#16148#16323#0" expanded="false" />
|
|
||||||
<element signature="e#16479#16668#0" expanded="false" />
|
|
||||||
<element signature="e#16823#19001#0" expanded="false" />
|
|
||||||
<element signature="e#17538#17589#0" expanded="false" />
|
|
||||||
<element signature="e#19005#19091#0" expanded="false" />
|
|
||||||
<element signature="e#19273#19341#0" expanded="false" />
|
|
||||||
<element signature="e#19443#19482#0" expanded="false" />
|
|
||||||
<element signature="e#19486#19547#0" expanded="false" />
|
|
||||||
<element signature="e#19973#21048#0" expanded="false" />
|
|
||||||
<element signature="e#21100#21178#0" expanded="false" />
|
|
||||||
<element signature="e#21246#21508#0" expanded="false" />
|
|
||||||
<element signature="e#21638#21703#0" expanded="false" />
|
|
||||||
<element signature="e#21766#21960#0" expanded="false" />
|
|
||||||
<element signature="e#21964#21992#0" expanded="false" />
|
|
||||||
<element signature="e#22284#22703#0" expanded="false" />
|
|
||||||
</folding>
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="angel_http.dart" pinned="false" current-in-tab="true">
|
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/http/angel_http.dart">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state relative-caret-position="30">
|
|
||||||
<caret line="2" column="51" lean-forward="false" selection-start-line="2" selection-start-column="51" selection-end-line="2" selection-end-column="51" />
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
</file>
|
|
||||||
<file leaf-file-name="services_test.dart" pinned="false" current-in-tab="false">
|
<file leaf-file-name="services_test.dart" pinned="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/test/services_test.dart">
|
<entry file="file://$PROJECT_DIR$/test/services_test.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
@ -191,6 +135,26 @@
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
</leaf>
|
</leaf>
|
||||||
|
</split-first>
|
||||||
|
<split-second>
|
||||||
|
<leaf>
|
||||||
|
<file leaf-file-name="angel_http.dart" pinned="false" current-in-tab="true">
|
||||||
|
<entry file="file://$PROJECT_DIR$/lib/src/http/angel_http.dart">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state relative-caret-position="300">
|
||||||
|
<caret line="20" column="0" lean-forward="true" selection-start-line="20" selection-start-column="0" selection-end-line="20" selection-end-column="0" />
|
||||||
|
<folding>
|
||||||
|
<element signature="e#0#20#0" expanded="true" />
|
||||||
|
<element signature="e#1190#1195#0" expanded="false" />
|
||||||
|
<element signature="e#1498#1523#0" expanded="false" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
</leaf>
|
||||||
|
</split-second>
|
||||||
|
</splitter>
|
||||||
</component>
|
</component>
|
||||||
<component name="FileTemplateManagerImpl">
|
<component name="FileTemplateManagerImpl">
|
||||||
<option name="RECENT_TEMPLATES">
|
<option name="RECENT_TEMPLATES">
|
||||||
|
@ -201,8 +165,6 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="FindInProjectRecents">
|
<component name="FindInProjectRecents">
|
||||||
<findStrings>
|
<findStrings>
|
||||||
<find>inject(</find>
|
|
||||||
<find>sendRe</find>
|
|
||||||
<find>sendResponse</find>
|
<find>sendResponse</find>
|
||||||
<find>addStream</find>
|
<find>addStream</find>
|
||||||
<find>Lo</find>
|
<find>Lo</find>
|
||||||
|
@ -231,6 +193,8 @@
|
||||||
<find>((cre)|(upd))atedAt</find>
|
<find>((cre)|(upd))atedAt</find>
|
||||||
<find>'((cre)|(upd))atedAt'</find>
|
<find>'((cre)|(upd))atedAt'</find>
|
||||||
<find>handleReque</find>
|
<find>handleReque</find>
|
||||||
|
<find>injectSeri</find>
|
||||||
|
<find>optimize</find>
|
||||||
</findStrings>
|
</findStrings>
|
||||||
<replaceStrings>
|
<replaceStrings>
|
||||||
<replace>_isClosed</replace>
|
<replace>_isClosed</replace>
|
||||||
|
@ -327,8 +291,8 @@
|
||||||
<option value="$PROJECT_DIR$/pubspec.yaml" />
|
<option value="$PROJECT_DIR$/pubspec.yaml" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/http/map_service.dart" />
|
<option value="$PROJECT_DIR$/lib/src/http/map_service.dart" />
|
||||||
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
<option value="$PROJECT_DIR$/CHANGELOG.md" />
|
||||||
<option value="$PROJECT_DIR$/lib/src/http/server.dart" />
|
|
||||||
<option value="$PROJECT_DIR$/lib/src/http/angel_http.dart" />
|
<option value="$PROJECT_DIR$/lib/src/http/angel_http.dart" />
|
||||||
|
<option value="$PROJECT_DIR$/lib/src/http/server.dart" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
@ -736,14 +700,7 @@
|
||||||
<workItem from="1513103483207" duration="18000" />
|
<workItem from="1513103483207" duration="18000" />
|
||||||
<workItem from="1513103506825" duration="139000" />
|
<workItem from="1513103506825" duration="139000" />
|
||||||
<workItem from="1517332581856" duration="858000" />
|
<workItem from="1517332581856" duration="858000" />
|
||||||
<workItem from="1517973177718" duration="1156000" />
|
<workItem from="1517973177718" duration="2011000" />
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00001" summary="Re-designed exception">
|
|
||||||
<created>1481237183504</created>
|
|
||||||
<option name="number" value="00001" />
|
|
||||||
<option name="presentableId" value="LOCAL-00001" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1481237183504</updated>
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00002" summary="Core done?">
|
<task id="LOCAL-00002" summary="Core done?">
|
||||||
<created>1481378740441</created>
|
<created>1481378740441</created>
|
||||||
|
@ -1081,7 +1038,14 @@
|
||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1517973884510</updated>
|
<updated>1517973884510</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="50" />
|
<task id="LOCAL-00050" summary="Created setup for AngelHttp">
|
||||||
|
<created>1517974351104</created>
|
||||||
|
<option name="number" value="00050" />
|
||||||
|
<option name="presentableId" value="LOCAL-00050" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1517974351105</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="51" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TestHistory">
|
<component name="TestHistory">
|
||||||
|
@ -1117,7 +1081,7 @@
|
||||||
</history-entry>
|
</history-entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="TimeTrackingManager">
|
<component name="TimeTrackingManager">
|
||||||
<option name="totallyTimeSpent" value="119192000" />
|
<option name="totallyTimeSpent" value="120047000" />
|
||||||
</component>
|
</component>
|
||||||
<component name="TodoView">
|
<component name="TodoView">
|
||||||
<todo-panel id="selected-file">
|
<todo-panel id="selected-file">
|
||||||
|
@ -1154,7 +1118,7 @@
|
||||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32905984" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32905984" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4002849" sideWeight="0.4964476" order="2" side_tool="false" content_ui="tabs" />
|
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4002849" sideWeight="0.4964476" order="2" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.48005697" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.48005697" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.23141123" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.23141123" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
<window_info id="Theme Preview" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
|
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="true" content_ui="tabs" />
|
||||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||||
|
@ -1176,7 +1140,6 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||||
<MESSAGE value="Swapped to angel_model" />
|
|
||||||
<MESSAGE value="1.0.7+2" />
|
<MESSAGE value="1.0.7+2" />
|
||||||
<MESSAGE value="Working on 1.0.8, including performance tuning" />
|
<MESSAGE value="Working on 1.0.8, including performance tuning" />
|
||||||
<MESSAGE value="Remove reopen" />
|
<MESSAGE value="Remove reopen" />
|
||||||
|
@ -1201,7 +1164,8 @@
|
||||||
<MESSAGE value="Patched ResponseContext#isOpen, bump to 1.1.0+3" />
|
<MESSAGE value="Patched ResponseContext#isOpen, bump to 1.1.0+3" />
|
||||||
<MESSAGE value="Response no longer closes if `serialize` is called with an empty string" />
|
<MESSAGE value="Response no longer closes if `serialize` is called with an empty string" />
|
||||||
<MESSAGE value="Added `autoSnakeCaseNames` to `MapService`" />
|
<MESSAGE value="Added `autoSnakeCaseNames` to `MapService`" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="Added `autoSnakeCaseNames` to `MapService`" />
|
<MESSAGE value="Created setup for AngelHttp" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="Created setup for AngelHttp" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager />
|
<breakpoint-manager />
|
||||||
|
@ -1574,67 +1538,23 @@
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/http/server.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/http/server.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="409">
|
<state relative-caret-position="-1684">
|
||||||
<caret line="464" column="0" lean-forward="true" selection-start-line="464" selection-start-column="0" selection-end-line="464" selection-end-column="0" />
|
<caret line="380" column="7" lean-forward="false" selection-start-line="380" selection-start-column="7" selection-end-line="380" selection-end-column="7" />
|
||||||
<folding>
|
<folding>
|
||||||
<element signature="e#1894#1949#0" expanded="false" />
|
<element signature="e#38#58#0" expanded="true" />
|
||||||
<element signature="e#2304#2311#0" expanded="false" />
|
|
||||||
<element signature="e#2534#2611#0" expanded="false" />
|
|
||||||
<element signature="e#2869#2964#0" expanded="false" />
|
|
||||||
<element signature="e#3252#3306#0" expanded="false" />
|
|
||||||
<element signature="e#3430#3485#0" expanded="false" />
|
|
||||||
<element signature="e#3611#3652#0" expanded="false" />
|
|
||||||
<element signature="e#3866#4128#0" expanded="false" />
|
|
||||||
<element signature="e#5025#5047#0" expanded="false" />
|
|
||||||
<element signature="e#5175#5490#0" expanded="false" />
|
|
||||||
<element signature="e#5601#5948#0" expanded="false" />
|
|
||||||
<element signature="e#6038#6405#0" expanded="false" />
|
|
||||||
<element signature="e#6498#6736#0" expanded="false" />
|
|
||||||
<element signature="e#6740#6807#0" expanded="false" />
|
|
||||||
<element signature="e#6911#7587#0" expanded="false" />
|
|
||||||
<element signature="e#7749#8389#0" expanded="false" />
|
|
||||||
<element signature="e#8501#8536#0" expanded="false" />
|
|
||||||
<element signature="e#8709#8750#0" expanded="false" />
|
|
||||||
<element signature="e#8886#8921#0" expanded="false" />
|
|
||||||
<element signature="e#9006#9723#0" expanded="false" />
|
|
||||||
<element signature="e#9892#10283#0" expanded="false" />
|
|
||||||
<element signature="e#10352#10696#0" expanded="false" />
|
|
||||||
<element signature="e#10837#10854#0" expanded="false" />
|
|
||||||
<element signature="e#11138#11281#0" expanded="false" />
|
|
||||||
<element signature="e#11380#11513#0" expanded="false" />
|
|
||||||
<element signature="e#11731#12311#0" expanded="false" />
|
|
||||||
<element signature="e#12660#13030#0" expanded="false" />
|
|
||||||
<element signature="e#12899#12904#0" expanded="false" />
|
|
||||||
<element signature="e#13199#13224#0" expanded="false" />
|
|
||||||
<element signature="e#14842#14904#0" expanded="false" />
|
|
||||||
<element signature="e#15220#15852#0" expanded="false" />
|
|
||||||
<element signature="e#15313#15437#0" expanded="false" />
|
|
||||||
<element signature="e#15471#15716#0" expanded="false" />
|
|
||||||
<element signature="e#15856#15914#0" expanded="false" />
|
|
||||||
<element signature="e#16148#16323#0" expanded="false" />
|
|
||||||
<element signature="e#16479#16668#0" expanded="false" />
|
|
||||||
<element signature="e#16823#19001#0" expanded="false" />
|
|
||||||
<element signature="e#17538#17589#0" expanded="false" />
|
|
||||||
<element signature="e#19005#19091#0" expanded="false" />
|
|
||||||
<element signature="e#19273#19341#0" expanded="false" />
|
|
||||||
<element signature="e#19443#19482#0" expanded="false" />
|
|
||||||
<element signature="e#19486#19547#0" expanded="false" />
|
|
||||||
<element signature="e#19973#21048#0" expanded="false" />
|
|
||||||
<element signature="e#21100#21178#0" expanded="false" />
|
|
||||||
<element signature="e#21246#21508#0" expanded="false" />
|
|
||||||
<element signature="e#21638#21703#0" expanded="false" />
|
|
||||||
<element signature="e#21766#21960#0" expanded="false" />
|
|
||||||
<element signature="e#21964#21992#0" expanded="false" />
|
|
||||||
<element signature="e#22284#22703#0" expanded="false" />
|
|
||||||
</folding>
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/lib/src/http/angel_http.dart">
|
<entry file="file://$PROJECT_DIR$/lib/src/http/angel_http.dart">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state relative-caret-position="30">
|
<state relative-caret-position="300">
|
||||||
<caret line="2" column="51" lean-forward="false" selection-start-line="2" selection-start-column="51" selection-end-line="2" selection-end-column="51" />
|
<caret line="20" column="0" lean-forward="true" selection-start-line="20" selection-start-column="0" selection-end-line="20" selection-end-column="0" />
|
||||||
<folding />
|
<folding>
|
||||||
|
<element signature="e#0#20#0" expanded="true" />
|
||||||
|
<element signature="e#1190#1195#0" expanded="false" />
|
||||||
|
<element signature="e#1498#1523#0" expanded="false" />
|
||||||
|
</folding>
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
|
|
|
@ -1,6 +1,231 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:angel_http_exception/angel_http_exception.dart';
|
||||||
|
import 'package:angel_route/angel_route.dart';
|
||||||
|
import 'package:combinator/combinator.dart';
|
||||||
|
import 'package:json_god/json_god.dart' as god;
|
||||||
|
import 'package:pool/pool.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
import 'request_context.dart';
|
||||||
|
import 'response_context.dart';
|
||||||
|
import 'server.dart';
|
||||||
|
|
||||||
|
final RegExp _straySlashes = new RegExp(r'(^/+)|(/+$)');
|
||||||
|
|
||||||
/// Adapts `dart:io`'s [HttpServer] to serve Angel.
|
/// Adapts `dart:io`'s [HttpServer] to serve Angel.
|
||||||
class AngelHttp {
|
class AngelHttp {
|
||||||
|
final Angel app;
|
||||||
|
|
||||||
|
Pool _pool;
|
||||||
|
|
||||||
|
AngelHttp(this.app);
|
||||||
|
|
||||||
|
/// Handles a single request.
|
||||||
|
Future handleRequest(HttpRequest request) async {
|
||||||
|
var req = await createRequestContext(request);
|
||||||
|
var res = await createResponseContext(request.response, req);
|
||||||
|
|
||||||
|
try {
|
||||||
|
var path = req.path;
|
||||||
|
if (path == '/') path = '';
|
||||||
|
|
||||||
|
Tuple3<List, Map, ParseResult<Map<String, String>>> resolveTuple() {
|
||||||
|
Router r = _flattened ?? this;
|
||||||
|
var resolved =
|
||||||
|
r.resolveAbsolute(path, method: req.method, strip: false);
|
||||||
|
|
||||||
|
return new Tuple3(
|
||||||
|
new MiddlewarePipeline(resolved).handlers,
|
||||||
|
resolved.fold<Map>({}, (out, r) => out..addAll(r.allParams)),
|
||||||
|
resolved.isEmpty ? null : resolved.first.parseResult,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
var cacheKey = req.method + path;
|
||||||
|
var tuple = app.isProduction
|
||||||
|
? app.handlerCache.putIfAbsent(cacheKey, resolveTuple)
|
||||||
|
: resolveTuple();
|
||||||
|
|
||||||
|
//req.inject(Zone, zone);
|
||||||
|
//req.inject(ZoneSpecification, zoneSpec);
|
||||||
|
req.params.addAll(tuple.item2);
|
||||||
|
req.inject(ParseResult, tuple.item3);
|
||||||
|
|
||||||
|
if (app.logger != null) req.inject(Stopwatch, new Stopwatch()..start());
|
||||||
|
|
||||||
|
var pipeline = tuple.item1;
|
||||||
|
|
||||||
|
for (var handler in pipeline) {
|
||||||
|
try {
|
||||||
|
if (handler == null || !await app.executeHandler(handler, req, res))
|
||||||
|
break;
|
||||||
|
} on AngelHttpException catch (e, st) {
|
||||||
|
e.stackTrace ??= st;
|
||||||
|
return await handleAngelHttpException(e, st, req, res, request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendResponse(request, req, res);
|
||||||
|
} on AngelHttpException catch (e, st) {
|
||||||
|
e.stackTrace ??= st;
|
||||||
|
return await handleAngelHttpException(
|
||||||
|
e,
|
||||||
|
st,
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
request,
|
||||||
|
ignoreFinalizers: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on FormatException catch (error, stackTrace) {
|
||||||
|
var e = new AngelHttpException.badRequest(message: error.message);
|
||||||
|
|
||||||
|
if (app.logger != null) {
|
||||||
|
app.logger.severe(e.message ?? e.toString(), error, stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await handleAngelHttpException(e, stackTrace, req, res, request);
|
||||||
|
} catch (error, stackTrace) {
|
||||||
|
var e = new AngelHttpException(error,
|
||||||
|
stackTrace: stackTrace, message: error?.toString());
|
||||||
|
|
||||||
|
if (app.logger != null) {
|
||||||
|
app.logger.severe(e.message ?? e.toString(), error, stackTrace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await handleAngelHttpException(e, stackTrace, req, res, request);
|
||||||
|
} finally {
|
||||||
|
res.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handles an [AngelHttpException].
|
||||||
|
Future handleAngelHttpException(AngelHttpException e, StackTrace st,
|
||||||
|
RequestContext req, ResponseContext res, HttpRequest request,
|
||||||
|
{bool ignoreFinalizers: false}) async {
|
||||||
|
if (req == null || res == null) {
|
||||||
|
try {
|
||||||
|
app.logger?.severe(e, st);
|
||||||
|
request.response
|
||||||
|
..statusCode = HttpStatus.INTERNAL_SERVER_ERROR
|
||||||
|
..write('500 Internal Server Error')
|
||||||
|
..close();
|
||||||
|
} finally {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.isOpen) {
|
||||||
|
res.statusCode = e.statusCode;
|
||||||
|
var result = await app.errorHandler(e, req, res);
|
||||||
|
await app.executeHandler(result, req, res);
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return await sendResponse(request, req, res,
|
||||||
|
ignoreFinalizers: ignoreFinalizers == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sends a response.
|
||||||
|
Future sendResponse(
|
||||||
|
HttpRequest request, RequestContext req, ResponseContext res,
|
||||||
|
{bool ignoreFinalizers: false}) {
|
||||||
|
if (res.willCloseItself) return new Future.value();
|
||||||
|
|
||||||
|
Future finalizers = ignoreFinalizers == true
|
||||||
|
? new Future.value()
|
||||||
|
: app.responseFinalizers.fold<Future>(
|
||||||
|
new Future.value(), (out, f) => out.then((_) => f(req, res)));
|
||||||
|
|
||||||
|
if (res.isOpen) res.end();
|
||||||
|
|
||||||
|
for (var key in res.headers.keys) {
|
||||||
|
request.response.headers.add(key, res.headers[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.response.contentLength = res.buffer.length;
|
||||||
|
request.response.headers.chunkedTransferEncoding = res.chunked ?? true;
|
||||||
|
|
||||||
|
List<int> outputBuffer = res.buffer.toBytes();
|
||||||
|
|
||||||
|
if (res.encoders.isNotEmpty) {
|
||||||
|
var allowedEncodings =
|
||||||
|
req.headers[HttpHeaders.ACCEPT_ENCODING]?.map((str) {
|
||||||
|
// Ignore quality specifications in accept-encoding
|
||||||
|
// ex. gzip;q=0.8
|
||||||
|
if (!str.contains(';')) return str;
|
||||||
|
return str.split(';')[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allowedEncodings != null) {
|
||||||
|
for (var encodingName in allowedEncodings) {
|
||||||
|
Converter<List<int>, List<int>> encoder;
|
||||||
|
String key = encodingName;
|
||||||
|
|
||||||
|
if (res.encoders.containsKey(encodingName))
|
||||||
|
encoder = res.encoders[encodingName];
|
||||||
|
else if (encodingName == '*') {
|
||||||
|
encoder = res.encoders[key = res.encoders.keys.first];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder != null) {
|
||||||
|
request.response.headers.set(HttpHeaders.CONTENT_ENCODING, key);
|
||||||
|
outputBuffer = res.encoders[key].convert(outputBuffer);
|
||||||
|
request.response.contentLength = outputBuffer.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.response
|
||||||
|
..statusCode = res.statusCode
|
||||||
|
..cookies.addAll(res.cookies)
|
||||||
|
..add(outputBuffer);
|
||||||
|
|
||||||
|
return finalizers.then((_) async {
|
||||||
|
request.response.close();
|
||||||
|
|
||||||
|
if (req.injections.containsKey(PoolResource)) {
|
||||||
|
req.injections[PoolResource].release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app.logger != null) {
|
||||||
|
var sw = req.grab<Stopwatch>(Stopwatch);
|
||||||
|
|
||||||
|
if (sw.isRunning) {
|
||||||
|
sw?.stop();
|
||||||
|
app.logger.info("${res.statusCode} ${req.method} ${req.uri} (${sw
|
||||||
|
?.elapsedMilliseconds ?? 'unknown'} ms)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<RequestContext> createRequestContext(HttpRequest request) {
|
||||||
|
var path = request.uri.path.replaceAll(_straySlashes, '');
|
||||||
|
if (path.length == 0) path = '/';
|
||||||
|
return RequestContext.from(request, app, path).then((req) async {
|
||||||
|
if (_pool != null) req.inject(PoolResource, await _pool.request());
|
||||||
|
if (app.injections.isNotEmpty) app.injections.forEach(req.inject);
|
||||||
|
return req;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<ResponseContext> createResponseContext(HttpResponse response,
|
||||||
|
[RequestContext correspondingRequest]) =>
|
||||||
|
new Future<ResponseContext>.value(
|
||||||
|
new ResponseContext(response, app, correspondingRequest)
|
||||||
|
..serializer = (_serializer ?? god.serialize)
|
||||||
|
..encoders.addAll(app.encoders ?? {}));
|
||||||
|
|
||||||
|
/// Limits the maximum number of requests to be handled concurrently by this instance.
|
||||||
|
///
|
||||||
|
/// You can optionally provide a [timeout] to limit the amount of time a request can be
|
||||||
|
/// handled before.
|
||||||
|
void throttle(int maxConcurrentRequests, {Duration timeout}) {
|
||||||
|
_pool = new Pool(maxConcurrentRequests, timeout: timeout);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -14,6 +14,7 @@ import 'package:meta/meta.dart';
|
||||||
import 'package:pool/pool.dart';
|
import 'package:pool/pool.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
import 'angel_base.dart';
|
import 'angel_base.dart';
|
||||||
|
import 'angel_http.dart';
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
import 'request_context.dart';
|
import 'request_context.dart';
|
||||||
import 'response_context.dart';
|
import 'response_context.dart';
|
||||||
|
@ -35,9 +36,9 @@ class Angel extends AngelBase {
|
||||||
handlerCache = new HashMap();
|
handlerCache = new HashMap();
|
||||||
|
|
||||||
Router _flattened;
|
Router _flattened;
|
||||||
|
AngelHttp _http;
|
||||||
bool _isProduction;
|
bool _isProduction;
|
||||||
Angel _parent;
|
Angel _parent;
|
||||||
Pool _pool;
|
|
||||||
StreamSubscription<HttpRequest> _sub;
|
StreamSubscription<HttpRequest> _sub;
|
||||||
ServerGenerator _serverGenerator = HttpServer.bind;
|
ServerGenerator _serverGenerator = HttpServer.bind;
|
||||||
|
|
||||||
|
@ -106,6 +107,9 @@ class Angel extends AngelBase {
|
||||||
/// These will only not run if a response's `willCloseItself` is set to `true`.
|
/// These will only not run if a response's `willCloseItself` is set to `true`.
|
||||||
final List<RequestHandler> responseFinalizers = [];
|
final List<RequestHandler> responseFinalizers = [];
|
||||||
|
|
||||||
|
/// All global dependencies injected into the application.
|
||||||
|
Map get injections => _injections;
|
||||||
|
|
||||||
/// Use [configuration] instead.
|
/// Use [configuration] instead.
|
||||||
@deprecated
|
@deprecated
|
||||||
Map get properties {
|
Map get properties {
|
||||||
|
@ -275,6 +279,7 @@ class Angel extends AngelBase {
|
||||||
|
|
||||||
/// Shortcut for adding a middleware to inject a serialize on every request.
|
/// Shortcut for adding a middleware to inject a serialize on every request.
|
||||||
void injectSerializer(ResponseSerializer serializer) {
|
void injectSerializer(ResponseSerializer serializer) {
|
||||||
|
// TODO: Make this public
|
||||||
_serializer = serializer;
|
_serializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,6 +322,8 @@ class Angel extends AngelBase {
|
||||||
else if (result is bool) {
|
else if (result is bool) {
|
||||||
return result;
|
return result;
|
||||||
} else if (result != null) {
|
} else if (result != null) {
|
||||||
|
// TODO: Make `serialize` return a bool, return this as the value.
|
||||||
|
// Do this wherever applicable
|
||||||
res.serialize(result,
|
res.serialize(result,
|
||||||
contentType: res.headers[HttpHeaders.CONTENT_TYPE] ??
|
contentType: res.headers[HttpHeaders.CONTENT_TYPE] ??
|
||||||
ContentType.JSON.mimeType);
|
ContentType.JSON.mimeType);
|
||||||
|
@ -325,22 +332,17 @@ class Angel extends AngelBase {
|
||||||
return res.isOpen;
|
return res.isOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
|
@deprecated
|
||||||
Future<RequestContext> createRequestContext(HttpRequest request) {
|
Future<RequestContext> createRequestContext(HttpRequest request) {
|
||||||
var path = request.uri.path.replaceAll(_straySlashes, '');
|
return _http.createRequestContext(request);
|
||||||
if (path.length == 0) path = '/';
|
|
||||||
return RequestContext.from(request, this, path).then((req) async {
|
|
||||||
if (_pool != null) req.inject(PoolResource, await _pool.request());
|
|
||||||
if (_injections.isNotEmpty) _injections.forEach(req.inject);
|
|
||||||
return req;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
|
@deprecated
|
||||||
Future<ResponseContext> createResponseContext(HttpResponse response,
|
Future<ResponseContext> createResponseContext(HttpResponse response,
|
||||||
[RequestContext correspondingRequest]) =>
|
[RequestContext correspondingRequest]) =>
|
||||||
new Future<ResponseContext>.value(
|
_http.createResponseContext(response, correspondingRequest);
|
||||||
new ResponseContext(response, this, correspondingRequest)
|
|
||||||
..serializer = (_serializer ?? god.serialize)
|
|
||||||
..encoders.addAll(encoders ?? {}));
|
|
||||||
|
|
||||||
/// Attempts to find a middleware by the given name within this application.
|
/// Attempts to find a middleware by the given name within this application.
|
||||||
findMiddleware(key) {
|
findMiddleware(key) {
|
||||||
|
@ -354,115 +356,19 @@ class Angel extends AngelBase {
|
||||||
return parent != null ? parent.findProperty(key) : null;
|
return parent != null ? parent.findProperty(key) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles an [AngelHttpException].
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
|
@deprecated
|
||||||
Future handleAngelHttpException(AngelHttpException e, StackTrace st,
|
Future handleAngelHttpException(AngelHttpException e, StackTrace st,
|
||||||
RequestContext req, ResponseContext res, HttpRequest request,
|
RequestContext req, ResponseContext res, HttpRequest request,
|
||||||
{bool ignoreFinalizers: false}) async {
|
{bool ignoreFinalizers: false}) {
|
||||||
if (req == null || res == null) {
|
return _http.handleAngelHttpException(e, st, req, res, request,
|
||||||
try {
|
|
||||||
logger?.severe(e, st);
|
|
||||||
request.response
|
|
||||||
..statusCode = HttpStatus.INTERNAL_SERVER_ERROR
|
|
||||||
..write('500 Internal Server Error')
|
|
||||||
..close();
|
|
||||||
} finally {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.isOpen) {
|
|
||||||
res.statusCode = e.statusCode;
|
|
||||||
var result = await errorHandler(e, req, res);
|
|
||||||
await executeHandler(result, req, res);
|
|
||||||
res.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
return await sendResponse(request, req, res,
|
|
||||||
ignoreFinalizers: ignoreFinalizers == true);
|
ignoreFinalizers: ignoreFinalizers == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a single request.
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
Future handleRequest(HttpRequest request) async {
|
@deprecated
|
||||||
var req = await createRequestContext(request);
|
Future handleRequest(HttpRequest request) {
|
||||||
var res = await createResponseContext(request.response, req);
|
return _http.handleRequest(request);
|
||||||
|
|
||||||
try {
|
|
||||||
var path = req.path;
|
|
||||||
if (path == '/') path = '';
|
|
||||||
|
|
||||||
Tuple3<List, Map, ParseResult<Map<String, String>>> resolveTuple() {
|
|
||||||
Router r = _flattened ?? this;
|
|
||||||
var resolved =
|
|
||||||
r.resolveAbsolute(path, method: req.method, strip: false);
|
|
||||||
|
|
||||||
return new Tuple3(
|
|
||||||
new MiddlewarePipeline(resolved).handlers,
|
|
||||||
resolved.fold<Map>({}, (out, r) => out..addAll(r.allParams)),
|
|
||||||
resolved.isEmpty ? null : resolved.first.parseResult,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var cacheKey = req.method + path;
|
|
||||||
var tuple = isProduction
|
|
||||||
? handlerCache.putIfAbsent(cacheKey, resolveTuple)
|
|
||||||
: resolveTuple();
|
|
||||||
|
|
||||||
//req.inject(Zone, zone);
|
|
||||||
//req.inject(ZoneSpecification, zoneSpec);
|
|
||||||
req.params.addAll(tuple.item2);
|
|
||||||
req.inject(ParseResult, tuple.item3);
|
|
||||||
|
|
||||||
if (logger != null) req.inject(Stopwatch, new Stopwatch()..start());
|
|
||||||
|
|
||||||
var pipeline = tuple.item1;
|
|
||||||
|
|
||||||
for (var handler in pipeline) {
|
|
||||||
try {
|
|
||||||
if (handler == null || !await executeHandler(handler, req, res))
|
|
||||||
break;
|
|
||||||
} on AngelHttpException catch (e, st) {
|
|
||||||
e.stackTrace ??= st;
|
|
||||||
return await handleAngelHttpException(e, st, req, res, request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await sendResponse(request, req, res);
|
|
||||||
} on AngelHttpException catch (e, st) {
|
|
||||||
e.stackTrace ??= st;
|
|
||||||
return await handleAngelHttpException(
|
|
||||||
e,
|
|
||||||
st,
|
|
||||||
req,
|
|
||||||
res,
|
|
||||||
request,
|
|
||||||
ignoreFinalizers: true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} on FormatException catch (error, stackTrace) {
|
|
||||||
var e = new AngelHttpException.badRequest(message: error.message);
|
|
||||||
|
|
||||||
if (logger != null) {
|
|
||||||
logger.severe(e.message ?? e.toString(), error, stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await handleAngelHttpException(e, stackTrace, req, res, request);
|
|
||||||
} catch (error, stackTrace) {
|
|
||||||
var e = new AngelHttpException(error,
|
|
||||||
stackTrace: stackTrace, message: error?.toString());
|
|
||||||
|
|
||||||
if (logger != null) {
|
|
||||||
logger.severe(e.message ?? e.toString(), error, stackTrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await handleAngelHttpException(e, stackTrace, req, res, request);
|
|
||||||
} finally {
|
|
||||||
res.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future setupRequest(RequestContext req) async {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs several optimizations, *if* [isProduction] is `true`.
|
/// Runs several optimizations, *if* [isProduction] is `true`.
|
||||||
|
@ -519,88 +425,18 @@ class Angel extends AngelBase {
|
||||||
// return await closureMirror.apply(args).reflectee;
|
// return await closureMirror.apply(args).reflectee;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends a response.
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
|
@deprecated
|
||||||
Future sendResponse(
|
Future sendResponse(
|
||||||
HttpRequest request, RequestContext req, ResponseContext res,
|
HttpRequest request, RequestContext req, ResponseContext res,
|
||||||
{bool ignoreFinalizers: false}) {
|
{bool ignoreFinalizers: false}) {
|
||||||
if (res.willCloseItself) return new Future.value();
|
return _http.sendResponse(request, req, res);
|
||||||
|
|
||||||
Future finalizers = ignoreFinalizers == true
|
|
||||||
? new Future.value()
|
|
||||||
: responseFinalizers.fold<Future>(
|
|
||||||
new Future.value(), (out, f) => out.then((_) => f(req, res)));
|
|
||||||
|
|
||||||
if (res.isOpen) res.end();
|
|
||||||
|
|
||||||
for (var key in res.headers.keys) {
|
|
||||||
request.response.headers.add(key, res.headers[key]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
request.response.contentLength = res.buffer.length;
|
/// Use the serving methods in [AngelHttp] instead.
|
||||||
request.response.headers.chunkedTransferEncoding = res.chunked ?? true;
|
@deprecated
|
||||||
|
|
||||||
List<int> outputBuffer = res.buffer.toBytes();
|
|
||||||
|
|
||||||
if (res.encoders.isNotEmpty) {
|
|
||||||
var allowedEncodings =
|
|
||||||
req.headers[HttpHeaders.ACCEPT_ENCODING]?.map((str) {
|
|
||||||
// Ignore quality specifications in accept-encoding
|
|
||||||
// ex. gzip;q=0.8
|
|
||||||
if (!str.contains(';')) return str;
|
|
||||||
return str.split(';')[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (allowedEncodings != null) {
|
|
||||||
for (var encodingName in allowedEncodings) {
|
|
||||||
Converter<List<int>, List<int>> encoder;
|
|
||||||
String key = encodingName;
|
|
||||||
|
|
||||||
if (res.encoders.containsKey(encodingName))
|
|
||||||
encoder = res.encoders[encodingName];
|
|
||||||
else if (encodingName == '*') {
|
|
||||||
encoder = res.encoders[key = res.encoders.keys.first];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (encoder != null) {
|
|
||||||
request.response.headers.set(HttpHeaders.CONTENT_ENCODING, key);
|
|
||||||
outputBuffer = res.encoders[key].convert(outputBuffer);
|
|
||||||
request.response.contentLength = outputBuffer.length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
request.response
|
|
||||||
..statusCode = res.statusCode
|
|
||||||
..cookies.addAll(res.cookies)
|
|
||||||
..add(outputBuffer);
|
|
||||||
|
|
||||||
return finalizers.then((_) async {
|
|
||||||
request.response.close();
|
|
||||||
|
|
||||||
if (req.injections.containsKey(PoolResource)) {
|
|
||||||
req.injections[PoolResource].release();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger != null) {
|
|
||||||
var sw = req.grab<Stopwatch>(Stopwatch);
|
|
||||||
|
|
||||||
if (sw.isRunning) {
|
|
||||||
sw?.stop();
|
|
||||||
logger.info("${res.statusCode} ${req.method} ${req.uri} (${sw
|
|
||||||
?.elapsedMilliseconds ?? 'unknown'} ms)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Limits the maximum number of requests to be handled concurrently by this instance.
|
|
||||||
///
|
|
||||||
/// You can optionally provide a [timeout] to limit the amount of time a request can be
|
|
||||||
/// handled before.
|
|
||||||
void throttle(int maxConcurrentRequests, {Duration timeout}) {
|
void throttle(int maxConcurrentRequests, {Duration timeout}) {
|
||||||
_pool = new Pool(maxConcurrentRequests, timeout: timeout);
|
_http?.throttle(maxConcurrentRequests, timeout: timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies an [AngelConfigurer] to this instance.
|
/// Applies an [AngelConfigurer] to this instance.
|
||||||
|
|
Loading…
Reference in a new issue