2013-09-10 2 views
-1

Я работаю над этим кодом, и по какой-то причине сервер не может открыть индексный файл, и я не могу понять, почему. Я проверил код других людей и не похоже, что есть разница.Почему мой сервер не открывает файлы?

Вот мой код:

require 'socket' 

class Server 

    def initialize (base, request, server_name, session, charset) 
    @base = base 
    @request = request 
    @charset = charset 
    @server_name = server_name 
    @session = session 
    serve() 
    end 
    def serve() 
    access_log() 
    getAddress() 
    @contentType = getContentType() 
    @session.print "HTTP/1.1 200 OK\r\nServer: #{@server_name}\r\nContent-Type: #{@contentType}; [email protected]{charset}\r\n\r\n" 
    getFile() 
    @base = nil 
    @request = nil 
    @server_name = nil 
    @contentType 
    @session.close 
    puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
    @session = nil 
    end 
    def access_log() 
    log = File.open(@base + "data/access_log.txt", "w") 
    log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{@session.peeraddr[2]}:#{@session.peeraddr[1]} #{@request}" unless log == nil 
    log.close 
    log = nil 
    end 
    def getAddress() 
    @src = @request 
    @src.gsub!(/GET /, '').gsub!(/ HTTP.*/, '') 
    @src.strip 
    @src = @base + "root" + @src 
    @src.gsub!('/', '\\') 
    end 
    def getContentType() 
    ext = nil 
    ext = File.extname(@src) 
    return "text/html" if ext == ".html" or ext == ".htm" 
    return "text/plain" if ext == ".txt" 
    return "text/css"  if ext == ".css" 
    return "image/jpeg" if ext == ".jpeg" or ext == ".jpg" 
    return "image/gif" if ext == ".gif" 
    return "image/bmp" if ext == ".bmp" 
    return "text/plain" if ext == ".rb" 
    return "text/xml"  if ext == ".xml" 
    return "text/xml"  if ext == ".xsl" 
    #return "image/x-icon" if ext == ".ico" or ext == ".icon" 
    return "text/html" 
    end 
    def getFile() 
     begin 
    if !File.exist?(@src) 
     puts "File: #{@src} could not be found" 
     if @contentType.include?("image") 
     file = File.open(@base + "root/server_files/broken_image.png", "r").each do |code| 
      @session.puts code 
     end 
     else 
     file = File.open(@base + "root/server_files/error404.html", "r").each do |code| 
      @session.puts code 
     end 
     end 
    else 
     puts "File #{@src} was opened" 
     file = File.open(@src, "r").each do |code| 
     @session.puts code 
     end 
    end 
     ensure 
    file.close unless file == nil 
     end 
    end 
end 

base = "C:\\Base\\" 
server_name = "Some Server" 
host = "localhost" 
port = 80 
charset = "UFT-8" 

server = TCPServer.new(host, port) 
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n" 

loop { 
    Thread.new(server.accept) do |session| 
    request = session.gets 
    puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}" 
    Server.new(base, request, server_name, session, charset) 
    end 
} 

p = gets.chomp 
server.close 
+1

Вы получаете сообщение об ошибке? Выполняется ли код как другой пользователь или есть разрешение на чтение файлов? –

+1

Вы должны дать нам немного больше, чем «Это не сработает. Вот мой код. Почему он сломан?» – benbot

+0

Я предлагаю вывести полное имя файла индекса (перед его открытием) на консоль, а затем посмотреть, существует ли этот файл или нет ... – rogerdpack

ответ

1

Есть проблемы с кодом. Я не знаю, вызвали ли они эту проблему, но достаточно запаха кода, который может помочь в следующих ошибках.

Не используйте имена методов CamelCase в Ruby. Мы используем snake_case.

require 'socket' 

