Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serving files from the content API #225

Closed
oeway opened this issue May 7, 2020 · 4 comments
Closed

Serving files from the content API #225

oeway opened this issue May 7, 2020 · 4 comments

Comments

@oeway
Copy link

oeway commented May 7, 2020

As discussed with @Zsailer , the current get content api returns a json object which requires extra parsing in order to be used.

One thing we want to have in ImJoy is an endpoint that can serve the files directly with the correct MIME type in the Content-Type header so the browser can render these files directly, like the /view endpint from the notebook(but it doesn't always give the correct mime type).

I think I can build a server extension for it, but definitely nice to have it built-in with the content api.

@Zsailer
Copy link
Member

Zsailer commented May 14, 2020

Pinging @saulshanabrook and @telamonian. They've been thinking about the future of the contents API quite a bit, so I'd like to loop them in here.

@saulshanabrook
Copy link
Contributor

Sounds generally sensible to me on another endpoint.

@krassowski
Copy link
Collaborator

How would that differ from existing /files/ endpoint?

class FilesHandler(JupyterHandler):
"""serve files via ContentsManager
Normally used when ContentsManager is not a FileContentsManager.
FileContentsManager subclasses use AuthenticatedFilesHandler by default,
a subclass of StaticFileHandler.
"""
@property
def content_security_policy(self):
# In case we're serving HTML/SVG, confine any Javascript to a unique
# origin so it can't interact with the notebook server.
return super(FilesHandler, self).content_security_policy + "; sandbox allow-scripts"
@web.authenticated
def head(self, path):
self.get(path, include_body=False)
self.check_xsrf_cookie()
return self.get(path, include_body=False)
@web.authenticated
async def get(self, path, include_body=True):
# /files/ requests must originate from the same site
self.check_xsrf_cookie()
cm = self.contents_manager
if await ensure_async(cm.is_hidden(path)) and not cm.allow_hidden:
self.log.info("Refusing to serve hidden file, via 404 Error")
raise web.HTTPError(404)
path = path.strip("/")
if "/" in path:
_, name = path.rsplit("/", 1)
else:
name = path
model = await ensure_async(cm.get(path, type="file", content=include_body))
if self.get_argument("download", False):
self.set_attachment_header(name)
# get mimetype from filename
if name.lower().endswith(".ipynb"):
self.set_header("Content-Type", "application/x-ipynb+json")
else:
cur_mime = mimetypes.guess_type(name)[0]
if cur_mime == "text/plain":
self.set_header("Content-Type", "text/plain; charset=UTF-8")
elif cur_mime is not None:
self.set_header("Content-Type", cur_mime)
else:
if model["format"] == "base64":
self.set_header("Content-Type", "application/octet-stream")
else:
self.set_header("Content-Type", "text/plain; charset=UTF-8")
if include_body:
if model["format"] == "base64":
b64_bytes = model["content"].encode("ascii")
self.write(decodebytes(b64_bytes))
elif model["format"] == "json":
self.write(json.dumps(model["content"]))
else:
self.write(model["content"])
self.flush()

I now it is not a part of the contents API, but would it be a good idea to include it in the documentation?

Zsailer added a commit to Zsailer/jupyter_server that referenced this issue Nov 18, 2022
* add contributing docs

* add some local/remote docs
@blink1073
Copy link
Contributor

Closing as answered, the documentation issue is tracked in #298

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants