# Building a Simple Web Server with Ruby 2.0+ (Part 2)

DevFeed: [Building a Simple Web Server with Ruby 2.0+ (Part 2)](<https://devfeed.tech/articles/building-a-simple-web-server-with-ruby-2-0-part-2-21046.md>)

Original publisher: [Read original article](<https://jakeyesbeck.com/2015/10/18/building-a-simple-web-server-with-ruby-2-part-2/>)

Published: 2015-10-18T12:00:00Z

Content type: tutorial

Language: en

Sources: [Jake Yesbeck](<https://devfeed.tech/sources/jake-yesbeck.md>)

Topics: [Ruby](<https://devfeed.tech/topics/ruby.md>), [HTTP](<https://devfeed.tech/topics/http.md>), [servers](<https://devfeed.tech/topics/servers.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [building](<https://devfeed.tech/tags/building.md>), [code](<https://devfeed.tech/tags/code.md>), [curl](<https://devfeed.tech/tags/curl.md>), [fetch](<https://devfeed.tech/tags/fetch.md>), [files](<https://devfeed.tech/tags/files.md>), [http](<https://devfeed.tech/tags/http.md>), [ruby](<https://devfeed.tech/tags/ruby.md>), [server](<https://devfeed.tech/tags/server.md>), [web](<https://devfeed.tech/tags/web.md>)

## AI overview

This tutorial extends a simple Ruby 2.0+ web server to serve files over HTTP. It explains parsing request paths, removing query parameters, restricting file access to a server root, handling missing files, preventing directory traversal, and mapping file extensions to content types.

## Source excerpt

In a previous post, a very simple Ruby server was created to listen to HTTP requests. While great for a first step, this example server does nothing more than respond with "Hello World". Greetings are nice and polite, but I think we can do better. Pro-filing A reasonable feature for this simple server is the ability to serve files. When retrieving files, the server must remain secure, only serving files that should be readable by clients. Additionally, if a requested file does not exist, the server should make the client aware. Since a request can have multiple parts, the server will need to parse out the noise from the desired file. For instance, if the request looks like /path/to/my_file.html?query=params&are=cool, the server should remove all query parameters and search for my_file.html nested within the /path/to/ directory. With an incoming request: GET /path/to/my_file.html?query=params&are=cool HTTP/1.1 A simple file fetching method might look like: require 'uri' SEVER_ROOT_DIR = '/var/www' def fetch_file(request_string) request_parts = request_string.split(' ') # Remove query params and HTTP verb, version path = URI(request_parts[1]).path full_path = File.join(SERVER_ROOT_DIR, path) File.open(full_path) if File.file?(full_path) end Given a request string input (from request.gets in the existing code), this method returns an instance of File if it can find the requested file or nil if it does not exist. The SERVER_ROOT_DIR is used to ensure the file lookup is centralized to where the server expects the files to be. Putting it all together, the server can now fetch and return files that exist. require 'socket' require 'uri' SERVER_ROOT_DIR = '/var/www' def fetch_file(request_string) request_parts = request_string.split(' ') path = URI(request_parts[1]).path full_path = File.join(SERVER_ROOT_DIR, path) File.open(full_path) if File.file?(full_path) end server = TCPServer.new(8080) loop do Thread.new(socket.accept) do |request| request_string = request.gets file_t