生成 Http 301 响应消息

Generating Http 301 Response Message

我正在尝试创建一个小型 Web 服务器并且能够生成 Http 响应消息 200、301 和 404。

我可以让 200 和 404 正常工作,但我在使用 301 时遇到问题。

当我尝试访问包含 "permanently moved" 的页面时,我的浏览器没有被重定向,我从 java 获得 java.lang.NullPointerException。

我确定代码是否应该是 301 的方式是检查客户端尝试访问的文件的字符串列表,以及他们尝试访问的原始文件是否已被移动,它将与新的 name/location 一起出现在列表中。因此,如果原始文件是 "index5.html" 并且它已被移动到 "index.html" 那么它们将在一个数组中并且 "index5.html" 将在 "index.html"[=11= 之前的索引 1 中]

我也在我自己的机器上测试这个,所以我使用 localhost 作为 URL 并使用端口 9012。

这是我的代码:

import java.io.*;
import java.net.*;
import java.util.*;


public final class HttpRequest implements Runnable {
    final static String CarrLine = "\r\n";
    Socket clientSocket;

    // A list of files that have been moved.
    // Even indexes (0, 2, 4, ...) are the original file names.
    // Odd indexes (1, 3, 5, ...) are where the files of previous indexes moved to.
    static String movedFiles[] = {"index5.html", "index.html", "page.html", "homepage.html"};

    // This sets the Httprequest object socket equal to
    // the socket the client comes in through
    public HttpRequest(Socket socket) throws Exception {
        this.clientSocket = socket;
    }

    // Here we define a new method that overwrites the
    // previous method in the Runnables class. This is done
    // so that when an Http request is attempted, and
    // something goes wrong, our whole web server will
    // not fail and crash.
    @Override
    public void run(){
        try {

            // This is where the method to actually start the Http request starts.
            requestProcessing();

        } catch (Exception ex) { System.out.print(ex); }
    } 


    // This is our main processing method to take in out Http request
    // and spit out a reponse header along with the requested data,
    // if there is any.
    void requestProcessing() throws Exception {
        Boolean fileExists = false;

        String CarrLine = "\r\n";
        String statusCode = null;
        String responseHeader = "HTTP/1.1 ";
        String fileName, line = null;
        String clientSentence = null;

        ArrayList<String> records = new ArrayList<String>();
        FileInputStream requestedFileStream = null;
        File requestedFile;

        // Starts input from client and establishes filters
        BufferedReader inFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

        // Starts output stream for output to client through socket
        DataOutputStream outToClient = new DataOutputStream(clientSocket.getOutputStream());

        /*
        // Reads in GET from client BufferedReader
        while ( (line = inFromClient.readLine()) != null){
            records.add(line);
            break;
        }*/
        clientSentence = inFromClient.readLine();

        // Parses and stores file name the client wants in a string
        fileName = parseGET(clientSentence);


        if (!existingFile(fileName)){

            // Here is where the 301 response message is generated and
            // retrieve the correct filename.
            if (hasMoved(fileName) != -1){
                statusCode = "301";
                responseHeader = responseHeader + statusCode + " Moved Permanently\n";
                responseHeader = responseHeader + "Location: localhost:9012/" 
                        + movedFiles[hasMoved(fileName)] + CarrLine;

            }

            // This generates the response header for the client
            // if the file the client is looking for is not there (404).
            else {
                statusCode = "404";
                responseHeader = responseHeader + statusCode + " Not Found: \n";
                responseHeader = responseHeader + "Content-Type: text/html" + CarrLine;
            }

        }

        // This generates the 200 status code response header
        // to send to the client saying the file was found.
        if (existingFile(fileName)) {
            statusCode = "200";
            responseHeader = responseHeader + statusCode + " OK: \n";
            responseHeader = responseHeader + "Content-Type: " + fileType(fileName) + CarrLine;
            requestedFileStream = openFileStream(fileName);
        }

        // Outputs the response message to the client through a data stream
        outToClient.writeBytes(responseHeader);
        outToClient.writeBytes(CarrLine);

        // If the file the client is requesting exists,
        // begin writing file out to client.
        if (existingFile(fileName)){
            fileWriteOut(requestedFileStream, outToClient);
            requestedFileStream.close();
        }

        else if(hasMoved(fileName) != -1){
            outToClient.writeBytes("File Moved");
        }

        // If the file the client is requesting does not exist,
        // return a 404 message.
        else {
            outToClient.writeBytes("404: File not found!");
        }

        // Closes all open streams and sockets to the client.
        inFromClient.close();
        outToClient.close();
        clientSocket.close();
    }

    // This parses the GET line from the client to get the filename the client is requesting
    String parseGET(String clientString){

        String temp[] = clientString.split(" /");
        temp = temp[1].split(" ");
        return temp[0];
    }

    // This is used to find the file the client is requesting.
    // It will return null if no file was found/opened.
    FileInputStream openFileStream(String file){
        FileInputStream fileStream = null;

        // Opening the file stream is in a try catch statment so that
        // incase there was no file, the program doesn't crash
        // and it'll alert the user on the console.
        try {
            fileStream = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            System.out.println(e);
            return null;
            }

        return fileStream;
    }

    // Determines the file type that is being sent to the client
    // and returns the appropriate string
    String fileType(String clientRequestFile){

        // If the file ends in .html or .htm, it will return "text/html"
        // so that it can be added to the response message.
        if (clientRequestFile.endsWith(".html") || clientRequestFile.endsWith(".htm")){
            return "text/html";
        }

        // If the file ends in .jpg, it will return "text/jpeg"
        // so that it can be added to the response message.
        if (clientRequestFile.endsWith(".jpg")){
            return "text/jpg";
        }

        // If the file ends in .css, it will return "text/css"
        // so that it can be added to the response message.
        if (clientRequestFile.endsWith(".css")){
            return "text/css";
        }

        // Returns this by default, if none of the above.
        return "application/octet-stream";
    }

    // This creates a 2k buffer and writes out
    // requested filed to the client.
    static void fileWriteOut(FileInputStream clientStream, OutputStream toClient) throws Exception{
        byte[] buffer = new byte[2048];
        int bytes = 0;

        while ((bytes = clientStream.read(buffer)) != -1){
            toClient.write(buffer, 0, bytes);
        }

    }

    // This determines whether or not a file that
    // the client has requested exists or not.
    // Returns a Boolean value.
    static Boolean existingFile(String fileName){
        File file = new File(fileName);

        if (file.exists() && !file.isDirectory()){
            return true;
        }
        return false;
    }


    // Determines if a file has been moved and if so,
    // returns the index of the NEW file. Else it
    // returns -1.
    static int hasMoved(String fileName){
        int i = 0;

        for (i = 0; i < movedFiles.length; i=i+2){
            if (movedFiles[i].equals(fileName)){
                return i+1;
            }
        }
        return -1;
    }
}

有人可以指出正确的方向来正确地做这件事吗?

谢谢!

好的,我明白了。

这是因为我试图在 301 响应消息中定义整个 "URL"。

所以应该是:

responseHeader = responseHeader + "Location: /" + movedFiles[hasMoved(fileName)] + CarrLine;

而不是:

responseHeader = responseHeader + "Location: localhost:9012/" + movedFiles[hasMoved(fileName)] + CarrLine;