2

I'm trying to make a simple Http server.

But I have a little problem.

If my /www dir is in .jar file compilation, all workse perfect: code:

private static final String DEFAULT_FILES_DIR = "/www";
....
private String getURLFromHeader(String header) {
    //gettint url from header
    ....
    return DEFAULT_FILES_DIR + url;
}
....
System.out.println("Resources: " + url + "\n");
System.out.println("Result code: " + code + "\n");

for index.html I become: Resources: /www/index.html Result code: 200 -> all works.

But when I make so:

private static final String DEFAULT_FILES_DIR = "D:/.../.../.../www"; // absolute pass;
....
....

server says "No man, i don't know what are you wont from me"! =) and type: Resources: D:/.../.../.../www/index.html Result code: 404 -> file not found.

What it can be?

P.s. I tried to put private static final String DEFAULT_FILES_DIR = "D:\\...\\...\\...\\www"; but it wouldn't work!))))

Jason C
  • 38,729
  • 14
  • 126
  • 182
Andrew Evt
  • 3,613
  • 1
  • 19
  • 35
  • 1
    Can you show us how you are attempting to access this resource? Also the name of your method implies that it should return a URL, but "D:\..." is not a valid URL. File URLs start with the scheme "file://". You may wish to work with `java.net.URL` instead of `String` to enforce proper semantics. – Jason C Nov 05 '13 at 20:10
  • getURLFromHeader() returns String(`url`) with default dir_url + file_url. this `url` goes in another method an than in : `InputStream stream = HttpServer.class.getResourceAsStream(**url**);` and checks: `int code = (stream != null) ? 200 : 404;`. Or what do you want to see? I can show full code, if it's necessary. – Andrew Evt Nov 05 '13 at 20:18

1 Answers1

10

You are using Class.getResourceAsStream() to load the resource. This uses the class loader to load the resource and it can only load paths inside the current class path. It can't load arbitrary local files.

What you should do is use Class.getResourceAsStream() for resources in the class path, and use a basic FileInputStream for resources in the file system.

You will have to have a way to differentiate between the two. Exactly how you implement this depends on your requirements. You have many options, a few are:

  • Attempt to load with getResourceAsStream(), and if it fails, use a FileInputStream. This is a bit sloppy but may work for you. The caveat is you run the risk of mistakenly loading a local file when you meant to load a resource if the resource path was inadvertently incorrect but matches a local file.
  • Treat strings that start with "D:" as a file. This is also a bit sloppy and could complicate handling of files in other locations or relative file paths, but it is very simple and may work for your application.
  • Use a properly formed java.net.URL, and if the scheme type is "file", treat it as a local file.
  • Abstract this behind some resource loader interface that you construct based on the type of the resource that you know ahead of time. For example (handle exceptions as you see fit):

    interface ResourceLoader { 
        public InputStream getInputStream (); 
    }
    
    class ClassResourceLoader implements ResourceLoader {
        private final String resource;
        public ClassResourceLoader (String resource) { 
            this.resource = resource; 
        }
        @Override public InputStream getInputStream () { 
            return HttpServer.class.getResourceAsStream(resource);
        } 
    }
    
    class FileResourceLoader implements ResourceLoader {
        private final String resource;
        public FileResourceLoader (String resource) { 
            this.resource = resource; 
        }
        @Override public InputStream getInputStream () { 
            try {
                return new FileInputStream(resource);
            } catch (Exception x) {
                return null; 
            }
        } 
    }
    
    private ResourceLoader getResourceLoaderFromHeader (String header) {
        return ...; // whatever is appropriate.
    }
    

You have a lot of choices but the take home point is: You cannot load local file resources with Class.getResourceAsStream() and you will have to handle the two cases differently, in any way you see fit.

Jason C
  • 38,729
  • 14
  • 126
  • 182