LoginSignup
0
0

More than 5 years have passed since last update.

socketでhttpサーバっぽいものを作ってみたかった

Last updated at Posted at 2016-12-10

はじめに

HTTPサーバの仕組みを理解するために,HTTP用のサーバアプリやライブラリを使わずにTCPレベルのSocketを使ってHTTPサーバもどきを作ってみた
勉強用なので簡単な機能しかとりあえずつけてません
※以下のソースコードは脆弱性満載なので使用の際のトラブル等は全て自己責任でお願いします

ソースコード

httpserver.rb
require "socket"

plane_ext = ["html","htm","txt"]
binary_ext = ["ico","jpg","png","gif"]
permited_ext = plane_ext + binary_ext

s = TCPServer.open(8080)

while true
  puts "Server Ready..."
  client = s.accept

  puts "Accept HTTP Message"

  msg=[]
  msg_hash=Hash.new

  request_msg = client.gets
  request_msg = request_msg.chomp.split(" ") if request_msg!=nil
  redo if request_msg==nil

  while str=client.gets
    if str!=nil
      break if (str.chomp) == "" 
      str.chomp!
      msg << str
      buf=str.split(": ")
      msg_hash[buf[0]] = buf[1]
    end
  end

  puts "======== message ========="
  puts request_msg.join(" ") if request_msg != nil
  puts "======== message ========="
  puts msg if msg != nil
  puts "=========================="

  sleep(1)

  begin
    filename= request_msg[1]
    filename+="index.html" if filename[-1]=="/"         # add "index.html"
    while filename.sub!(/(\/\w*)(\/\.\.)/,"") do end    # remove .. from filename
    filename[0]=""                                      # remove "/" on the first word
    ext = filename.match(/\.([\w\.]*)/)[1]              # get extemsion name from the filename
    puts "filename = #{filename}"
    puts "extension = [#{ext}]"

    if filename[0,2] != ".." && permited_ext.include?(ext)
      if plane_ext.include?(ext)
        html = IO.read(filename)
      elsif binary_ext.include?(ext)
        html = IO.binread(filename)
      end
      client.puts "HTTP/1.1 200 OK"
      client.puts ""
      client.puts html
    else
      client.puts "HTTP/1.1 403 Forbidden"
      client.puts ""
    end
  rescue Errno::ENOENT => e
    client.puts "HTTP/1.1 404 Not Found"
    client.puts ""
  end

  client.close
end

ソースコード解説

  • ソケットが繋がったらrequest_msgに最初の[リクエスト,パス,バージョン]が入ります
  • その他のヘッダ部分はmsgとmsg_hashに入れます
  • 改行のみのデータが来たら読み込みを停止します
  • request_msgのパスを"/"で終われば"index.html"を付加して,最初の"/"を消して相対パスにします
  • 対応するデータを探し,開けなければ「404」,開ければ「200」と「改行」,「データ」を送ります
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0