具有 Crystal 的类似 WEBrick 的服务器
A WEBrick like server with Crystal
是否可以使用 Crystal 创建一个简单的 Web 服务器,可以服务 HTML、CSS 和 JS 页面?
我当前的代码是:
require "http/server"
Port = 8080
Mime = "text/html"
server = HTTP::Server.new([HTTP::ErrorHandler.new, HTTP::LogHandler.new]) do |context|
req = context.request
if req.method == "GET"
filename = File.join(Dir.current, "index.html")
context.response.content_type = Mime
context.response.content_length = File.size(filename)
File.open(filename) { |file| IO.copy(file, context.response) }
next
end
context.response.content_type = Mime
end
puts "\e[1;33mStarted Listening on Port #{Port}\e[0m"
server.listen(Port)
当我 运行 编译和 运行 程序时,它会初始化服务器,但有几个问题:
- 在 Firefox 浏览器的 "Inspect Element" 控制台中,我看到:
The stylesheet http://127.0.0.1:8080/styling.css was not loaded because its MIME type, "text/html", is not "text/css". 127.0.0.1:8080
The script from “http://127.0.0.1:8080/javascript.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type. 127.0.0.1:8080
SyntaxError: expected expression, got '<' javascript.js:1
服务器只显示index.html
的内容。
代码HTML、CSS和JS在我运行使用WEBrick或直接加载index.html到浏览器时完全有效。
- 无法从本地网络上的任何其他设备访问我的服务器。
您可能需要为此使用 HTTP::StaticFileHandler
。它提供本地目录中的文件。
- 在处理程序中,无论请求是什么,您总是读取文件
index.html
。这不行。
HTTP::Server#listen
在 127.0.0.1
上侦听,因此它只能从本地主机获得。为了可以从网络访问,您需要侦听网络上可用的地址。例如 server.listen("0.0.0.0", Port)
将监听所有接口。
非常感谢@Johannes Müller 解决了我的问题。在这里,我正在分享我想要的代码。
代码:
#!/usr/bin/env crystal
require "http/server"
# Get the Address
ADDR = (ARGV.find { |x| x.split(".").size == 4 } || "0.0.0.0").tap { |x| ARGV.delete(x) }
.split(".").map { |x| x.to_i { 0 } }.join(".")
# Get the Port
PORT = ARGV.find { |x| x.to_i { 0 } > 0 }.tap { |x| ARGV.delete(x) }.to_s.to_i { 8080 }
# Get the path
d = Dir.current
dir = ARGV[0] rescue d
path = Dir.exists?(dir) ? dir : Dir.exists?(File.join(d, dir)) ? File.join(d, dir) : d
listing = !!Dir.children(path).find { |x| x == "index.html" }
actual_path = listing ? File.join(path, "index.html") : path
server = HTTP::Server.new([
HTTP::ErrorHandler.new,
HTTP::LogHandler.new,
HTTP::StaticFileHandler.new(path, directory_listing: !listing)
]) do |context|
context.response.content_type = "text/html"
File.open(actual_path) { |file| IO.copy(file, context.response) }
end
puts "\e[1;33m:: Starting Sharing \e[38;5;75m#{actual_path}\e[1;31m on \e[38;5;226mhttp://#{ADDR}:#{PORT}\e[0m"
server.listen(::ADDR, ::PORT)
此代码查找 "index.html" 文件到提供的路径(默认 Dir.current),如果找到,它会将 index.html 文件共享到 IP 地址(默认 0.0.0.0 ) 和端口(默认 8080),否则它只共享当前目录内容。
运行:
crystal code.cr /tmp/ 5020 127.0.0.1
选项可以随机排列。例如:
crystal code.cr 5020 /tmp/ 127.0.0.1
或
crystal code.cr 5020 127.0.0.1 /tmp
这将启动服务器并共享 /tmp 目录。如果在 /tmp/ 目录中找到 index.html 文件,请求的浏览器将显示 index.html 内容,或者它的工作方式类似于 FTP(尽管它不是)。
编译和运行:
crystal build code.cr
./code [options]
如果您不想深入研究本机代码并且想要一个简单的解决方案 - 您应该使用任何提供文件服务器的框架。
您可以为此使用 Shivneri 框架。 Shivneri 内置文件服务器,易于配置 -
Shivneri.folders = [{
path: "/",
folder: File.join(Dir.current, "assets"),
}]
您可以根据需要添加任意数量的文件夹。每个文件夹都将映射到提供的路径。
有关更多信息,请阅读文档 - https://shivneriforcrystal.com/tutorial/file-server/
是否可以使用 Crystal 创建一个简单的 Web 服务器,可以服务 HTML、CSS 和 JS 页面?
我当前的代码是:
require "http/server"
Port = 8080
Mime = "text/html"
server = HTTP::Server.new([HTTP::ErrorHandler.new, HTTP::LogHandler.new]) do |context|
req = context.request
if req.method == "GET"
filename = File.join(Dir.current, "index.html")
context.response.content_type = Mime
context.response.content_length = File.size(filename)
File.open(filename) { |file| IO.copy(file, context.response) }
next
end
context.response.content_type = Mime
end
puts "\e[1;33mStarted Listening on Port #{Port}\e[0m"
server.listen(Port)
当我 运行 编译和 运行 程序时,它会初始化服务器,但有几个问题:
- 在 Firefox 浏览器的 "Inspect Element" 控制台中,我看到:
The stylesheet http://127.0.0.1:8080/styling.css was not loaded because its MIME type, "text/html", is not "text/css". 127.0.0.1:8080
The script from “http://127.0.0.1:8080/javascript.js” was loaded even though its MIME type (“text/html”) is not a valid JavaScript MIME type. 127.0.0.1:8080
SyntaxError: expected expression, got '<' javascript.js:1
服务器只显示index.html
的内容。
代码HTML、CSS和JS在我运行使用WEBrick或直接加载index.html到浏览器时完全有效。
- 无法从本地网络上的任何其他设备访问我的服务器。
您可能需要为此使用 HTTP::StaticFileHandler
。它提供本地目录中的文件。
- 在处理程序中,无论请求是什么,您总是读取文件
index.html
。这不行。 HTTP::Server#listen
在127.0.0.1
上侦听,因此它只能从本地主机获得。为了可以从网络访问,您需要侦听网络上可用的地址。例如server.listen("0.0.0.0", Port)
将监听所有接口。
非常感谢@Johannes Müller 解决了我的问题。在这里,我正在分享我想要的代码。
代码:
#!/usr/bin/env crystal
require "http/server"
# Get the Address
ADDR = (ARGV.find { |x| x.split(".").size == 4 } || "0.0.0.0").tap { |x| ARGV.delete(x) }
.split(".").map { |x| x.to_i { 0 } }.join(".")
# Get the Port
PORT = ARGV.find { |x| x.to_i { 0 } > 0 }.tap { |x| ARGV.delete(x) }.to_s.to_i { 8080 }
# Get the path
d = Dir.current
dir = ARGV[0] rescue d
path = Dir.exists?(dir) ? dir : Dir.exists?(File.join(d, dir)) ? File.join(d, dir) : d
listing = !!Dir.children(path).find { |x| x == "index.html" }
actual_path = listing ? File.join(path, "index.html") : path
server = HTTP::Server.new([
HTTP::ErrorHandler.new,
HTTP::LogHandler.new,
HTTP::StaticFileHandler.new(path, directory_listing: !listing)
]) do |context|
context.response.content_type = "text/html"
File.open(actual_path) { |file| IO.copy(file, context.response) }
end
puts "\e[1;33m:: Starting Sharing \e[38;5;75m#{actual_path}\e[1;31m on \e[38;5;226mhttp://#{ADDR}:#{PORT}\e[0m"
server.listen(::ADDR, ::PORT)
此代码查找 "index.html" 文件到提供的路径(默认 Dir.current),如果找到,它会将 index.html 文件共享到 IP 地址(默认 0.0.0.0 ) 和端口(默认 8080),否则它只共享当前目录内容。
运行:
crystal code.cr /tmp/ 5020 127.0.0.1
选项可以随机排列。例如:
crystal code.cr 5020 /tmp/ 127.0.0.1
或
crystal code.cr 5020 127.0.0.1 /tmp
这将启动服务器并共享 /tmp 目录。如果在 /tmp/ 目录中找到 index.html 文件,请求的浏览器将显示 index.html 内容,或者它的工作方式类似于 FTP(尽管它不是)。
编译和运行:
crystal build code.cr
./code [options]
如果您不想深入研究本机代码并且想要一个简单的解决方案 - 您应该使用任何提供文件服务器的框架。
您可以为此使用 Shivneri 框架。 Shivneri 内置文件服务器,易于配置 -
Shivneri.folders = [{
path: "/",
folder: File.join(Dir.current, "assets"),
}]
您可以根据需要添加任意数量的文件夹。每个文件夹都将映射到提供的路径。
有关更多信息,请阅读文档 - https://shivneriforcrystal.com/tutorial/file-server/