概要

前回作ったHttpServerはどんなファイルを要求されても毎回同じメッセージを返しているだけだったが今回は要求されたHTMLファイルを返すところまで実装してみました。ただ、まじめにHTTPリクエストヘッダを解析していない点に注意してください。もし要求されたファイルが見つからなければHTTPステータスコード404を返しています。ちなみに今回のサンプルはJavaのファイルと同じディレクトリにwwwディレクトリが存在していてその中にHTMLファイルがあることを想定しています。今回のHTMLでは画像を含んだWEBページでは画像が表示できませんが次回のプログラムから画像に対応します。

ソースコード

import java.net.Socket;
import java.net.ServerSocket;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import java.io.PrintWriter;
import java.io.BufferedOutputStream;

import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.charset.StandardCharsets;

import java.io.IOException;

public class HttpServerSample{
    public static void main(String... args){
        //ポート12435でServerSocket作成
        try(var server = new ServerSocket(12435)){
            HttpServerSample.accept(server);
        }catch(IOException e){
            e.printStackTrace();
        }
    }

    private static void accept(ServerSocket server){
        while(true){
            //クライアントからの接続を待機する
            try(var socket = server.accept()){
                //クライアントから接続されたときの処理
                HttpServerSample.connectHttp(socket);
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    private static void connectHttp(Socket socket) throws IOException{
        try(
            var in = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
            var out = new PrintWriter(new BufferedOutputStream(socket.getOutputStream()), true);
        ){
            String line = in.readLine();

            if(line != null){
                var tokens = line.split(" ");
                var fileName = tokens.length == 3 ? tokens[1] : "index.html";

                if(fileName.equals("/")){
                    fileName = "index.html";
                }

                System.out.printf("Request FileName: %s\n", fileName);

                while((line = in.readLine()) != null){
                    System.out.println(line);

                    if(line.isEmpty()){
                        break;
                    }
                }

                HttpServerSample.printHTML(out, fileName);
            }
        }
    }

    private static void printHTML(PrintWriter out, String fileName) throws IOException{
        var path = Paths.get("www", fileName);

        //ファイルが見つかればHTMLとして返す(画像などは未対応)
        if(Files.exists(path)){
            out.println("HTTP/1.1 200 OK");
            out.println("Content-Type: text/html; charset=UTF-8");
            out.println();

            Files.lines(path).forEach(out::println);
        }else{
            //ファイルが見つからなければ404を返す
            out.println("HTTP/1.1 404 Not Found");
            out.println("Content-Type: text/html; charset=UTF-8");
            out.println();
            out.println("<html><title><head>404 Not Found</head></title><body><h1>404 Not Found</h1></body></html>");
            
            System.err.printf("%s is Not Found", path.toAbsolutePath().toString());
        }
    }
}

配置するHTMLの例

wwwディレクトリに以下の内容のHTMLを保存してみましょう。とりあえずファイル名はindex.htmlにしておきます。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Hello</title>
</head>
<body>
  <h1>サンプルページ</h1>
</body>
</html>