Multipart support thanks to http_server
This commit is contained in:
parent
5c0ee725d1
commit
9a06489be5
15 changed files with 529 additions and 1118 deletions
|
@ -5,318 +5,350 @@
|
|||
<entry key="analyzer">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/analyzer-0.27.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/analyzer-0.27.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="args">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/args-0.13.4/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/args-0.13.4/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="async">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/async-1.10.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/async-1.10.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="barback">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/barback-0.15.2+7/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/barback-0.15.2+7/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="boolean_selector">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/boolean_selector-1.0.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="charcode">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/charcode-1.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="collection">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/collection-1.5.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/collection-1.9.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="convert">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/convert-1.0.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/convert-1.0.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="crypto">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/crypto-1.0.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/crypto-1.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="csslib">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/csslib-0.12.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/csslib-0.12.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="glob">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/glob-1.1.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/glob-1.1.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="html">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/html-0.12.2+1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/html-0.12.2+1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="http">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http-0.11.3+3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http-0.11.3+3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="http_multi_server">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http_multi_server-2.0.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_multi_server-2.0.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="http_parser">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http_parser-2.2.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_parser-2.2.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="http_server">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_server-0.9.6/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="json_god">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/json_god-1.0.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/json_god-2.0.0-beta/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="json_schema">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/json_schema-1.0.4/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="logging">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/logging-0.11.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/logging-0.11.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="matcher">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.0+2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/matcher-0.12.0+2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="mime">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/mime-0.9.3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/mime-0.9.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="package_config">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/package_config-0.1.3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/package_config-0.1.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="package_resolver">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/package_resolver-1.0.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="path">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path-1.3.9/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/path-1.3.9/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="plugin">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/plugin-0.1.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/plugin-0.1.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pool">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pool-1.2.3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/pool-1.2.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pub_semver">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.2.4/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/pub_semver-1.2.4/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="shelf">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf-0.6.5/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf-0.6.5/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="shelf_packages_handler">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_packages_handler-1.0.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="shelf_static">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf_static-0.2.3+3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_static-0.2.3+3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="shelf_web_socket">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.0/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.0/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="source_map_stack_trace">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-1.0.4/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_map_stack_trace-1.1.3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="source_maps">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.1+1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_maps-0.10.1+1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="source_span">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_span-1.2.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_span-1.2.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="stack_trace">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.6.5/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.6.5/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="stream_channel">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stream_channel-1.3.1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/stream_channel-1.3.1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="string_scanner">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/string_scanner-0.1.4+1/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/string_scanner-0.1.4+1/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="test">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/test-0.12.13/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/test-0.12.15+6/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="typed_data">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/typed_data-1.1.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="utf">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/utf-0.9.0+3/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/utf-0.9.0+3/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="watcher">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/watcher-0.9.7/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/watcher-0.9.7/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="web_socket_channel">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.0.2/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/web_socket_channel-1.0.2/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="yaml">
|
||||
<value>
|
||||
<list>
|
||||
<option value="$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.8/lib" />
|
||||
<option value="$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/yaml-2.1.8/lib" />
|
||||
</list>
|
||||
</value>
|
||||
</entry>
|
||||
</option>
|
||||
</properties>
|
||||
<CLASSES>
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/analyzer-0.27.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/args-0.13.4/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/async-1.10.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/barback-0.15.2+7/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/boolean_selector-1.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/charcode-1.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/collection-1.5.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/convert-1.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/crypto-1.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/csslib-0.12.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/glob-1.1.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/html-0.12.2+1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http-0.11.3+3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http_multi_server-2.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/http_parser-2.2.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/json_god-1.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/logging-0.11.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/matcher-0.12.0+2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/mime-0.9.3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/package_config-0.1.3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/path-1.3.9/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/plugin-0.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pool-1.2.3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/pub_semver-1.2.4/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf-0.6.5/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf_static-0.2.3+3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.0/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_map_stack_trace-1.0.4/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_maps-0.10.1+1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/source_span-1.2.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.6.5/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/stream_channel-1.3.1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/string_scanner-0.1.4+1/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/test-0.12.13/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/typed_data-1.1.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/utf-0.9.0+3/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/watcher-0.9.7/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/web_socket_channel-1.0.2/lib" />
|
||||
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.dartlang.org/yaml-2.1.8/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/analyzer-0.27.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/args-0.13.4/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/async-1.10.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/barback-0.15.2+7/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/boolean_selector-1.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/charcode-1.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/collection-1.9.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/convert-1.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/crypto-1.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/csslib-0.12.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/glob-1.1.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/html-0.12.2+1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http-0.11.3+3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_multi_server-2.0.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_parser-2.2.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/http_server-0.9.6/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/json_god-2.0.0-beta/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/json_schema-1.0.4/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/logging-0.11.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/matcher-0.12.0+2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/mime-0.9.3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/package_config-0.1.3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/package_resolver-1.0.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/path-1.3.9/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/plugin-0.1.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/pool-1.2.3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/pub_semver-1.2.4/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf-0.6.5/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_packages_handler-1.0.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_static-0.2.3+3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/shelf_web_socket-0.2.0/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_map_stack_trace-1.1.3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_maps-0.10.1+1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/source_span-1.2.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/stack_trace-1.6.5/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/stream_channel-1.3.1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/string_scanner-0.1.4+1/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/test-0.12.15+6/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/typed_data-1.1.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/utf-0.9.0+3/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/watcher-0.9.7/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/web_socket_channel-1.0.2/lib" />
|
||||
<root url="file://$USER_HOME$/AppData/Roaming/Pub/Cache/hosted/pub.dartlang.org/yaml-2.1.8/lib" />
|
||||
</CLASSES>
|
||||
<SOURCES />
|
||||
</library>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Body Parser
|
||||
![version 1.0.0-dev](https://img.shields.io/badge/version-1.0.0--dev-red.svg)
|
||||
![version 1.0.0-dev+1](https://img.shields.io/badge/version-1.0.0--dev-red.svg)
|
||||
|
||||
**NOT YET PRODUCTION READY**
|
||||
|
||||
|
@ -68,6 +68,4 @@ Thank you for using this library. I hope you like it.
|
|||
|
||||
Feel free to follow me on Twitter:
|
||||
|
||||
[@thosakwe](http://twitter.com/thosakwe)
|
||||
or
|
||||
[@regios_tech](http://twitter.com/regios_tech)
|
||||
[@_wapaa_](http://twitter.com/_wapaa_)
|
File diff suppressed because one or more lines are too long
|
@ -4,161 +4,7 @@ library body_parser;
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
part 'file_upload_info.dart';
|
||||
|
||||
/// A representation of data from an incoming request.
|
||||
class BodyParseResult {
|
||||
/// The parsed body.
|
||||
Map body = {};
|
||||
|
||||
/// The parsed query string.
|
||||
Map query = {};
|
||||
|
||||
/// All files uploaded within this request.
|
||||
List<FileUploadInfo> files = [];
|
||||
}
|
||||
|
||||
/// Grabs data from an incoming request.
|
||||
///
|
||||
/// Supports urlencoded and JSON, as well as multipart/form-data uploads.
|
||||
/// On a file upload request, only fields with the name **'file'** are processed
|
||||
/// as files. Anything else is put in the body. You can change the upload file name
|
||||
/// via the *fileUploadName* parameter. :)
|
||||
Future<BodyParseResult> parseBody(HttpRequest request,
|
||||
{String fileUploadName: 'file'}) async {
|
||||
BodyParseResult result = new BodyParseResult();
|
||||
ContentType contentType = request.headers.contentType;
|
||||
|
||||
// Parse body
|
||||
if (contentType != null) {
|
||||
if (contentType.mimeType == 'application/json')
|
||||
result.body = JSON.decode(await request.transform(UTF8.decoder).join());
|
||||
else if (contentType.mimeType == 'application/x-www-form-urlencoded') {
|
||||
String body = await request.transform(UTF8.decoder).join();
|
||||
buildMapFromUri(result.body, body);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse query
|
||||
RegExp queryRgx = new RegExp(r'\?(.+)$');
|
||||
String uriString = request.requestedUri.toString();
|
||||
if (queryRgx.hasMatch(uriString)) {
|
||||
Match queryMatch = queryRgx.firstMatch(uriString);
|
||||
buildMapFromUri(result.query, queryMatch.group(1));
|
||||
}
|
||||
|
||||
// Accept file
|
||||
if (contentType != null && request.method == 'POST') {
|
||||
RegExp parseBoundaryRgx = new RegExp(
|
||||
r'multipart\/form-data;\s*boundary=([^\s;]+)');
|
||||
if (parseBoundaryRgx.hasMatch(contentType.toString())) {
|
||||
Match boundaryMatch = parseBoundaryRgx.firstMatch(contentType.toString());
|
||||
String boundary = boundaryMatch.group(1);
|
||||
String body = await request.transform(UTF8.decoder).join();
|
||||
for (String chunk in body.split(boundary)) {
|
||||
var fileData = getFileDataFromChunk(
|
||||
chunk, boundary, fileUploadName, result.body);
|
||||
if (fileData != null)
|
||||
fileData.forEach((x) => result.files.add(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Parses file data from a multipart/form-data chunk.
|
||||
List<FileUploadInfo> getFileDataFromChunk(String chunk, String boundary, String fileUploadName,
|
||||
Map body) {
|
||||
FileUploadInfo result = new FileUploadInfo();
|
||||
RegExp isFormDataRgx = new RegExp(
|
||||
r'Content-Disposition:\s*([^;]+);\s*name="([^"]+)"');
|
||||
|
||||
if (isFormDataRgx.hasMatch(chunk)) {
|
||||
Match formDataMatch = isFormDataRgx.firstMatch(chunk);
|
||||
String disposition = formDataMatch.group(1);
|
||||
String name = formDataMatch.group(2);
|
||||
String restOfChunk = chunk.substring(formDataMatch.end);
|
||||
|
||||
RegExp parseFilenameRgx = new RegExp(r'filename="([^"]+)"');
|
||||
if (parseFilenameRgx.hasMatch(chunk)) {
|
||||
result.filename = parseFilenameRgx.firstMatch(chunk).group(1);
|
||||
}
|
||||
|
||||
RegExp contentTypeRgx = new RegExp(r'Content-Type:\s*([^\r\n]+)\r\n');
|
||||
if (contentTypeRgx.hasMatch(restOfChunk)) {
|
||||
Match contentTypeMatch = contentTypeRgx.firstMatch(restOfChunk);
|
||||
restOfChunk = restOfChunk.substring(contentTypeMatch.end);
|
||||
result.mimeType = contentTypeMatch.group(1);
|
||||
} else restOfChunk = restOfChunk.replaceAll(new RegExp(r'^(\r\n)+'), "");
|
||||
|
||||
restOfChunk = restOfChunk
|
||||
.replaceAll(boundary, "")
|
||||
.replaceFirst(new RegExp(r'\r\n$'), "");
|
||||
|
||||
if (disposition == 'file' && name == fileUploadName) {
|
||||
result.name = name;
|
||||
result.data = UTF8.encode(restOfChunk);
|
||||
return [result];
|
||||
} else {
|
||||
buildMapFromUri(body, "$name=$restOfChunk");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Parses a URI-encoded string into real data! **Wow!**
|
||||
///
|
||||
/// Whichever map you provide will be automatically populated from the urlencoded body string you provide.
|
||||
buildMapFromUri(Map map, String body) {
|
||||
RegExp parseArrayRgx = new RegExp(r'^(.+)\[\]$');
|
||||
|
||||
for (String keyValuePair in body.split('&')) {
|
||||
if (keyValuePair.contains('=')) {
|
||||
List<String> split = keyValuePair.split('=');
|
||||
String key = Uri.decodeQueryComponent(split[0]);
|
||||
String value = Uri.decodeQueryComponent(split[1]);
|
||||
|
||||
if (parseArrayRgx.hasMatch(key)) {
|
||||
Match queryMatch = parseArrayRgx.firstMatch(key);
|
||||
key = queryMatch.group(1);
|
||||
if (!(map[key] is List)) {
|
||||
map[key] = [];
|
||||
}
|
||||
|
||||
map[key].add(getValue(value));
|
||||
} else if (key.contains('.')) {
|
||||
// i.e. map.foo.bar => [map, foo, bar]
|
||||
List<String> keys = key.split('.');
|
||||
|
||||
Map targetMap = map[keys[0]] ?? {};
|
||||
map[keys[0]] = targetMap;
|
||||
for (int i = 1; i < keys.length; i++) {
|
||||
if (i < keys.length - 1) {
|
||||
targetMap[keys[i]] = targetMap[keys[i]] ?? {};
|
||||
targetMap = targetMap[keys[i]];
|
||||
} else {
|
||||
targetMap[keys[i]] = getValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else map[key] = getValue(value);
|
||||
} else map[Uri.decodeQueryComponent(keyValuePair)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
getValue(String value) {
|
||||
num numValue = num.parse(value, (_) => double.NAN);
|
||||
if (!numValue.isNaN)
|
||||
return numValue;
|
||||
else if (value.startsWith('[') && value.endsWith(']'))
|
||||
return JSON.decode(value);
|
||||
else if (value.startsWith('{') && value.endsWith('}'))
|
||||
return JSON.decode(value);
|
||||
else if (value.trim().toLowerCase() == 'null')
|
||||
return null;
|
||||
else return value;
|
||||
}
|
||||
export 'src/body_parser.dart';
|
||||
export 'src/body_parse_result.dart';
|
||||
export 'src/file_upload_info.dart';
|
||||
export 'src/parse_body.dart';
|
||||
|
|
13
lib/src/body_parse_result.dart
Normal file
13
lib/src/body_parse_result.dart
Normal file
|
@ -0,0 +1,13 @@
|
|||
import 'file_upload_info.dart';
|
||||
|
||||
/// A representation of data from an incoming request.
|
||||
class BodyParseResult {
|
||||
/// The parsed body.
|
||||
Map body = {};
|
||||
|
||||
/// The parsed query string.
|
||||
Map query = {};
|
||||
|
||||
/// All files uploaded within this request.
|
||||
List<FileUploadInfo> files = [];
|
||||
}
|
21
lib/src/body_parser.dart
Normal file
21
lib/src/body_parser.dart
Normal file
|
@ -0,0 +1,21 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'body_parse_result.dart';
|
||||
|
||||
class BodyParser implements StreamTransformer<List<int>, BodyParseResult> {
|
||||
|
||||
@override
|
||||
Stream<BodyParseResult> bind(HttpRequest stream) {
|
||||
var _stream = new StreamController<BodyParseResult>();
|
||||
|
||||
stream.toList().then((lists) {
|
||||
var ints = [];
|
||||
lists.forEach(ints.addAll);
|
||||
_stream.close();
|
||||
|
||||
|
||||
});
|
||||
|
||||
return _stream.stream;
|
||||
}
|
||||
}
|
8
lib/src/chunk.dart
Normal file
8
lib/src/chunk.dart
Normal file
|
@ -0,0 +1,8 @@
|
|||
import 'file_upload_info.dart';
|
||||
|
||||
List<FileUploadInfo> getFileDataFromChunk(String chunk, String boundary,
|
||||
String fileUploadName,
|
||||
Map body) {
|
||||
List<FileUploadInfo> result = [];
|
||||
return result;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
part of body_parser;
|
||||
|
||||
/// Represents a file uploaded to the server.
|
||||
class FileUploadInfo {
|
||||
/// The MIME type of the uploaded file.
|
14
lib/src/get_value.dart
Normal file
14
lib/src/get_value.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
import 'dart:convert';
|
||||
|
||||
getValue(String value) {
|
||||
num numValue = num.parse(value, (_) => double.NAN);
|
||||
if (!numValue.isNaN)
|
||||
return numValue;
|
||||
else if (value.startsWith('[') && value.endsWith(']'))
|
||||
return JSON.decode(value);
|
||||
else if (value.startsWith('{') && value.endsWith('}'))
|
||||
return JSON.decode(value);
|
||||
else if (value.trim().toLowerCase() == 'null')
|
||||
return null;
|
||||
else return value;
|
||||
}
|
41
lib/src/map_from_uri.dart
Normal file
41
lib/src/map_from_uri.dart
Normal file
|
@ -0,0 +1,41 @@
|
|||
import 'get_value.dart';
|
||||
|
||||
/// Parses a URI-encoded string into real data! **Wow!**
|
||||
///
|
||||
/// Whichever map you provide will be automatically populated from the urlencoded body string you provide.
|
||||
buildMapFromUri(Map map, String body) {
|
||||
RegExp parseArrayRgx = new RegExp(r'^(.+)\[\]$');
|
||||
|
||||
for (String keyValuePair in body.split('&')) {
|
||||
if (keyValuePair.contains('=')) {
|
||||
List<String> split = keyValuePair.split('=');
|
||||
String key = Uri.decodeQueryComponent(split[0]);
|
||||
String value = Uri.decodeQueryComponent(split[1]);
|
||||
|
||||
if (parseArrayRgx.hasMatch(key)) {
|
||||
Match queryMatch = parseArrayRgx.firstMatch(key);
|
||||
key = queryMatch.group(1);
|
||||
if (!(map[key] is List)) {
|
||||
map[key] = [];
|
||||
}
|
||||
|
||||
map[key].add(getValue(value));
|
||||
} else if (key.contains('.')) {
|
||||
// i.e. map.foo.bar => [map, foo, bar]
|
||||
List<String> keys = key.split('.');
|
||||
|
||||
Map targetMap = map[keys[0]] ?? {};
|
||||
map[keys[0]] = targetMap;
|
||||
for (int i = 1; i < keys.length; i++) {
|
||||
if (i < keys.length - 1) {
|
||||
targetMap[keys[i]] = targetMap[keys[i]] ?? {};
|
||||
targetMap = targetMap[keys[i]];
|
||||
} else {
|
||||
targetMap[keys[i]] = getValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else map[key] = getValue(value);
|
||||
} else map[Uri.decodeQueryComponent(keyValuePair)] = true;
|
||||
}
|
||||
}
|
59
lib/src/parse_body.dart
Normal file
59
lib/src/parse_body.dart
Normal file
|
@ -0,0 +1,59 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:http_server/http_server.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'body_parse_result.dart';
|
||||
import 'chunk.dart';
|
||||
import 'file_upload_info.dart';
|
||||
import 'map_from_uri.dart';
|
||||
|
||||
/// Grabs data from an incoming request.
|
||||
///
|
||||
/// Supports URL-encoded and JSON, as well as multipart/* forms.
|
||||
/// On a file upload request, only fields with the name **'file'** are processed
|
||||
/// as files. Anything else is put in the body. You can change the upload file name
|
||||
/// via the *fileUploadName* parameter. :)
|
||||
Future<BodyParseResult> parseBody(HttpRequest request) async {
|
||||
var result = new BodyParseResult();
|
||||
|
||||
if (request.headers.contentType != null) {
|
||||
if (request.headers.contentType.primaryType == 'multipart' &&
|
||||
request.headers.contentType.parameters.containsKey('boundary')) {
|
||||
var parts = request
|
||||
.transform(new MimeMultipartTransformer(
|
||||
request.headers.contentType.parameters['boundary']))
|
||||
.map((part) =>
|
||||
HttpMultipartFormData.parse(part, defaultEncoding: UTF8));
|
||||
|
||||
await for (HttpMultipartFormData part in parts) {
|
||||
if (part.isBinary || part.contentDisposition.parameters.containsKey("filename")) {
|
||||
BytesBuilder builder = await part.fold(new BytesBuilder(), (BytesBuilder b, d) => b..add(d is! String ? d : d.codeUnits));
|
||||
var upload = new FileUploadInfo(
|
||||
mimeType: part.contentType.mimeType,
|
||||
name: part.contentDisposition.parameters['name'],
|
||||
filename: part.contentDisposition.parameters['filename'] ?? 'file',
|
||||
data: builder.takeBytes());
|
||||
result.files.add(upload);
|
||||
} else if (part.isText) {
|
||||
var text = await part.join();
|
||||
buildMapFromUri(result.body, '${part.contentDisposition.parameters["name"]}=$text');
|
||||
} else {
|
||||
print("Found something else : ${part.contentDisposition}");
|
||||
}
|
||||
}
|
||||
} else if (request.headers.contentType.mimeType ==
|
||||
ContentType.JSON.mimeType) {
|
||||
result.body
|
||||
.addAll(JSON.decode(await request.transform(UTF8.decoder).join()));
|
||||
} else if (request.headers.contentType.mimeType ==
|
||||
'application/x-www-form-urlencoded') {
|
||||
String body = await request.transform(UTF8.decoder).join();
|
||||
buildMapFromUri(result.body, body);
|
||||
}
|
||||
} else if (request.uri.hasQuery) {
|
||||
buildMapFromUri(result.query, request.uri.query);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
10
pubspec.yaml
10
pubspec.yaml
|
@ -1,9 +1,11 @@
|
|||
name: body_parser
|
||||
author: Tobe O <thosakwe@gmail.com>
|
||||
version: 1.0.0-dev
|
||||
version: 1.0.0-dev+1
|
||||
description: Parse request bodies and query strings in Dart.
|
||||
homepage: https://github.com/thosakwe/body_parser
|
||||
dependencies:
|
||||
http_server: ">=0.9.6 <1.0.0"
|
||||
dev_dependencies:
|
||||
http: any
|
||||
json_god: any
|
||||
test: any
|
||||
http: ">=0.11.3 <0.12.0"
|
||||
json_god: ">=2.0.0-beta <3.0.0"
|
||||
test: ">=0.12.15 <0.13.0"
|
|
@ -1,168 +1,9 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:body_parser/body_parser.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_god/json_god.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'server.dart' as server;
|
||||
import 'uploads.dart' as uploads;
|
||||
|
||||
main() {
|
||||
group('Test server support', () {
|
||||
HttpServer server;
|
||||
String url;
|
||||
http.Client client;
|
||||
God god;
|
||||
|
||||
setUp(() async {
|
||||
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
server.listen((HttpRequest request) async {
|
||||
//Server will simply return a JSON representation of the parsed body
|
||||
request.response.write(god.serialize(await parseBody(request)));
|
||||
await request.response.close();
|
||||
});
|
||||
url = 'http://localhost:${server.port}';
|
||||
print('Test server listening on $url');
|
||||
client = new http.Client();
|
||||
god = new God();
|
||||
});
|
||||
tearDown(() async {
|
||||
await server.close(force: true);
|
||||
client.close();
|
||||
server = null;
|
||||
url = null;
|
||||
client = null;
|
||||
god = null;
|
||||
});
|
||||
|
||||
group('query string', () {
|
||||
test('GET Simple', () async {
|
||||
print('GET $url/?hello=world');
|
||||
var response = await client.get('$url/?hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{},"query":{"hello":"world"},"files":[]}'));
|
||||
});
|
||||
|
||||
test('GET Complex', () async {
|
||||
var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 -
|
||||
1}&map.foo.bar=baz';
|
||||
print('Body: $postData');
|
||||
var response = await client.get('$url/?$postData');
|
||||
print('Response: ${response.body}');
|
||||
var query = god.deserialize(response.body)['query'];
|
||||
expect(query['hello'], equals('world'));
|
||||
expect(query['nums'][2], equals(2));
|
||||
expect(query['map'] is Map, equals(true));
|
||||
expect(query['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
|
||||
group('urlencoded', () {
|
||||
Map<String, String> headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'application/x-www-form-urlencoded'
|
||||
};
|
||||
test('POST Simple', () async {
|
||||
print('Body: hello=world');
|
||||
var response = await client.post(
|
||||
url, headers: headers, body: 'hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{"hello":"world"},"query":{},"files":[]}'));
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 -
|
||||
1}&map.foo.bar=baz';
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
var body = god.deserialize(response.body)['body'];
|
||||
expect(body['hello'], equals('world'));
|
||||
expect(body['nums'][2], equals(2));
|
||||
expect(body['map'] is Map, equals(true));
|
||||
expect(body['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
|
||||
group('JSON', () {
|
||||
Map<String, String> headers = {
|
||||
HttpHeaders.CONTENT_TYPE: ContentType.JSON.toString()
|
||||
};
|
||||
test('Post Simple', () async {
|
||||
var postData = god.serialize({
|
||||
'hello': 'world'
|
||||
});
|
||||
print('Body: $postData');
|
||||
var response = await client.post(
|
||||
url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{"hello":"world"},"query":{},"files":[]}'));
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
var postData = god.serialize({
|
||||
'hello': 'world',
|
||||
'nums': [1, 2.0, 3 - 1],
|
||||
'map': {
|
||||
'foo': {
|
||||
'bar': 'baz'
|
||||
}
|
||||
}
|
||||
});
|
||||
print('Body: $postData');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
var body = god.deserialize(response.body)['body'];
|
||||
expect(body['hello'], equals('world'));
|
||||
expect(body['nums'][2], equals(2));
|
||||
expect(body['map'] is Map, equals(true));
|
||||
expect(body['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
|
||||
group('File', () {
|
||||
test('Single upload', () async {
|
||||
String boundary = '----myBoundary';
|
||||
Map headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'multipart/form-data; boundary=$boundary'
|
||||
};
|
||||
String postData = '\r\n$boundary\r\n' +
|
||||
'Content-Disposition: form-data; name="hello"\r\nworld\r\n$boundary\r\n' +
|
||||
'Content-Disposition: file; name="file"; filename="app.dart"\r\n' +
|
||||
'Content-Type: text/plain\r\nHello world\r\n$boundary--';
|
||||
|
||||
print('Form Data: \n$postData');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
Map json = god.deserialize(response.body);
|
||||
List<Map> files = json['files'];
|
||||
expect(files.length, equals(1));
|
||||
expect(files[0]['name'], equals('file'));
|
||||
expect(files[0]['mimeType'], equals('text/plain'));
|
||||
expect(files[0]['data'].length, equals(11));
|
||||
expect(files[0]['filename'], equals('app.dart'));
|
||||
expect(json['body']['hello'], equals('world'));
|
||||
});
|
||||
|
||||
test('Multiple upload', () async {
|
||||
String boundary = '----myBoundary';
|
||||
Map headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'multipart/form-data; boundary=$boundary'
|
||||
};
|
||||
String postData = '\r\n$boundary\r\n' +
|
||||
'Content-Disposition: form-data; name="json"\r\ngod\r\n$boundary\r\n' +
|
||||
'Content-Disposition: file; name="file"; filename="app.dart"\r\n' +
|
||||
'Content-Type: text/plain\r\nHello world\r\n$boundary--';
|
||||
|
||||
print('Form Data: \n$postData');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
Map json = god.deserialize(response.body);
|
||||
List<Map> files = json['files'];
|
||||
expect(files.length, equals(1));
|
||||
expect(files[0]['name'], equals('file'));
|
||||
expect(files[0]['mimeType'], equals('text/plain'));
|
||||
expect(files[0]['data'].length, equals(11));
|
||||
expect(json['body']['json'], equals('god'));
|
||||
}, skip: 'Multiple file uploads are yet to come.');
|
||||
});
|
||||
});
|
||||
}
|
||||
group('server', server.main);
|
||||
group('uploads', uploads.main);
|
||||
}
|
||||
|
|
110
test/server.dart
Normal file
110
test/server.dart
Normal file
|
@ -0,0 +1,110 @@
|
|||
import 'dart:io';
|
||||
import 'package:body_parser/body_parser.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_god/json_god.dart' as god;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
main() {
|
||||
HttpServer server;
|
||||
String url;
|
||||
http.Client client;
|
||||
|
||||
setUp(() async {
|
||||
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
server.listen((HttpRequest request) async {
|
||||
//Server will simply return a JSON representation of the parsed body
|
||||
request.response.write(god.serialize(await parseBody(request)));
|
||||
await request.response.close();
|
||||
});
|
||||
url = 'http://localhost:${server.port}';
|
||||
print('Test server listening on $url');
|
||||
client = new http.Client();
|
||||
});
|
||||
tearDown(() async {
|
||||
await server.close(force: true);
|
||||
client.close();
|
||||
server = null;
|
||||
url = null;
|
||||
client = null;
|
||||
});
|
||||
|
||||
group('query string', () {
|
||||
test('GET Simple', () async {
|
||||
print('GET $url/?hello=world');
|
||||
var response = await client.get('$url/?hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{},"query":{"hello":"world"},"files":[]}'));
|
||||
});
|
||||
|
||||
test('GET Complex', () async {
|
||||
var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 -
|
||||
1}&map.foo.bar=baz';
|
||||
print('Body: $postData');
|
||||
var response = await client.get('$url/?$postData');
|
||||
print('Response: ${response.body}');
|
||||
var query = god.deserialize(response.body)['query'];
|
||||
expect(query['hello'], equals('world'));
|
||||
expect(query['nums'][2], equals(2));
|
||||
expect(query['map'] is Map, equals(true));
|
||||
expect(query['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
|
||||
group('urlencoded', () {
|
||||
Map<String, String> headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'application/x-www-form-urlencoded'
|
||||
};
|
||||
test('POST Simple', () async {
|
||||
print('Body: hello=world');
|
||||
var response =
|
||||
await client.post(url, headers: headers, body: 'hello=world');
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{"hello":"world"},"query":{},"files":[]}'));
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
var postData = 'hello=world&nums%5B%5D=1&nums%5B%5D=2.0&nums%5B%5D=${3 -
|
||||
1}&map.foo.bar=baz';
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
var body = god.deserialize(response.body)['body'];
|
||||
expect(body['hello'], equals('world'));
|
||||
expect(body['nums'][2], equals(2));
|
||||
expect(body['map'] is Map, equals(true));
|
||||
expect(body['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
|
||||
group('JSON', () {
|
||||
Map<String, String> headers = {
|
||||
HttpHeaders.CONTENT_TYPE: ContentType.JSON.toString()
|
||||
};
|
||||
test('Post Simple', () async {
|
||||
var postData = god.serialize({'hello': 'world'});
|
||||
print('Body: $postData');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
expect(response.body,
|
||||
equals('{"body":{"hello":"world"},"query":{},"files":[]}'));
|
||||
});
|
||||
|
||||
test('Post Complex', () async {
|
||||
var postData = god.serialize({
|
||||
'hello': 'world',
|
||||
'nums': [1, 2.0, 3 - 1],
|
||||
'map': {
|
||||
'foo': {'bar': 'baz'}
|
||||
}
|
||||
});
|
||||
print('Body: $postData');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
var body = god.deserialize(response.body)['body'];
|
||||
expect(body['hello'], equals('world'));
|
||||
expect(body['nums'][2], equals(2));
|
||||
expect(body['map'] is Map, equals(true));
|
||||
expect(body['map']['foo'], equals({'bar': 'baz'}));
|
||||
});
|
||||
});
|
||||
}
|
135
test/uploads.dart
Normal file
135
test/uploads.dart
Normal file
|
@ -0,0 +1,135 @@
|
|||
import 'dart:io';
|
||||
import 'package:body_parser/body_parser.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:json_god/json_god.dart' as god;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
main() {
|
||||
HttpServer server;
|
||||
String url;
|
||||
http.Client client;
|
||||
|
||||
setUp(() async {
|
||||
server = await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0);
|
||||
server.listen((HttpRequest request) async {
|
||||
//Server will simply return a JSON representation of the parsed body
|
||||
request.response.write(god.serialize(await parseBody(request)));
|
||||
await request.response.close();
|
||||
});
|
||||
url = 'http://localhost:${server.port}';
|
||||
print('Test server listening on $url');
|
||||
client = new http.Client();
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await server.close(force: true);
|
||||
client.close();
|
||||
server = null;
|
||||
url = null;
|
||||
client = null;
|
||||
});
|
||||
|
||||
test('No upload', () async {
|
||||
String boundary = 'myBoundary';
|
||||
Map headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'multipart/form-data; boundary=$boundary'
|
||||
};
|
||||
String postData = '''
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="hello"
|
||||
|
||||
world
|
||||
--$boundary--
|
||||
'''
|
||||
.replaceAll("\n", "\r\n");
|
||||
|
||||
print(
|
||||
'Form Data: \n${postData.replaceAll("\r", "\\r").replaceAll("\n", "\\n")}');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
Map json = god.deserialize(response.body);
|
||||
List<Map> files = json['files'];
|
||||
expect(files.length, equals(0));
|
||||
expect(json['body']['hello'], equals('world'));
|
||||
});
|
||||
|
||||
test('Single upload', () async {
|
||||
String boundary = 'myBoundary';
|
||||
Map headers = {
|
||||
HttpHeaders.CONTENT_TYPE: new ContentType("multipart", "form-data",
|
||||
parameters: {"boundary": boundary}).toString()
|
||||
};
|
||||
String postData = '''
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="hello"
|
||||
|
||||
world
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="file"; filename="app.dart"
|
||||
Content-Type: application/dart
|
||||
|
||||
Hello world
|
||||
--$boundary--
|
||||
'''
|
||||
.replaceAll("\n", "\r\n");
|
||||
|
||||
print(
|
||||
'Form Data: \n${postData.replaceAll("\r", "\\r").replaceAll("\n", "\\n")}');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
Map json = god.deserialize(response.body);
|
||||
List<Map> files = json['files'];
|
||||
expect(files.length, equals(1));
|
||||
expect(files[0]['name'], equals('file'));
|
||||
expect(files[0]['mimeType'], equals('application/dart'));
|
||||
expect(files[0]['data'].length, equals(11));
|
||||
expect(files[0]['filename'], equals('app.dart'));
|
||||
expect(json['body']['hello'], equals('world'));
|
||||
});
|
||||
|
||||
test('Multiple upload', () async {
|
||||
String boundary = 'myBoundary';
|
||||
Map headers = {
|
||||
HttpHeaders.CONTENT_TYPE: 'multipart/form-data; boundary=$boundary'
|
||||
};
|
||||
String postData = '''
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="json"
|
||||
|
||||
god
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="num"
|
||||
|
||||
14.50000
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="file"; filename="app.dart"
|
||||
Content-Type: text/plain
|
||||
|
||||
Hello world
|
||||
--$boundary
|
||||
Content-Disposition: form-data; name="entry-point"; filename="main.js"
|
||||
Content-Type: text/javascript
|
||||
|
||||
function main() {
|
||||
console.log("Hello, world!");
|
||||
}
|
||||
--$boundary--
|
||||
'''
|
||||
.replaceAll("\n", "\r\n");
|
||||
|
||||
print(
|
||||
'Form Data: \n${postData.replaceAll("\r", "\\r").replaceAll("\n", "\\n")}');
|
||||
var response = await client.post(url, headers: headers, body: postData);
|
||||
print('Response: ${response.body}');
|
||||
Map json = god.deserialize(response.body);
|
||||
List<Map> files = json['files'];
|
||||
expect(files.length, equals(2));
|
||||
expect(files[0]['name'], equals('file'));
|
||||
expect(files[0]['mimeType'], equals('text/plain'));
|
||||
expect(files[0]['data'].length, equals(11));
|
||||
expect(files[1]['name'], equals('entry-point'));
|
||||
expect(files[1]['mimeType'], equals('text/javascript'));
|
||||
expect(json['body']['json'], equals('god'));
|
||||
expect(json['body']['num'], equals(14.5));
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue