Search code examples
javahtmlsocketshttpserver

Locally hosted image isn't displaying on browser when hosting a HTTPSocket server


EDIT: Figured it out. I was using PrinterWriter to write the header and OutputStream to write the content. I used OutputStream to write the header and the content and the image loaded.

I'm creating a simple server in Java using ServerSocket. When I run the code and connect to the localhost site, it displays my html and css properly, but my locally hosted image doesn't display and the alt text is shown.

When I open the html file through firefox without the server, the image loads. I am 99% sure the file path is correct, as the other files i.e. my css file is retrieved correctly.

When linking directly to the bear (Warning: cute bear) in my html, the bear displays.

Any ideas? Thanks.

Here is my file layout: file layout

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

// Hosts an httpserver located in the directory ../website. Clients can connect to receive
// Specific page. If the page requested doesn't exist, serve index.html
public class HttpServer {
    // HttpServer object contains a ServerSocket object, representing the server, and an
    // ArrayList which contains the sockets connected
    private ServerSocket server_;
    private ArrayList<Socket> sockets_ = new ArrayList<>();
    // Starts the server and runs a while loop waiting for sockets to connect. If a socket
    // connects, serve the client the requested page or index.html
    public static void main(String[] args) throws IOException {
        HttpServer testServer = new HttpServer(8080);
        boolean cont = true;
        while(cont){
            Request newRequest = testServer.AcceptSocket();
            Response newResponse = testServer.generateResponse(newRequest);
            cont = testServer.Respond(newResponse);
        }
    }
    // HttpServer constructor that makes a server at the specified port
    public HttpServer(int port) throws IOException {
        server_ = new ServerSocket(port);
    }
    // Waits for a client socket to connect. Returns a Request object representing the
    // client's request
    public Request AcceptSocket() throws IOException {
        sockets_.add(server_.accept());
        return new Request(sockets_.get(sockets_.size()-1).getInputStream());
    }
    // Returns a Response object when given a Request object
    public Response generateResponse(Request newRequest) throws IOException {
        return new Response(new File("Resources" + newRequest.getPath_()));
    }
    // Writes out Response to the most recently connected client socket based on the given
    // Response object
    public boolean Respond(Response newResponse) throws IOException {
        try{
            OutputStream output = sockets_.get(sockets_.size()-1).getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);
            writer.println(newResponse.getHeader_());
            writer.print(newResponse.getResponse_());
            writer.flush();
            writer.close();
            sockets_.get(sockets_.size()-1).close();
            return true;
        }
        catch(FileNotFoundException e){
            return false;
        }

    }
}
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Scanner;
// Represents a server's response based to a client socket
public class Response {
    private String header_;
    private String response_;
    // Constructor that generates a response based on the requested file. If the file
    // doesn't exist, return the index
    public Response(File file) throws IOException {
        // If the file is "Resources", that means no index was entered and return index.html
        if(file.getName().equals("Resources")){
            file = new File("Resources/index.html");
        }
        System.out.println(file.toPath());
        // If the file doesn't exist or is directory, return 404
        if(!file.exists() || file.isDirectory()){
            header_ = "HTTP/1.1 404 Not Found\n";
            response_ = "404: file doesn't exist";
        } else{
            String contentType = "";
            try{
                contentType = Files.probeContentType(file.toPath());
            }
            catch(Exception e){
                System.out.println("IOException caught");
            }
            header_ = "HTTP/1.1 200 OK\nContent-Type: "+contentType+" \n\r\n";
            Scanner fileScan = new Scanner(file);
            StringBuilder responseText = new StringBuilder();
            while(fileScan.hasNextLine()){
                responseText.append(fileScan.nextLine());
            }
            response_ = responseText.toString();
            fileScan.close();
        }
    }
    public String getResponse_() {return response_;}
    public String getHeader_() { return header_;  }
}
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Scanner;
// Represents a client socket's request
public class Request {
    // Contains the method, path, protocol and a Hashtable representing the header
    private String method_;
    private String path_;
    private String protocol_;
    private Hashtable<String, String> header_;
    // Request constructor that makes a Request object based on the given InputStream given
    // by the client socket
    public Request(InputStream input){
        Scanner scanner = new Scanner(input);
        method_ = scanner.next();
        path_ = scanner.next();
        protocol_ = scanner.nextLine();
        Hashtable<String, String> header = new Hashtable<>();
        // Loops through the remaining user input and populates the header hashtable with
        // The first word and the corresponding value
        String nextLn = scanner.nextLine();
        while(!nextLn.equals("")){
            String firstWord = nextLn.substring(0, nextLn.indexOf(" "));
            header.put(firstWord, nextLn.substring(nextLn.indexOf(" ")));
            nextLn = scanner.nextLine();
        }
        header_ = header;
    }
    public String getMethod_() {
        return method_;
    }
    public String getPath_() {
        return path_;
    }
    public String getProtocol_() {
        return protocol_;
    }
    public Hashtable<String, String> getHeader_() {
        return header_;
    }
}
<!DOCTYPE html>


<html>
  <head>
    <title> Test webpage </title>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="styles.css" type="text/css">
  </head>
  <body>
    <h1 id="header1"> Spencer DeLange!?</h1>
    <h2> Tests below </h2>
    <p> Paragraph with tests </p>
    <a href="//www.google.com">Click to go to google.com</a>
    <div>
      <ul>
        <li> test </li>
    <li> test2</li>
    <li> test3</li>
      </ul>
      <ol>
    <li> ordered one</li>
    <li> ordered two</li>
    <li> ordered three</li>
      </ol>
    </div>
    
    <div class="bordered">
      <p>Bordered test paragraph </p>
    </div>

    <img alt = "bear" src="bear.jpg">

  </body>
</html>
├── MyHttpServer.iml
├── Resources
│   ├── README.md
│   ├── bear.jpeg
│   ├── bear.jpg
│   ├── index.html
│   └── styles.css
├── out
│   └── production
│       └── MyHttpServer
│           ├── HttpServer.class
│           ├── Request.class
│           └── Response.class
└── src
    ├── HttpServer.java
    ├── Request.java
    └── Response.java

5 directories, 12 files

Solution

  • The answer was to use the OutputStream write() function to write out the file that had been read. Use write() for both the header and the content of the file.

    My mistake was using PrintWriter for the header and write() for the content, which wouldn't work.