Packages
livebook
0.2.0
0.19.8
0.19.7
0.19.6
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.6
0.18.5
0.18.4
0.18.3
0.18.2
0.18.1
0.18.0
0.17.3
0.17.2
0.17.1
0.17.0
0.16.4
0.16.3
0.16.2
0.16.1
0.16.0
0.15.5
0.15.4
0.15.3
0.15.2
0.15.1
0.15.0
0.14.7
0.14.6
0.14.5
0.14.4
0.14.3
0.14.2
0.14.1
0.14.0
0.14.0-rc.1
0.14.0-rc.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.1
0.12.0
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.3
0.9.2
0.9.1
0.9.0
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
Automate code & data workflows with interactive notebooks
Current section
Files
Jump to
Current section
Files
lib/livebook/content_loader.ex
defmodule Livebook.ContentLoader do
@moduledoc false
@doc """
Rewrite known URLs, so that they point to plain text file rather than HTML.
Currently the rewerites handle:
* GitHub files
* Gist files
"""
@spec rewrite_url(String.t()) :: String.t()
def rewrite_url(url) do
url
|> URI.parse()
|> do_rewrite_url()
|> URI.to_string()
end
defp do_rewrite_url(%URI{host: "github.com"} = uri) do
case String.split(uri.path, "/") do
["", owner, repo, "blob", hash | file_path] ->
path = Enum.join(["", owner, repo, hash | file_path], "/")
%{
uri
| path: path,
host: "raw.githubusercontent.com",
authority: "raw.githubusercontent.com"
}
_ ->
uri
end
end
defp do_rewrite_url(%URI{host: "gist.github.com"} = uri) do
case String.split(uri.path, "/") do
["", owner, hash] ->
path = Enum.join(["", owner, hash, "raw"], "/")
%{
uri
| path: path,
host: "gist.githubusercontent.com",
authority: "gist.githubusercontent.com"
}
_ ->
uri
end
end
defp do_rewrite_url(uri), do: uri
@doc """
Loads binary content from the given URl and validates if its plain text.
"""
@spec fetch_content(String.t()) :: {:ok, String.t()} | {:error, String.t()}
def fetch_content(url) do
case :httpc.request(:get, {url, []}, http_opts(), body_format: :binary) do
{:ok, {{_, 200, _}, headers, body}} ->
valid_content? =
case fetch_content_type(headers) do
{:ok, content_type} -> content_type in ["text/plain", "text/markdown"]
:error -> false
end
if valid_content? do
{:ok, body}
else
{:error, "invalid content type, make sure the URL points to live markdown"}
end
_ ->
{:error, "failed to download notebook from the given URL"}
end
end
defp fetch_content_type(headers) do
case Enum.find(headers, fn {key, _} -> key == 'content-type' end) do
{_, value} ->
{:ok,
value
|> List.to_string()
|> String.split(";")
|> hd()}
_ ->
:error
end
end
crt_file = CAStore.file_path()
crt = File.read!(crt_file)
pems = :public_key.pem_decode(crt)
ders = Enum.map(pems, fn {:Certificate, der, _} -> der end)
# Note: we need to load the certificates at compilation time,
# as we don't have access to package files in Escript.
@cacerts ders
defp http_opts() do
[
# Use secure options, see https://gist.github.com/jonatanklosko/5e20ca84127f6b31bbe3906498e1a1d7
ssl: [
verify: :verify_peer,
cacerts: @cacerts,
customize_hostname_check: [
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]
]
]
end
end