class Server 

    def initialize(base, request, server_name, session, charset) 

    @base = base 
    @request = request 
    @charset = charset 
    @server_name = server_name 
    @session = session 

    serve() 

    end 

    def serve 

    access_log 
    get_address() 
    @content_type = get_content_type() 
    @session.print "HTTP/1.1 200 OK\r\nServer: #{@server_name}\r\nContent-Type: #{@content_type}; [email protected]{charset}\r\n\r\n" 
    get_file() 
    @content_type 
    @session.close 
    puts "Session Ended\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
    @base = @request = @server_name = @session = nil 

    end 

Я не знаю, почему у вас есть @content_type по своей линии до @session.close. Это не вызов метода, и не похоже, что он вернет что-либо на сервер или исходящий поток данных.

def access_log 

    File.open(File.join(@base, "data/access_log.txt"), "w") do |log| 
     log.puts "#{Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")} #{@session.peeraddr[2]}:#{@session.peeraddr[1]} #{@request}" 
    end 

    end 

Ruby's File.open принимает блок. Когда блок выходит из файла, файл будет автоматически закрыт. File.join - это правильный способ построения пути. Ruby знает о соответствующих ограничителях пути и будет автоматически использовать их, помогая сделать ваш код более переносимым.

def get_address 

    src = @request.gsub(/GET /, '').gsub(/ HTTP.*/, '').strip 
    @src = (@base + "root" + src).gsub('/', '\\') 

    end 

Вы делаете много gsub! без причины. Цепь их, объедините строку, сделайте окончательный gsub и двигайтесь дальше.

def get_content_type() 

    ext = File.extname(@src) 

    content_type = case ext 
        when /\.html?/ 
        "text/html" 
        when ".txt" 
        "text/plain" 
        when ".css" 
        "text/css" 
        when /\.jpe?g/ 
        "image/jpeg" 
        when ".gif" 
        "image/gif" 
        when ".bmp" 
        "image/bmp" 
        when ".rb" 
        "text/plain" 
        when /\.x[ms]l/ 
        "text/xml" 
        else 
        "text/html" 
        end 

    content_type 

    end 

Это сбивает с толку, чтобы иметь несколько returns в подпрограммой или способом, так что это очищает его. Окончательный content_type будет возвращен в результате вызова метода. Использование case/when позволяет использовать несколько тестов для каждого when, уменьшая шум линии.

def get_file() 
    begin 

     if !File.exist?(@src) 

     puts "File: #{@src} could not be found" 
     if @content_type["image"] 
      File.open(File.join(@base, "root", "server_files", "broken_image.png"), "rb") do |image| 
      @session.puts image.read 
      end 
     else 
      File.foreach(File.join(@base, "root", "server_files", "error404.html")) do |li| 
      @session.puts li 
      end 
     end 

     else 

     puts "File #{@src} was opened" 
     File.foreach(@src) do |li| 
      @session.puts li 
     end 

     end 

    rescue Exception => e 
     puts e.message 
    end 
    end 

Если вы хотите, чтобы прочитать двоичный файл, например, «broken_image.png», ВСЕГДА открыть его в двоичном режиме: "rb". В противном случае Ruby будет считать, что это нормально, чтобы преобразовать линейные окончания в собственный формат для ОС, что повредит данные. Кроме того, снова используйте блок-формы методов File, чтобы они автоматически закрывались. И, используйте File.join для переносимости. Когда вы читаете текстовый файл, используйте File.foreach, чтобы читать его по очереди, если вы не знаете, что он поместится в доступной памяти; «Слоение» ваших файлов - плохая форма, потому что она не масштабируема.

end 

base = "C:/Base/" 
server_name = "Some Server" 
host = "localhost" 
port = 80 
charset = "UFT-8" 

server = TCPServer.new(host, port) 
puts "~ Server hosted on #{host}:#{port} ~\n====================================\n" 

loop { 
    Thread.new(server.accept) do |session| 
    request = session.gets 
    puts "#{session.peeraddr[2]}:#{session.peeraddr[1]} #{request}" 
    Server.new(base, request, server_name, session, charset) 
    end 
} 

p = gets.chomp 
server.close 

Изменения кода доступны по адресу: https://gist.github.com/anonymous/6515451

+0

Спасибо, что действительно помогает – user2766296

Смежные вопросы