Skip to content

Commit 3353156

Browse files
committed
Fix posit-dev#1601: Force text/javascript for .js files
1 parent 2c6bb01 commit 3353156

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3131

3232
* `ui.notification_show(duration=None)` now persists the notification until the app user closes it. (#1577)
3333

34-
### Bug fixes
34+
* Some copies of Windows 10 have registry entries mapping .js files to content type "text/plain", which was causing all sorts of problems for browsers.
3535

3636
### Deprecations
3737

shiny/_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ def guess_mime_type(
8282
"""
8383
# Note that in the parameters above, "os.PathLike[str]" is in quotes to avoid
8484
# "TypeError: 'ABCMeta' object is not subscriptable", in Python<=3.8.
85+
if url:
86+
# Work around issue #1601, some installations of Windows 10 return text/plain
87+
# as the mime type for .js files
88+
_, ext = os.path.splitext(os.fspath(url))
89+
if ext.lower() in [".js", ".mjs", ".cjs"]:
90+
return "text/javascript"
8591
return mimetypes.guess_type(url, strict)[0] or default
8692

8793

shiny/http_staticfiles.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
from __future__ import annotations
1313

1414
import re
15+
from typing import Any
16+
17+
from . import _utils
1518

1619
__all__ = (
1720
"StaticFiles",
@@ -24,13 +27,32 @@
2427

2528
if "pyodide" not in sys.modules:
2629
# Running in native mode; use starlette StaticFiles
30+
import os
2731

2832
import starlette.responses
2933
import starlette.staticfiles
3034

31-
StaticFiles = starlette.staticfiles.StaticFiles # type: ignore
3235
FileResponse = starlette.responses.FileResponse # type: ignore
3336

37+
# Wrapper for StaticFiles to fix .js content-type issues on Windows 10 (see #1601)
38+
class StaticFiles(starlette.staticfiles.StaticFiles): # type: ignore
39+
def file_response(
40+
self,
41+
full_path: str | os.PathLike[str],
42+
*args: Any,
43+
**kwargs: Any,
44+
) -> starlette.responses.Response:
45+
resp = super().file_response(full_path, *args, **kwargs)
46+
if resp.headers["content-type"].startswith("text/plain"):
47+
correct_type = _utils.guess_mime_type(full_path)
48+
resp.headers["content-type"] = (
49+
f"{correct_type}; charset={resp.charset}"
50+
if correct_type.startswith("text/")
51+
else correct_type
52+
)
53+
resp.media_type = correct_type
54+
return resp
55+
3456
else:
3557
# Running in wasm mode; must use our own simple StaticFiles
3658

@@ -43,8 +65,6 @@
4365
from starlette.responses import PlainTextResponse
4466
from starlette.types import Receive, Scope, Send
4567

46-
from . import _utils
47-
4868
class StaticFiles:
4969
dir: pathlib.Path
5070
root_path: str

0 commit comments

Comments
 (0)