2013-04-09 6 views
7

私はJerseyのHttpServerFactoryを使用して、いくつかの休憩サービスをホストする単純な組み込みHttpserverを作成しています。私たちはちょうど小さな素早く軽いものが必要でした。私は同じ静的なhtmlページを同じサーバーインスタンス内にホストする必要があります。静的ハンドラをサーバーに追加する簡単な方法はありますか?私が使用できる事前定義されたハンドラはありますか?それはかなり一般的な仕事のように思えます、私はそれが既に存在する場合は、コードを書き直すことは嫌です。sunsを使って静的コンテンツを提供する方法単純なhttpserver

 server = HttpServerFactory.create(url); 
     server.setExecutor(Executors.newCachedThreadPool()); 
     server.createContext("/staticcontent", new HttpHandler() { 

      @Override 
      public void handle(HttpExchange arg0) throws IOException { 
       //What goes here? 

      } 
     }); 
     server.start(); 

答えて

6

それは誰もがあなたが任意の有効なJavaファイルパスに./wwwroot変更することができます ../../../要求することにより、ツリーを歩くことができないが、これは、トリックを行います。

static class MyHandler implements HttpHandler { 
     public void handle(HttpExchange t) throws IOException { 
      String root = "./wwwroot"; 
      URI uri = t.getRequestURI(); 
      System.out.println("looking for: "+ root + uri.getPath()); 
      String path = uri.getPath(); 
      File file = new File(root + path).getCanonicalFile(); 

      if (!file.isFile()) { 
       // Object does not exist or is not a file: reject with 404 error. 
       String response = "404 (Not Found)\n"; 
       t.sendResponseHeaders(404, response.length()); 
       OutputStream os = t.getResponseBody(); 
       os.write(response.getBytes()); 
       os.close(); 
      } else { 
       // Object exists and is a file: accept with response code 200. 
       String mime = "text/html"; 
       if(path.substring(path.length()-3).equals(".js")) mime = "application/javascript"; 
       if(path.substring(path.length()-3).equals("css")) mime = "text/css";    

       Headers h = t.getResponseHeaders(); 
       h.set("Content-Type", mime); 
       t.sendResponseHeaders(200, 0);    

       OutputStream os = t.getResponseBody(); 
       FileInputStream fs = new FileInputStream(file); 
       final byte[] buffer = new byte[0x10000]; 
       int count = 0; 
       while ((count = fs.read(buffer)) >= 0) { 
       os.write(buffer,0,count); 
       } 
       fs.close(); 
       os.close(); 
      } 
     } 
    } 
+0

私はこれをやりたくはありませんでしたが、他のソリューションの競合するjarファイルを実行した後に戻ってきました。私は "httpServer.createContext("/"、新しいMyHandler());"ハンドラをサーバーに追加する行です。 '/'はパスを開始するために必要です。 – Speck

+0

私は窓を使用しています。私は自分のD:ドライブをルートフォルダとして使用したい。なにか提案を。 –

+0

Java 7を起動するには、String mime = Files.probeContentType(file.toPath());を使用します。 – krishnakumarp

2

ここは安全なバージョンです。一般的なものに応じて、いくつかのMIMEタイプを追加することができます(またはyour platform has thatの場合は別のメソッドを使用します)。

package de.phihag.miniticker; 

import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.util.HashMap; 
import java.util.Map; 

import com.sun.net.httpserver.HttpExchange; 
import com.sun.net.httpserver.HttpHandler; 
import com.sun.net.httpserver.HttpServer; 

public class StaticFileHandler implements HttpHandler { 
    private static final Map<String,String> MIME_MAP = new HashMap<>(); 
    static { 
     MIME_MAP.put("appcache", "text/cache-manifest"); 
     MIME_MAP.put("css", "text/css"); 
     MIME_MAP.put("gif", "image/gif"); 
     MIME_MAP.put("html", "text/html"); 
     MIME_MAP.put("js", "application/javascript"); 
     MIME_MAP.put("json", "application/json"); 
     MIME_MAP.put("jpg", "image/jpeg"); 
     MIME_MAP.put("jpeg", "image/jpeg"); 
     MIME_MAP.put("mp4", "video/mp4"); 
     MIME_MAP.put("pdf", "application/pdf"); 
     MIME_MAP.put("png", "image/png"); 
     MIME_MAP.put("svg", "image/svg+xml"); 
     MIME_MAP.put("xlsm", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 
     MIME_MAP.put("xml", "application/xml"); 
     MIME_MAP.put("zip", "application/zip"); 
     MIME_MAP.put("md", "text/plain"); 
     MIME_MAP.put("txt", "text/plain"); 
     MIME_MAP.put("php", "text/plain"); 
    }; 

    private String filesystemRoot; 
    private String urlPrefix; 
    private String directoryIndex; 

    /** 
    * @param urlPrefix The prefix of all URLs. 
    *     This is the first argument to createContext. Must start and end in a slash. 
    * @param filesystemRoot The root directory in the filesystem. 
    *      Only files under this directory will be served to the client. 
    *      For instance "./staticfiles". 
    * @param directoryIndex File to show when a directory is requested, e.g. "index.html". 
    */ 
    public StaticFileHandler(String urlPrefix, String filesystemRoot, String directoryIndex) { 
     if (!urlPrefix.startsWith("/")) { 
      throw new RuntimeException("pathPrefix does not start with a slash"); 
     } 
     if (!urlPrefix.endsWith("/")) { 
      throw new RuntimeException("pathPrefix does not end with a slash"); 
     } 
     this.urlPrefix = urlPrefix; 

     assert filesystemRoot.endsWith("/"); 
     try { 
      this.filesystemRoot = new File(filesystemRoot).getCanonicalPath(); 
     } catch (IOException e) { 
      throw new RuntimeException(e); 
     } 

     this.directoryIndex = directoryIndex; 
    } 

    /** 
    * Create and register a new static file handler. 
    * @param hs The HTTP server where the file handler will be registered. 
    * @param path The path in the URL prefixed to all requests, such as "/static/" 
    * @param filesystemRoot The filesystem location. 
    *      For instance "/var/www/mystaticfiles/". 
    *      A request to "/static/x/y.html" will be served from the filesystem file "/var/www/mystaticfiles/x/y.html" 
    * @param directoryIndex File to show when a directory is requested, e.g. "index.html". 
    */ 
    public static void create(HttpServer hs, String path, String filesystemRoot, String directoryIndex) { 
     StaticFileHandler sfh = new StaticFileHandler(path, filesystemRoot, directoryIndex); 
     hs.createContext(path, sfh); 
    } 

    public void handle(HttpExchange he) throws IOException { 
     String method = he.getRequestMethod(); 
     if (! ("HEAD".equals(method) || "GET".equals(method))) { 
      sendError(he, 501, "Unsupported HTTP method"); 
      return; 
     } 

     String wholeUrlPath = he.getRequestURI().getPath(); 
     if (wholeUrlPath.endsWith("/")) { 
      wholeUrlPath += directoryIndex; 
     } 
     if (! wholeUrlPath.startsWith(urlPrefix)) { 
      throw new RuntimeException("Path is not in prefix - incorrect routing?"); 
     } 
     String urlPath = wholeUrlPath.substring(urlPrefix.length()); 

     File f = new File(filesystemRoot, urlPath); 
     File canonicalFile; 
     try { 
      canonicalFile = f.getCanonicalFile(); 
     } catch (IOException e) { 
      // This may be more benign (i.e. not an attack, just a 403), 
      // but we don't want the attacker to be able to discern the difference. 
      reportPathTraversal(he); 
      return; 
     } 

     String canonicalPath = canonicalFile.getPath(); 
     if (! canonicalPath.startsWith(filesystemRoot)) { 
      reportPathTraversal(he); 
      return; 
     } 

     FileInputStream fis; 
     try { 
      fis = new FileInputStream(canonicalFile); 
     } catch (FileNotFoundException e) { 
      // The file may also be forbidden to us instead of missing, but we're leaking less information this way 
      sendError(he, 404, "File not found"); 
      return; 
     } 

     String mimeType = lookupMime(urlPath); 
     he.getResponseHeaders().set("Content-Type", mimeType); 
     if ("GET".equals(method)) { 
      he.sendResponseHeaders(200, canonicalFile.length());    
      OutputStream os = he.getResponseBody(); 
      copyStream(fis, os); 
      os.close(); 
     } else { 
      assert("HEAD".equals(method)); 
      he.sendResponseHeaders(200, -1); 
     } 
     fis.close(); 
    } 

    private void copyStream(InputStream is, OutputStream os) throws IOException { 
     byte[] buf = new byte[4096]; 
     int n; 
     while ((n = is.read(buf)) >= 0) { 
      os.write(buf, 0, n); 
     } 
    } 

    private void sendError(HttpExchange he, int rCode, String description) throws IOException { 
     String message = "HTTP error " + rCode + ": " + description; 
     byte[] messageBytes = message.getBytes("UTF-8"); 

     he.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8"); 
     he.sendResponseHeaders(rCode, messageBytes.length); 
     OutputStream os = he.getResponseBody(); 
     os.write(messageBytes); 
     os.close(); 
    } 

    // This is one function to avoid giving away where we failed 
    private void reportPathTraversal(HttpExchange he) throws IOException { 
     sendError(he, 400, "Path traversal attempt detected"); 
    } 

    private static String getExt(String path) { 
     int slashIndex = path.lastIndexOf('/'); 
     String basename = (slashIndex < 0) ? path : path.substring(slashIndex + 1); 

     int dotIndex = basename.lastIndexOf('.'); 
     if (dotIndex >= 0) { 
      return basename.substring(dotIndex + 1); 
     } else { 
      return ""; 
     } 
    } 

    private static String lookupMime(String path) { 
     String ext = getExt(path).toLowerCase(); 
     return MIME_MAP.getOrDefault(ext, "application/octet-stream"); 
    } 
} 
関連する問題