fs - simple file server

Check-in [87b77ab4de]
Login

Check-in [87b77ab4de]

Overview
Comment:Serve index.html files correctly.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 87b77ab4de07524cbd4ee291570b7b464259f6e4346b2249f0dcfb7933317be8
User & Date: marka on 2025-08-15 07:04:49.792
Other Links: manifest | tags
Context
2025-08-15
13:44
Use Crystal MIME library for determining content-type. check-in: e81f9f06dd user: marka tags: trunk
07:04
Serve index.html files correctly. check-in: 87b77ab4de user: marka tags: trunk
02:26
First checkin. check-in: 0ec0ee863c user: marka tags: trunk
Changes
Modified src/fs.cr from [ce44d3a1f8] to [ff1867bb3f].
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109

110


111
112

113
114
115
116
117
118
119
120







121
122
123
124
125
126
127
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102
103
104

105
106
107
108
109
110

111
112
113
114
115
116
117
118
119
120



121
122
123
124
125
126
127
128
129
130
131
132
133
134







+







-



-
+




+
-
+
+


+





-
-
-
+
+
+
+
+
+
+







end

# Simple HTTP server for static files.

class Server
  def initialize(config : Config)
    @config = config
    @root = config.root
    @server = uninitialized HTTP::Server
  end

  def process_request(context : HTTP::Server::Context)
    request = context.request
    request_path = request.path
    method = request.method
    root = @config.root

    MyLog.debug "process_request: got path #{request_path}, method #{method}"

    path = File.join(root, request_path)
    path = File.join(@root, request_path)
    if Dir.exists?(path)
      path = File.join(path, "index.html")
    end
    if File.exists?(path)
      content_type = `file -b --mime-type #{path}`.strip
      context.response.content_type = `file -b --mime-type #{path}`.strip
      context.response.content_type = content_type
      MyLog.info "Serving #{path}, content type #{content_type}"
      File.open(path) { |file| IO.copy(file, context.response) }
    else
      MyLog.error "No such file #{path}"
      context.response.respond_with_status(404, "No such file #{request_path}")
    end
  end

  def start
    @server = HTTP::Server.new do |context|
      process_request(context)
    end
    @server = HTTP::Server.new([
      HTTP::ErrorHandler.new,
      HTTP::LogHandler.new,
      HTTP::StaticFileHandler.new(@root, directory_listing: false)
      ]) do |context|
        process_request(context)
      end

    if @server
      address = @server.bind_tcp @config.host, @config.port
      puts "Listening on http://#{address}"

      # If SSL is specified, set that up.  If you have Apache
      # available, it's probably better to NOT let fs handle