invicnaper/MWF

View on GitHub
Tools/mwf_server/mwf_server.rb

Summary

Maintainability
A
35 mins
Test Coverage
=begin
 _   _  _ _ _  ___ 
| \_/ || | | || __|
| \_/ || V V || _| 
|_| |_| \_n_/ |_|  

@author : naper
@description : c++ web framework

GNU LESSER GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.


  This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.

  0. Additional Definitions.

  As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.

  "The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.

  An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.

  A "Combined Work" is a work produced by combining or linking an
Application with the Library.  The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
=end

require 'socket'
require 'uri'
require File.expand_path('../Console/rf.console',__FILE__)
require File.expand_path('../Utils/error_message',__FILE__)

# Files will be served from this directory
#will be /var/mww/
WEB_ROOT = '/var/mww'

IP_SERVER = "127.0.0.1"
PORT_SERVER = 9090


# Map extensions to their content type
CONTENT_TYPE_MAPPING = {
  'html' => 'text/html',
  'htm' => 'text/html',
  'mw' => 'application/octet-stream',
  'txt' => 'text/plain',
  'css' => 'text/css',
  'png' => 'image/png',
  'js' => 'application/javascript',
  'jpg' => 'image/jpeg'
}

# Treat as binary data if content type cannot be found
DEFAULT_CONTENT_TYPE = 'application/octet-stream'

def content_type(path)
  ext = File.extname(path).split(".").last
  CONTENT_TYPE_MAPPING.fetch(ext, DEFAULT_CONTENT_TYPE)
end

# This helper function parses the Request-Line and
# generates a path to a file on the server.

def requested_file(request_line)
  request_uri  = request_line.split(" ")[1]
  path         = URI.unescape(URI(request_uri).path)

  clean = []

  # Split the path into components
  parts = path.split("/")

  parts.each do |part|
    # skip any empty or current directory (".") path components
    next if part.empty? || part == '.'
    # If the path component goes up one directory level (".."),
    part == '..' ? clean.pop : clean << part
  end

  # return the web root joined to the clean path
  File.join(WEB_ROOT, *clean)
end

Console.header()
Console.print_action("Starting web server in #{IP_SERVER}:#{PORT_SERVER}")
server = TCPServer.new(IP_SERVER, PORT_SERVER)

begin

loop do
  socket       = server.accept
  request_line = socket.gets

  STDERR.puts request_line

  path = requested_file(request_line)
  path = File.join(path, 'index.html') if File.directory?(path)

  if File.exist?(path) && !File.directory?(path)
    Console.print_action("Opening #{path}")
    if(File.extname(path) == ".mw")
      #exec mw file as cgi bin
      output = IO.popen("#{path} >> tmp/__#{File.basename(path)}.txt")
      File.open("tmp/__#{File.basename(path)}.txt", "rb") do |file|
        socket.print "HTTP/1.1 200 OK\r\n" +
                   "Content-Type: text/html\r\n" +
                   "Content-Length: #{file.size}\r\n" +
                   "Connection: close\r\n"

        socket.print "\r\n"
        IO.copy_stream(file, socket)
        #delete tmp file
    end
  else
    File.open(path, "rb") do |file|
      socket.print "HTTP/1.1 200 OK\r\n" +
                   "Content-Type: #{content_type(file)}\r\n" +
                   "Content-Length: #{file.size}\r\n" +
                   "Connection: close\r\n"

      socket.print "\r\n"

      # write the contents of the file to the socket
      IO.copy_stream(file, socket)
    end
    end
  else
    Console.print_error("File not found")
    
    # respond with a 404 error code to indicate the file does not exist
    socket.print "HTTP/1.1 404 Not Found\r\n" +
                 "Content-Type: text/html\r\n" +
                 "Content-Length: #{NOTFOUND.show(path, IP_SERVER,PORT_SERVER).size}\r\n" +
                 "Connection: close\r\n"

    socket.print "\r\n"
    socket.print NOTFOUND.show(path, IP_SERVER,PORT_SERVER)
  end

  socket.close
end

rescue Exception => e 
  Console.print_error("Mwf server will be closed , #{e}")
end