Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
31254fbe
Unverified
Commit
31254fbe
authored
Sep 25, 2020
by
Mouad Debbar
Committed by
GitHub
Sep 25, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[web] Change the web server to support path url strategy (#66606)
parent
eb543889
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
133 additions
and
63 deletions
+133
-63
devfs_web.dart
packages/flutter_tools/lib/src/build_runner/devfs_web.dart
+69
-26
devfs_web_test.dart
.../flutter_tools/test/general.shard/web/devfs_web_test.dart
+64
-37
No files found.
packages/flutter_tools/lib/src/build_runner/devfs_web.dart
View file @
31254fbe
...
...
@@ -190,6 +190,7 @@ class WebAssetServer implements AssetReader {
platform:
globals
.
platform
,
flutterRoot:
Cache
.
flutterRoot
,
webBuildDirectory:
getWebBuildDirectory
(),
basePath:
server
.
basePath
,
);
shelf
.
serveRequests
(
httpServer
,
releaseAssetServer
.
handle
);
return
server
;
...
...
@@ -316,30 +317,28 @@ class WebAssetServer implements AssetReader {
@visibleForTesting
Uint8List
getMetadata
(
String
path
)
=>
_metadataFiles
[
path
];
@visibleForTesting
/// The base path to serve from.
///
/// It should have no leading or trailing slashes.
String
basePath
=
''
;
// handle requests for JavaScript source, dart sources maps, or asset files.
@visibleForTesting
Future
<
shelf
.
Response
>
handleRequest
(
shelf
.
Request
request
)
async
{
String
requestPath
=
request
.
url
.
path
;
while
(
requestPath
.
startsWith
(
'/'
))
{
requestPath
=
requestPath
.
substring
(
1
);
final
String
requestPath
=
_stripBasePath
(
request
.
url
.
path
,
basePath
);
if
(
requestPath
==
null
)
{
return
shelf
.
Response
.
notFound
(
''
);
}
final
Map
<
String
,
String
>
headers
=
<
String
,
String
>{};
// If the response is `/`, then we are requesting the index file.
if
(
request
.
url
.
path
==
'/'
||
request
.
url
.
path
.
isEmpty
)
{
final
File
indexFile
=
globals
.
fs
.
currentDirectory
.
childDirectory
(
'web'
)
.
childFile
(
'index.html'
);
if
(
indexFile
.
existsSync
())
{
headers
[
HttpHeaders
.
contentTypeHeader
]
=
'text/html'
;
headers
[
HttpHeaders
.
contentLengthHeader
]
=
indexFile
.
lengthSync
().
toString
();
return
shelf
.
Response
.
ok
(
indexFile
.
openRead
(),
headers:
headers
);
}
else
{
headers
[
HttpHeaders
.
contentTypeHeader
]
=
'text/html'
;
headers
[
HttpHeaders
.
contentLengthHeader
]
=
_kDefaultIndex
.
length
.
toString
();
return
shelf
.
Response
.
ok
(
_kDefaultIndex
,
headers:
headers
);
}
if
(
requestPath
==
'/'
||
requestPath
.
isEmpty
)
{
return
_serveIndex
();
}
final
Map
<
String
,
String
>
headers
=
<
String
,
String
>{};
// Track etag headers for better caching of resources.
final
String
ifNoneMatch
=
request
.
headers
[
HttpHeaders
.
ifNoneMatchHeader
];
headers
[
HttpHeaders
.
cacheControlHeader
]
=
'max-age=0, must-revalidate'
;
...
...
@@ -407,7 +406,7 @@ class WebAssetServer implements AssetReader {
}
if
(!
file
.
existsSync
())
{
return
shelf
.
Response
.
notFound
(
''
);
return
_serveIndex
(
);
}
// For real files, use a serialized file stat plus path as a revision.
...
...
@@ -536,6 +535,23 @@ class WebAssetServer implements AssetReader {
/// Whether to use the cavaskit SDK for rendering.
bool
canvasKitRendering
=
false
;
shelf
.
Response
_serveIndex
()
{
final
Map
<
String
,
String
>
headers
=
<
String
,
String
>{
HttpHeaders
.
contentTypeHeader
:
'text/html'
,
};
final
File
indexFile
=
globals
.
fs
.
currentDirectory
.
childDirectory
(
'web'
)
.
childFile
(
'index.html'
);
if
(
indexFile
.
existsSync
())
{
headers
[
HttpHeaders
.
contentLengthHeader
]
=
indexFile
.
lengthSync
().
toString
();
return
shelf
.
Response
.
ok
(
indexFile
.
openRead
(),
headers:
headers
);
}
headers
[
HttpHeaders
.
contentLengthHeader
]
=
_kDefaultIndex
.
length
.
toString
();
return
shelf
.
Response
.
ok
(
_kDefaultIndex
,
headers:
headers
);
}
// Attempt to resolve `path` to a dart file.
File
_resolveDartFile
(
String
path
)
{
// Return the actual file objects so that local engine changes are automatically picked up.
...
...
@@ -907,6 +923,7 @@ class ReleaseAssetServer {
@required
String
webBuildDirectory
,
@required
String
flutterRoot
,
@required
Platform
platform
,
this
.
basePath
=
''
,
})
:
_fileSystem
=
fileSystem
,
_platform
=
platform
,
_flutterRoot
=
flutterRoot
,
...
...
@@ -920,6 +937,12 @@ class ReleaseAssetServer {
final
FileSystemUtils
_fileSystemUtils
;
final
Platform
_platform
;
@visibleForTesting
/// The base path to serve from.
///
/// It should have no leading or trailing slashes.
final
String
basePath
;
// Locations where source files, assets, or source maps may be located.
List
<
Uri
>
_searchPaths
()
=>
<
Uri
>[
_fileSystem
.
directory
(
_webBuildDirectory
).
uri
,
...
...
@@ -931,11 +954,17 @@ class ReleaseAssetServer {
Future
<
shelf
.
Response
>
handle
(
shelf
.
Request
request
)
async
{
Uri
fileUri
;
final
String
requestPath
=
_stripBasePath
(
request
.
url
.
path
,
basePath
);
if
(
requestPath
==
null
)
{
return
shelf
.
Response
.
notFound
(
''
);
}
if
(
request
.
url
.
toString
()
==
'main.dart'
)
{
fileUri
=
entrypoint
;
}
else
{
for
(
final
Uri
uri
in
_searchPaths
())
{
final
Uri
potential
=
uri
.
resolve
(
request
.
url
.
p
ath
);
final
Uri
potential
=
uri
.
resolve
(
request
P
ath
);
if
(
potential
==
null
||
!
_fileSystem
.
isFileSync
(
potential
.
toFilePath
(
windows:
_platform
.
isWindows
)))
{
continue
;
...
...
@@ -955,13 +984,11 @@ class ReleaseAssetServer {
'Content-Type'
:
mimeType
,
});
}
if
(
request
.
url
.
path
==
''
)
{
final
File
file
=
_fileSystem
.
file
(
_fileSystem
.
path
.
join
(
_webBuildDirectory
,
'index.html'
));
return
shelf
.
Response
.
ok
(
file
.
readAsBytesSync
(),
headers:
<
String
,
String
>{
'Content-Type'
:
'text/html'
,
});
}
return
shelf
.
Response
.
notFound
(
''
);
final
File
file
=
_fileSystem
.
file
(
_fileSystem
.
path
.
join
(
_webBuildDirectory
,
'index.html'
));
return
shelf
.
Response
.
ok
(
file
.
readAsBytesSync
(),
headers:
<
String
,
String
>{
'Content-Type'
:
'text/html'
,
});
}
}
...
...
@@ -975,3 +1002,19 @@ Future<Directory> _loadDwdsDirectory(FileSystem fileSystem, Logger logger) async
);
return
fileSystem
.
directory
(
packageConfig
[
'dwds'
].
packageUriRoot
);
}
String
_stripBasePath
(
String
path
,
String
basePath
)
{
while
(
path
.
startsWith
(
'/'
))
{
path
=
path
.
substring
(
1
);
}
if
(
path
.
startsWith
(
basePath
))
{
path
=
path
.
substring
(
basePath
.
length
);
}
else
{
// The given path isn't under base path, return null to indicate that.
return
null
;
}
while
(
path
.
startsWith
(
'/'
))
{
path
=
path
.
substring
(
1
);
}
return
path
;
}
packages/flutter_tools/test/general.shard/web/devfs_web_test.dart
View file @
31254fbe
...
...
@@ -160,6 +160,61 @@ void main() {
expect
((
await
response
.
read
().
toList
()).
first
,
source
.
readAsBytesSync
());
}));
test
(
'takes base path into account when serving'
,
()
=>
testbed
.
run
(()
async
{
webAssetServer
.
basePath
=
'base/path'
;
globals
.
fs
.
file
(
'foo.png'
).
createSync
();
globals
.
fs
.
currentDirectory
=
globals
.
fs
.
directory
(
'project_directory'
)
..
createSync
();
final
File
source
=
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'web'
,
'foo.png'
))
..
createSync
(
recursive:
true
)
..
writeAsBytesSync
(
kTransparentImage
);
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/base/path/foo.png'
)),
);
expect
(
response
.
headers
,
allOf
(<
Matcher
>[
containsPair
(
HttpHeaders
.
contentLengthHeader
,
source
.
lengthSync
().
toString
()),
containsPair
(
HttpHeaders
.
contentTypeHeader
,
'image/png'
),
containsPair
(
HttpHeaders
.
etagHeader
,
isNotNull
),
containsPair
(
HttpHeaders
.
cacheControlHeader
,
'max-age=0, must-revalidate'
)
]));
expect
((
await
response
.
read
().
toList
()).
first
,
source
.
readAsBytesSync
());
}));
test
(
'serves index.html at the base path'
,
()
=>
testbed
.
run
(()
async
{
webAssetServer
.
basePath
=
'base/path'
;
const
String
htmlContent
=
'<html><head></head><body id="test"></body></html>'
;
final
Directory
webDir
=
globals
.
fs
.
currentDirectory
.
childDirectory
(
'web'
)
..
createSync
();
webDir
.
childFile
(
'index.html'
).
writeAsStringSync
(
htmlContent
);
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/base/path/'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
ok
);
expect
(
await
response
.
readAsString
(),
htmlContent
);
}));
test
(
'does not serve outside the base path'
,
()
=>
testbed
.
run
(()
async
{
webAssetServer
.
basePath
=
'base/path'
;
const
String
htmlContent
=
'<html><head></head><body id="test"></body></html>'
;
final
Directory
webDir
=
globals
.
fs
.
currentDirectory
.
childDirectory
(
'web'
)
..
createSync
();
webDir
.
childFile
(
'index.html'
).
writeAsStringSync
(
htmlContent
);
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
notFound
);
}));
test
(
'serves JavaScript files from in memory cache not from manifest'
,
()
=>
testbed
.
run
(()
async
{
webAssetServer
.
writeFile
(
'foo.js'
,
'main() {}'
);
...
...
@@ -191,25 +246,18 @@ void main() {
expect
(
await
cachedResponse
.
read
().
toList
(),
isEmpty
);
}));
test
(
'handles missing JavaScript files from in memory cache'
,
()
=>
testbed
.
run
(()
async
{
final
File
source
=
globals
.
fs
.
file
(
'source'
)
..
writeAsStringSync
(
'main() {}'
);
final
File
sourcemap
=
globals
.
fs
.
file
(
'sourcemap'
)
..
writeAsStringSync
(
'{}'
);
final
File
metadata
=
globals
.
fs
.
file
(
'metadata'
)
..
writeAsStringSync
(
'{}'
);
final
File
manifest
=
globals
.
fs
.
file
(
'manifest'
)
..
writeAsStringSync
(
json
.
encode
(<
String
,
Object
>{
'/foo.js'
:
<
String
,
Object
>{
'code'
:
<
int
>[
0
,
source
.
lengthSync
()],
'sourcemap'
:
<
int
>[
0
,
2
],
'metadata'
:
<
int
>[
0
,
2
],
}}));
webAssetServer
.
write
(
source
,
manifest
,
sourcemap
,
metadata
);
test
(
'serves index.html when path is unknown'
,
()
=>
testbed
.
run
(()
async
{
const
String
htmlContent
=
'<html><head></head><body id="test"></body></html>'
;
final
Directory
webDir
=
globals
.
fs
.
currentDirectory
.
childDirectory
(
'web'
)
..
createSync
();
webDir
.
childFile
(
'index.html'
).
writeAsStringSync
(
htmlContent
);
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/bar
.js
'
)));
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/bar
/baz
'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
notFound
);
expect
(
response
.
statusCode
,
HttpStatus
.
ok
);
expect
(
await
response
.
readAsString
(),
htmlContent
);
}));
test
(
'serves default index.html'
,
()
=>
testbed
.
run
(()
async
{
...
...
@@ -333,13 +381,6 @@ void main() {
Platform:
()
=>
linux
,
}));
test
(
'Handles missing Dart files from filesystem'
,
()
=>
testbed
.
run
(()
async
{
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/foo.dart'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
notFound
);
}));
test
(
'serves asset files from in filesystem with known mime type'
,
()
=>
testbed
.
run
(()
async
{
final
File
source
=
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'build'
,
'flutter_assets'
,
'foo.png'
))
..
createSync
(
recursive:
true
)
...
...
@@ -397,20 +438,6 @@ void main() {
expect
(
etag
.
runes
,
everyElement
(
predicate
((
int
char
)
=>
char
<
255
)));
}));
test
(
'handles serving missing asset file'
,
()
=>
testbed
.
run
(()
async
{
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/assets/foo'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
notFound
);
}));
test
(
'handles serving unresolvable package file'
,
()
=>
testbed
.
run
(()
async
{
final
Response
response
=
await
webAssetServer
.
handleRequest
(
Request
(
'GET'
,
Uri
.
parse
(
'http://foobar/packages/notpackage/file'
)));
expect
(
response
.
statusCode
,
HttpStatus
.
notFound
);
}));
test
(
'serves /packages/<package>/<path> files as if they were '
'package:<package>/<path> uris'
,
()
=>
testbed
.
run
(()
async
{
final
Uri
expectedUri
=
packages
.
resolve
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment