/* http-base - Extensions to jdk.httpserver Copyright (C) 2021 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.uhilger.httpserver.base.handler; import de.uhilger.httpserver.base.HttpResponder; import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import de.uhilger.httpserver.base.HttpHelper; import de.uhilger.httpserver.base.actor.FileActor; import java.io.File; import java.io.IOException; import java.util.logging.Logger; /** * Die Klasse FileHandler dient zur Auslieferung von Dateiinhalten über * HTTP. * * Für das Streaming über HTTP wird die Auslieferung von Teilinhalten * mit dem Accept-Ranges-Header angeboten und via Range-Header unterstützt. * (vgl. https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) * * @author Ulrich Hilger * @version 1, 03.06.2021, (seit 25. März 2021) */ public class FileHandler implements HttpHandler { /* Der Logger fuer diesen FileHandler */ private static final Logger logger = Logger.getLogger(FileHandler.class.getName()); /* Headernamen */ public static final String RANGE_HEADER = "Range"; public static final String CONTENT_RANGE_HEADER = "Content-Range"; //public static final String ACCEPT_RANGES_HEADER = "Accept-Ranges"; //public static final String LAST_MODIFIED_DATE_HEADER = "Last-Modified"; public static final String CONTENT_TYPE = "Content-Type"; public static final String CONTENT_LENGTH = "Content-Length"; /* Statuscodes */ public static final int SC_OK = 200; public static final int SC_PARTIAL_CONTENT = 206; public static final int SC_FORBIDDEN = 403; public static final int SC_NOT_FOUND = 404; public static final int SC_METHOD_NOT_ALLOWED = 405; public static final int SC_UNPROCESSABLE_ENTITY = 422; /* String Konstanten */ //public static final String STR_BYTES = "bytes"; public static final String STR_SLASH = "/"; public static final String STR_BLANK = " "; public static final String STR_DASH = "-"; public static final String STR_COMMA = ","; public static final String STR_DOT = "."; //public static final String STR_NOT_FOUND = " not found."; //public static final String LM_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz"; public static final String RANGE_PATTERN = "[^\\d-,]"; public static final String WELCOME_FILE = "index.html"; /* Ablageort fuer Webinhalte */ //protected final String fileBase; public static final String ATTR_FILE_BASE = "fileBase"; public static final String ATTR_WELCOME_FILES = "welcomeFiles"; /** * Ein neues Objekt der Klasse FileHandler erzeugen * * @param absoluteDirectoryPathAndName der absolute Pfad und Name des * Ordners im Dateisystem, der die Inhalte enthaelt, die von diesem * Handler ausgeliefert werden sollen */ /* public FileHandler(String absoluteDirectoryPathAndName) { this.fileBase = absoluteDirectoryPathAndName; } */ /** * Die Datei ermitteln, die sich aus dem angefragten URL ergibt, prüfen, * ob die Datei existiert und den Inhalt der Datei abhängig davon, ob ein * Range-Header vorhanden ist, ganz oder teilweise ausliefern. * * @param e das Objekt mit Methoden zur Untersuchung der Anfrage sowie zum * Anfertigen und Senden der Antwort * @throws IOException falls etwas schief geht entsteht dieser Fehler */ @Override public void handle(HttpExchange e) throws IOException { String fName = new HttpHelper().getFileName(e); if (fName.startsWith(STR_DOT)) { HttpResponder fs = new HttpResponder(); fs.sendNotFound(e, fName); } else { Headers headers = e.getRequestHeaders(); if (headers.containsKey(RANGE_HEADER)) { FileActor fa = new FileActor(); fa.serveFileParts(e, new File(e.getHttpContext().getAttributes().get(ATTR_FILE_BASE).toString(), fName)); } else { HttpResponder fs = new HttpResponder(); File file = new File(e.getHttpContext().getAttributes().get(ATTR_FILE_BASE).toString(), fName); if (fName.length() < 1 || fName.endsWith(STR_SLASH)) { HttpHelper helper = new HttpHelper(); File welcomeFile = helper.tryWelcomeFiles(e, fName); if(welcomeFile != null) { file = welcomeFile; } } fs.serveFile(e, file); } } } /** * Den Namen der gewünschten Datei aus der HTTP-Anfrage ermitteln * * @param e das Objekt mit Methoden zur Untersuchung der Anfrage sowie zum * Anfertigen und Senden der Antwort * @return Name der gewünschten Datei */ /* public String getFileName(HttpExchange e) { String ctxPath = e.getHttpContext().getPath(); String uriPath = e.getRequestURI().getPath(); logger.info(uriPath); return uriPath.substring(ctxPath.length()); } */ }